WIP Crook recipes

This commit is contained in:
thedarkcolour 2024-02-08 22:32:52 -08:00
parent ffe32fe3ac
commit 40e6896135
37 changed files with 1170 additions and 52 deletions

View File

@ -5,7 +5,7 @@ plugins {
id 'org.spongepowered.mixin' version '0.7.+'
}
version = '1.20'
version = '1.21'
group = 'thedarkcolour.exdeorum'
base {
archivesName = 'exdeorum'

View File

@ -1,3 +1,11 @@
## Ex Deorum 1.21
- Added Jade compatibility
- Added partial compatibility with Roughly Enough Items to hide compat blocks for mods that aren't installed (use REI Plugin Compatibilities mod to gain full compatibility with Ex Deorum)
- Added configurable sifting interval to limit speed of sifting by hand in order to curb the speed of autoclickers on sieves. (PR #47 by CPearl0)
- Added Chinese translation (PR #45 by CPearl0)
- Infested leaves string drop rate can now be configured in the server config.
- Fixed dedicated server crash when using Mycelium Spores to convert a cow into a Mooshroom (PR #44 by CPearl0)
## Ex Deorum 1.20
- Added Mechanical Hammer, a machine that uses FE to hammer blocks automatically. Uses 20 FE a tick by default and takes 200 ticks (10 seconds) to hammer an item with a hammer that has no efficiency.
- Fixed network bug when joining a server (PR #43 by CPearl0)

BIN
logs/debug-1.log.gz Normal file

Binary file not shown.

BIN
logs/debug-2.log.gz Normal file

Binary file not shown.

BIN
logs/debug-3.log.gz Normal file

Binary file not shown.

204
logs/debug.log Normal file
View File

@ -0,0 +1,204 @@
[08Feb2024 13:05:36.188] [main/DEBUG] [io.netty.util.internal.logging.InternalLoggerFactory/]: Using SLF4J as the default logging framework
[08Feb2024 13:05:36.196] [main/DEBUG] [io.netty.util.ResourceLeakDetector/]: -Dio.netty.leakDetection.level: simple
[08Feb2024 13:05:36.196] [main/DEBUG] [io.netty.util.ResourceLeakDetector/]: -Dio.netty.leakDetection.targetRecords: 4
[08Feb2024 13:05:39.569] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: -Dio.netty.noUnsafe: false
[08Feb2024 13:05:39.570] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: Java version: 17
[08Feb2024 13:05:39.571] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: sun.misc.Unsafe.theUnsafe: available
[08Feb2024 13:05:39.572] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: sun.misc.Unsafe.copyMemory: available
[08Feb2024 13:05:39.584] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: sun.misc.Unsafe.storeFence: available
[08Feb2024 13:05:39.585] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: java.nio.Buffer.address: available
[08Feb2024 13:05:39.585] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: direct buffer constructor: unavailable
java.lang.UnsupportedOperationException: Reflective setAccessible(true) disabled
at io.netty.util.internal.ReflectionUtil.trySetAccessible(ReflectionUtil.java:31) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at io.netty.util.internal.PlatformDependent0$5.run(PlatformDependent0.java:288) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at java.security.AccessController.doPrivileged(AccessController.java:318) ~[?:?]
at io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:282) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at io.netty.util.internal.PlatformDependent.isAndroid(PlatformDependent.java:333) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:88) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at io.netty.buffer.UnpooledByteBufAllocator.<clinit>(UnpooledByteBufAllocator.java:37) ~[netty-buffer-4.1.82.Final.jar:4.1.82.Final]
at io.netty.buffer.Unpooled.<clinit>(Unpooled.java:75) ~[netty-buffer-4.1.82.Final.jar:4.1.82.Final]
at thedarkcolour.exdeorum.recipe.BlockPredicateTest.networkTest(BlockPredicateTest.java:44) ~[test/:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727) ~[junit-platform-commons-1.9.2.jar:1.9.2]
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at java.util.ArrayList.forEach(ArrayList.java:1511) ~[?:?]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at java.util.ArrayList.forEach(ArrayList.java:1511) ~[?:?]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57) ~[junit5-rt.jar:?]
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) ~[junit-rt.jar:?]
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) ~[idea_rt.jar:?]
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) ~[junit-rt.jar:?]
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232) ~[junit-rt.jar:?]
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55) ~[junit-rt.jar:?]
[08Feb2024 13:05:39.596] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: java.nio.Bits.unaligned: available, true
[08Feb2024 13:05:39.597] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable
java.lang.IllegalAccessException: class io.netty.util.internal.PlatformDependent0$7 cannot access class jdk.internal.misc.Unsafe (in module java.base) because module java.base does not export jdk.internal.misc to unnamed module @c33b74f
at jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392) ~[?:?]
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:560) ~[?:?]
at io.netty.util.internal.PlatformDependent0$7.run(PlatformDependent0.java:410) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at java.security.AccessController.doPrivileged(AccessController.java:318) ~[?:?]
at io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:401) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at io.netty.util.internal.PlatformDependent.isAndroid(PlatformDependent.java:333) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:88) ~[netty-common-4.1.82.Final.jar:4.1.82.Final]
at io.netty.buffer.UnpooledByteBufAllocator.<clinit>(UnpooledByteBufAllocator.java:37) ~[netty-buffer-4.1.82.Final.jar:4.1.82.Final]
at io.netty.buffer.Unpooled.<clinit>(Unpooled.java:75) ~[netty-buffer-4.1.82.Final.jar:4.1.82.Final]
at thedarkcolour.exdeorum.recipe.BlockPredicateTest.networkTest(BlockPredicateTest.java:44) ~[test/:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727) ~[junit-platform-commons-1.9.2.jar:1.9.2]
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68) ~[junit-jupiter-engine-5.9.2.jar:5.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at java.util.ArrayList.forEach(ArrayList.java:1511) ~[?:?]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at java.util.ArrayList.forEach(ArrayList.java:1511) ~[?:?]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) ~[junit-platform-engine-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) ~[junit-platform-launcher-1.9.2.jar:1.9.2]
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57) ~[junit5-rt.jar:?]
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) ~[junit-rt.jar:?]
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) ~[idea_rt.jar:?]
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) ~[junit-rt.jar:?]
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232) ~[junit-rt.jar:?]
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55) ~[junit-rt.jar:?]
[08Feb2024 13:05:39.601] [main/DEBUG] [io.netty.util.internal.PlatformDependent0/]: java.nio.DirectByteBuffer.<init>(long, int): unavailable
[08Feb2024 13:05:39.601] [main/DEBUG] [io.netty.util.internal.PlatformDependent/]: sun.misc.Unsafe: available
[08Feb2024 13:05:39.601] [main/DEBUG] [io.netty.util.internal.PlatformDependent/]: maxDirectMemory: 8417968128 bytes (maybe)
[08Feb2024 13:05:39.601] [main/DEBUG] [io.netty.util.internal.PlatformDependent/]: -Dio.netty.tmpdir: C:\Users\Max\AppData\Local\Temp (java.io.tmpdir)
[08Feb2024 13:05:39.602] [main/DEBUG] [io.netty.util.internal.PlatformDependent/]: -Dio.netty.bitMode: 64 (sun.arch.data.model)
[08Feb2024 13:05:39.602] [main/DEBUG] [io.netty.util.internal.PlatformDependent/]: Platform: Windows
[08Feb2024 13:05:39.603] [main/DEBUG] [io.netty.util.internal.PlatformDependent/]: -Dio.netty.maxDirectMemory: -1 bytes
[08Feb2024 13:05:39.603] [main/DEBUG] [io.netty.util.internal.PlatformDependent/]: -Dio.netty.uninitializedArrayAllocationThreshold: -1
[08Feb2024 13:05:39.604] [main/DEBUG] [io.netty.util.internal.CleanerJava9/]: java.nio.ByteBuffer.cleaner(): available
[08Feb2024 13:05:39.605] [main/DEBUG] [io.netty.util.internal.PlatformDependent/]: -Dio.netty.noPreferDirect: false
[08Feb2024 13:05:39.611] [main/DEBUG] [io.netty.buffer.AbstractByteBuf/]: -Dio.netty.buffer.checkAccessible: true
[08Feb2024 13:05:39.611] [main/DEBUG] [io.netty.buffer.AbstractByteBuf/]: -Dio.netty.buffer.checkBounds: true
[08Feb2024 13:05:39.612] [main/DEBUG] [io.netty.util.ResourceLeakDetectorFactory/]: Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@200ef05b
[08Feb2024 13:05:39.627] [main/DEBUG] [io.netty.util.internal.InternalThreadLocalMap/]: -Dio.netty.threadLocalMap.stringBuilder.initialSize: 1024
[08Feb2024 13:05:39.628] [main/DEBUG] [io.netty.util.internal.InternalThreadLocalMap/]: -Dio.netty.threadLocalMap.stringBuilder.maxSize: 4096
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.numHeapArenas: 32
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.numDirectArenas: 32
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.pageSize: 8192
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.maxOrder: 9
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.chunkSize: 4194304
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.smallCacheSize: 256
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.normalCacheSize: 64
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.maxCachedBufferCapacity: 32768
[08Feb2024 13:05:39.632] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.cacheTrimInterval: 8192
[08Feb2024 13:05:39.633] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.cacheTrimIntervalMillis: 0
[08Feb2024 13:05:39.633] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.useCacheForAllThreads: false
[08Feb2024 13:05:39.633] [main/DEBUG] [io.netty.buffer.PooledByteBufAllocator/]: -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023
[08Feb2024 13:05:39.642] [main/DEBUG] [io.netty.buffer.ByteBufUtil/]: -Dio.netty.allocator.type: pooled
[08Feb2024 13:05:39.643] [main/DEBUG] [io.netty.buffer.ByteBufUtil/]: -Dio.netty.threadLocalDirectBufferSize: 0
[08Feb2024 13:05:39.643] [main/DEBUG] [io.netty.buffer.ByteBufUtil/]: -Dio.netty.maxThreadLocalCharBufferSize: 16384

0
logs/latest.log Normal file
View File

View File

@ -1,4 +1,4 @@
// 1.20.1 2024-02-01T18:59:58.2852543 Recipes
// 1.20.1 2024-02-07T21:04:33.4555528 Recipes
e37b64428f17e304e91539ac0513456d7ce40cd1 data/exdeorum/advancements/recipes/building_blocks/sponge.json
5ad481a0c376c1a1785a5d3b992064d0ec0bf3b0 data/exdeorum/advancements/recipes/food/end_cake.json
25dd027e844a72b03c95dbe5e3c3dd8c738ceb00 data/exdeorum/advancements/recipes/misc/acacia_barrel.json
@ -205,6 +205,8 @@ ba90fbda213e52dc15ea532c8f10c63ea47747de data/exdeorum/recipes/cobblestone.json
20ddd97165d2b2c1c9c04f364ddec810ca7d73d6 data/exdeorum/recipes/crimson_crucible.json
21057c2afeda8c54e808b82818c93c8102326f98 data/exdeorum/recipes/crimson_sieve.json
f6a9036c1bbc4fa0cdc25ef4c851de5ddac0a4ff data/exdeorum/recipes/crook.json
ae7e544d3e51182204eeb1efe15079103ea09802 data/exdeorum/recipes/crook/silkworm.json
b8636418dc9384bd44313de1d17fd4bbc06c0152 data/exdeorum/recipes/crook/silkworm_bonus.json
c81379fe022f3667ce506e4927aac97d1b66999f data/exdeorum/recipes/crystallized_barrel.json
77cf611f4e10c507fc4ec116ba0a9d9d1ce58273 data/exdeorum/recipes/crystallized_crucible.json
324b6222287940a7fb008b9c6a1e9caecada8af3 data/exdeorum/recipes/crystallized_sieve.json

View File

@ -0,0 +1,8 @@
{
"type": "exdeorum:crook",
"block_predicate": {
"block_tag": "minecraft:leaves"
},
"chance": 0.01,
"result": "exdeorum:silk_worm"
}

View File

@ -0,0 +1,11 @@
{
"type": "exdeorum:crook",
"block_predicate": {
"block": "exdeorum:infested_leaves",
"state": {
"fully_infested": "true"
}
},
"chance": 0.01,
"result": "exdeorum:silk_worm"
}

View File

@ -0,0 +1,129 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.compat.jei;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.helpers.IJeiHelpers;
import mezz.jei.api.helpers.IModIdHelper;
import mezz.jei.api.recipe.IFocusFactory;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.api.runtime.IIngredientManager;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.registries.ForgeRegistries;
import thedarkcolour.exdeorum.data.TranslationKeys;
import thedarkcolour.exdeorum.registry.EBlocks;
import thedarkcolour.exdeorum.registry.EItems;
import java.util.ArrayList;
import java.util.List;
public class CrookCategory implements IRecipeCategory<CrookJeiRecipe> {
private static final Component REQUIRES_CERTAIN_STATE = Component.translatable(TranslationKeys.CROOK_CATEGORY_REQUIRES_STATE);
private final IDrawable background;
private final IDrawable icon;
private final IDrawable arrow;
private final IDrawable slot;
private final Component title;
private final IFocusFactory focusFactory;
private final IIngredientManager ingredientManager;
private final IModIdHelper modIdHelper;
private final CycleTimer timer = new CycleTimer(0);
public CrookCategory(IJeiHelpers helpers, IDrawable arrow) {
var helper = helpers.getGuiHelper();
this.background = helper.createBlankDrawable(120, 48);
this.icon = helper.createDrawableItemStack(new ItemStack(EItems.CROOK.get()));
this.arrow = arrow;
this.slot = helper.getSlotDrawable();
this.title = Component.translatable(TranslationKeys.CROOK_CATEGORY_TITLE);
this.focusFactory = helpers.getFocusFactory();
this.ingredientManager = helpers.getIngredientManager();
this.modIdHelper = helpers.getModIdHelper();
}
@Override
public RecipeType<CrookJeiRecipe> getRecipeType() {
return ExDeorumJeiPlugin.CROOK;
}
@Override
public Component getTitle() {
return this.title;
}
@Override
public IDrawable getBackground() {
return this.background;
}
@Override
public IDrawable getIcon() {
return this.icon;
}
@Override
public void setRecipe(IRecipeLayoutBuilder builder, CrookJeiRecipe recipe, IFocusGroup focuses) {
recipe.addIngredients(builder);
builder.addSlot(RecipeIngredientRole.OUTPUT, 80, 18).addItemStack(new ItemStack(recipe.result));
}
@Override
public void draw(CrookJeiRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) {
this.timer.onDraw();
this.arrow.draw(graphics, 52, 18);
this.slot.draw(graphics, 79, 17);
BlockState state = this.timer.getCycledItem(recipe.states);
if (state.is(EBlocks.INFESTED_LEAVES.get())) {
state = Blocks.OAK_LEAVES.defaultBlockState();
}
ClientJeiUtil.renderBlock(graphics, state, 28, 18, 10, 20F);
}
@Override
public List<Component> getTooltipStrings(CrookJeiRecipe recipe, IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) {
if (44.0 < mouseX && mouseX < 76.0 && 16 < mouseY && mouseY < 48) {
var block = this.timer.getCycledItem(recipe.states).getBlock();
var modId = ForgeRegistries.BLOCKS.getKey(block).getNamespace();
var tooltip = new ArrayList<Component>();
tooltip.add(Component.translatable(block.getDescriptionId()));
if (recipe.getClass() == CrookJeiRecipe.StatesRecipe.class) {
tooltip.add(REQUIRES_CERTAIN_STATE);
}
tooltip.add(Component.literal(this.modIdHelper.getFormattedModNameForModId(modId)));
return tooltip;
}
return List.of();
}
}

View File

@ -0,0 +1,134 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.compat.jei;
import com.google.common.collect.ImmutableList;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.recipe.RecipeIngredientRole;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import thedarkcolour.exdeorum.recipe.BlockPredicate;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
public sealed abstract class CrookJeiRecipe {
public final List<BlockState> states;
public Item result;
public float chance;
public CrookJeiRecipe(List<BlockState> states, Item result, float chance) {
this.states = states;
this.result = result;
this.chance = chance;
}
public abstract void addIngredients(IRecipeLayoutBuilder builder);
static CrookJeiRecipe create(CrookRecipe recipe) {
if (recipe.blockPredicate() instanceof BlockPredicate.BlockStatePredicate state) {
return new StatesRecipe(state.possibleStates().collect(Collectors.toList()), recipe.result(), recipe.chance());
} else if (recipe.blockPredicate() instanceof BlockPredicate.SingleBlockPredicate block) {
return new BlockRecipe(block.block(), recipe.result(), recipe.chance());
} else if (recipe.blockPredicate() instanceof BlockPredicate.TagPredicate tag) {
var list = new ArrayList<BlockState>();
for (var holder : BuiltInRegistries.BLOCK.getTagOrEmpty(tag.tag())) {
if (holder.isBound()) {
list.add(holder.value().defaultBlockState());
}
}
return new TagRecipe(tag.tag(), List.copyOf(list), recipe.result(), recipe.chance());
}
throw new IllegalArgumentException("Invalid crook recipe?? -> " + recipe);
}
sealed static class StatesRecipe extends CrookJeiRecipe {
private final List<ItemStack> itemIngredients;
StatesRecipe(List<BlockState> states, Item result, float chance) {
super(states, result, chance);
ImmutableList.Builder<ItemStack> temp = ImmutableList.builder();
var blocks = new HashSet<Block>();
for (var state : states) {
var block = state.getBlock();
if (blocks.add(block)) {
var item = block.asItem();
if (item != Items.AIR) {
temp.add(new ItemStack(item));
}
}
}
this.itemIngredients = temp.build();
}
@Override
public void addIngredients(IRecipeLayoutBuilder builder) {
if (!this.itemIngredients.isEmpty()) {
builder.addInvisibleIngredients(RecipeIngredientRole.INPUT).addItemStacks(this.itemIngredients);
}
}
}
static final class TagRecipe extends StatesRecipe {
public final TagKey<Block> tag;
public TagRecipe(TagKey<Block> tag, List<BlockState> states, Item result, float chance) {
super(states, result, chance);
this.tag = tag;
}
}
static final class BlockRecipe extends CrookJeiRecipe {
private final ItemStack itemIngredient;
BlockRecipe(Block block, Item result, float chance) {
super(List.of(block.defaultBlockState()), result, chance);
var item = block.asItem();
if (item == Items.AIR) {
this.itemIngredient = ItemStack.EMPTY;
} else {
this.itemIngredient = new ItemStack(item);
}
}
@Override
public void addIngredients(IRecipeLayoutBuilder builder) {
if (!this.itemIngredient.isEmpty()) {
builder.addInvisibleIngredients(RecipeIngredientRole.INPUT).addItemStack(this.itemIngredient);
}
}
}
}

View File

@ -0,0 +1,56 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.compat.jei;
import net.minecraft.client.gui.screens.Screen;
import java.util.List;
// Copy of JEI CycleTimer that doesn't force TypedIngredient and isn't in a non-API package
public class CycleTimer {
// the amount of time in ms to display one thing before cycling to the next one
private static final int CYCLE_TIME = 1000;
private long startTime;
private long drawTime;
private long pausedDuration = 0;
public CycleTimer(int offset) {
long time = System.currentTimeMillis();
this.startTime = time - ((long) offset * CYCLE_TIME);
this.drawTime = time;
}
// Assumes list is not empty
public <T> T getCycledItem(List<T> list) {
long index = ((this.drawTime - this.startTime) / CYCLE_TIME) % list.size();
return list.get(Math.toIntExact(index));
}
public void onDraw() {
if (!Screen.hasShiftDown()) {
if (pausedDuration > 0) {
this.startTime += this.pausedDuration;
this.pausedDuration = 0;
}
this.drawTime = System.currentTimeMillis();
} else {
this.pausedDuration = System.currentTimeMillis() - this.drawTime;
}
}
}

View File

@ -18,7 +18,6 @@
package thedarkcolour.exdeorum.compat.jei;
import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
@ -56,6 +55,7 @@ import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.registry.EBlocks;
@ -82,6 +82,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
static final RecipeType<CrucibleHeatSourceRecipe> CRUCIBLE_HEAT_SOURCES = RecipeType.create(ExDeorum.ID, "crucible_heat_sources", CrucibleHeatSourceRecipe.class);
static final RecipeType<GroupedSieveRecipe> SIEVE = RecipeType.create(ExDeorum.ID, "sieve", GroupedSieveRecipe.class);
static final RecipeType<HammerRecipe> HAMMER = RecipeType.create(ExDeorum.ID, "hammer", HammerRecipe.class);
static final RecipeType<CrookJeiRecipe> CROOK = RecipeType.create(ExDeorum.ID, "crook", CrookJeiRecipe.class);
@Override
public ResourceLocation getPluginUid() {
@ -102,6 +103,7 @@ public class ExDeorumJeiPlugin implements IModPlugin {
registration.addRecipeCategories(new CrucibleHeatSourcesCategory(registration.getJeiHelpers()));
registration.addRecipeCategories(new SieveCategory(helper));
registration.addRecipeCategories(new HammerCategory(helper, arrow));
registration.addRecipeCategories(new CrookCategory(registration.getJeiHelpers(), arrow));
}
@Override
@ -136,6 +138,9 @@ public class ExDeorumJeiPlugin implements IModPlugin {
registration.addRecipeCatalyst(new ItemStack(EItems.DIAMOND_HAMMER.get()), HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.NETHERITE_HAMMER.get()), HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.MECHANICAL_HAMMER.get()), HAMMER);
registration.addRecipeCatalyst(new ItemStack(EItems.CROOK.get()), CROOK);
registration.addRecipeCatalyst(new ItemStack(EItems.BONE_CROOK.get()), CROOK);
}
@Override
@ -185,6 +190,11 @@ public class ExDeorumJeiPlugin implements IModPlugin {
addRecipes(registration, LAVA_CRUCIBLE, ERecipeTypes.LAVA_CRUCIBLE);
addRecipes(registration, WATER_CRUCIBLE, ERecipeTypes.WATER_CRUCIBLE);
addRecipes(registration, HAMMER, ERecipeTypes.HAMMER);
var crookRecipes = new ArrayList<CrookJeiRecipe>();
for (var recipe : Objects.requireNonNull(Minecraft.getInstance().level).getRecipeManager().getAllRecipesFor(ERecipeTypes.CROOK.get())) {
crookRecipes.add(CrookJeiRecipe.create(recipe));
}
registration.addRecipes(CROOK, crookRecipes);
registration.addRecipes(SIEVE, GroupedSieveRecipe.getAllRecipesGrouped());
addCrucibleHeatSources(registration);

View File

@ -68,6 +68,8 @@ class English {
english.add(TranslationKeys.CRUCIBLE_HEAT_SOURCE_CATEGORY_TITLE, "Crucible Heat Sources");
english.add(TranslationKeys.CRUCIBLE_HEAT_SOURCE_CATEGORY_MULTIPLIER, "Melt Rate: %sx");
english.add(TranslationKeys.HAMMER_CATEGORY_TITLE, "Hammer");
english.add(TranslationKeys.CROOK_CATEGORY_TITLE, "Crook");
english.add(TranslationKeys.CROOK_CATEGORY_REQUIRES_STATE, "Requires specific block state");
english.add(TranslationKeys.SIEVE_CATEGORY_TITLE, "Sieve");
english.add(TranslationKeys.SIEVE_RECIPE_CHANCE, "Chance: %s%%");
english.add(TranslationKeys.SIEVE_RECIPE_AVERAGE_OUTPUT, "Avg. Output: %s");

View File

@ -67,6 +67,8 @@ public class TranslationKeys {
public static final String CRUCIBLE_HEAT_SOURCE_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.crucible_heat_source";
public static final String CRUCIBLE_HEAT_SOURCE_CATEGORY_MULTIPLIER = "gui." + ExDeorum.ID + ".category.crucible_heat_source.multiplier";
public static final String HAMMER_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.hammer";
public static final String CROOK_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.crook";
public static final String CROOK_CATEGORY_REQUIRES_STATE = "gui." + ExDeorum.ID + ".category.crook.requires_state";
public static final String SIEVE_CATEGORY_TITLE = "gui." + ExDeorum.ID + ".category.sieve";
public static final String SIEVE_RECIPE_CHANCE = "gui." + ExDeorum.ID + ".category.sieve.chance";
public static final String SIEVE_RECIPE_AVERAGE_OUTPUT = "gui." + ExDeorum.ID + ".category.sieve.average_output";

View File

@ -18,9 +18,11 @@
package thedarkcolour.exdeorum.data.recipe;
import net.minecraft.advancements.critereon.StatePropertiesPredicate;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.ItemTags;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
@ -29,7 +31,6 @@ import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.material.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
@ -44,12 +45,15 @@ import net.minecraftforge.common.crafting.conditions.TagEmptyCondition;
import net.minecraftforge.registries.RegistryObject;
import org.apache.commons.lang3.mutable.MutableObject;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.block.InfestedLeavesBlock;
import thedarkcolour.exdeorum.compat.ModIds;
import thedarkcolour.exdeorum.data.ModCompatData;
import thedarkcolour.exdeorum.recipe.TagResultRecipe;
import thedarkcolour.exdeorum.recipe.barrel.FinishedBarrelCompostRecipe;
import thedarkcolour.exdeorum.recipe.barrel.FinishedBarrelFluidMixingRecipe;
import thedarkcolour.exdeorum.recipe.barrel.FinishedBarrelMixingRecipe;
import thedarkcolour.exdeorum.recipe.BlockPredicate;
import thedarkcolour.exdeorum.recipe.crook.FinishedCrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.FinishedCrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.FinishedHammerRecipe;
import thedarkcolour.exdeorum.registry.EBlocks;
@ -75,6 +79,7 @@ public class Recipes {
SieveRecipes.sieveRecipes(writer);
crucibleRecipes(writer);
hammerRecipes(writer);
crookRecipes(writer);
barrelCompostRecipes(writer);
barrelMixingRecipes(writer);
}
@ -481,6 +486,16 @@ public class Recipes {
writer.accept(new FinishedHammerRecipe(new ResourceLocation(ExDeorum.ID, "hammer/" + name), block, result.asItem(), resultAmount));
}
private static void crookRecipes(Consumer<FinishedRecipe> writer) {
crookRecipe(writer, "silkworm", BlockPredicate.blockTag(BlockTags.LEAVES), EItems.SILK_WORM.get(), 0.01f);
var fullyInfestedLeaves = BlockPredicate.blockState(EBlocks.INFESTED_LEAVES.get(), StatePropertiesPredicate.Builder.properties().hasProperty(InfestedLeavesBlock.FULLY_INFESTED, true).build());
crookRecipe(writer, "silkworm_bonus", fullyInfestedLeaves, EItems.SILK_WORM.get(), 0.01f);
}
private static void crookRecipe(Consumer<FinishedRecipe> writer, String name, BlockPredicate blockPredicate, ItemLike result, float chance) {
writer.accept(new FinishedCrookRecipe(new ResourceLocation(ExDeorum.ID, "crook/" + name), blockPredicate, result.asItem(), chance));
}
private static void barrelCompostRecipes(Consumer<FinishedRecipe> writer) {
// plants
barrelCompost(writer, "saplings", ingredient(ItemTags.SAPLINGS), 125);

View File

@ -26,6 +26,7 @@ import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
@ -33,14 +34,14 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.common.loot.LootModifier;
import org.jetbrains.annotations.NotNull;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.registry.EItems;
public class CrookLootModifier extends LootModifier {
public static final Codec<CrookLootModifier> CODEC = RecordCodecBuilder.create(inst -> {
return LootModifier.codecStart(inst).apply(inst, CrookLootModifier::new);
});
import java.util.List;
private static final float[] SILK_WORM_FORTUNE_CHANCES = new float[] { 0.01f, 0.0111111114f, 0.0125f, 0.016666668f, 0.05f };
public class CrookLootModifier extends LootModifier {
public static final Codec<CrookLootModifier> CODEC = RecordCodecBuilder.create(inst -> LootModifier.codecStart(inst).apply(inst, CrookLootModifier::new));
protected CrookLootModifier(LootItemCondition[] conditions) {
super(conditions);
@ -51,38 +52,31 @@ public class CrookLootModifier extends LootModifier {
var state = context.getParamOrNull(LootContextParams.BLOCK_STATE);
var stack = context.getParamOrNull(LootContextParams.TOOL);
if (state != null && stack != null && state.is(BlockTags.LEAVES)) {
if (state != null && stack != null) {
var rand = context.getRandom();
if (stack.getEnchantmentLevel(Enchantments.SILK_TOUCH) == 0) {
var fortune = stack.getEnchantmentLevel(Enchantments.BLOCK_FORTUNE);
var repeats = Math.max(1, Mth.ceil(fortune / 3f));
var rolls = Math.max(1, Mth.ceil(fortune / 3f));
if (rand.nextInt(100) == 0) {
generatedLoot.add(new ItemStack(EItems.SILK_WORM.get()));
for (CrookRecipe recipe : RecipeUtil.getCrookRecipes(state)) {
for (int i = 0; i < rolls; i++) {
if (rand.nextFloat() < recipe.chance()) {
generatedLoot.add(new ItemStack(recipe.result()));
}
}
}
for (int i = 0; i < repeats; i++) {
if (rand.nextFloat() < SILK_WORM_FORTUNE_CHANCES[fortune % 3]) {
generatedLoot.add(new ItemStack(EItems.SILK_WORM.get()));
}
// crook gives an additional roll for leaf drops
if (state.is(BlockTags.LEAVES)) {
// this must not be a crook in order to avoid recursively triggering CrookLootModifier from the re roll method
// copying the tag is required so that enchantments like fortune are preserved
var nonCrook = new ItemStack(Items.BARRIER);
nonCrook.setTag(stack.getTag());
// crook gives an additional roll for drops
var builder = new LootParams.Builder(context.getLevel());
builder.withParameter(LootContextParams.BLOCK_STATE, context.getParam(LootContextParams.BLOCK_STATE));
// avoid recursion
var dummy = new ItemStack(Items.DEAD_BUSH);
dummy.setTag(stack.getTag());
builder.withParameter(LootContextParams.TOOL, dummy);
if (context.hasParam(LootContextParams.THIS_ENTITY)) {
builder.withParameter(LootContextParams.THIS_ENTITY, context.getParam(LootContextParams.THIS_ENTITY));
for (int i = 0; i < rolls; i++) {
generatedLoot.addAll(reRollDrops(context, nonCrook, state));
}
if (context.hasParam(LootContextParams.ORIGIN)) {
builder.withParameter(LootContextParams.ORIGIN, context.getParam(LootContextParams.ORIGIN));
}
var reRoll = state.getDrops(builder);
generatedLoot.addAll(reRoll);
}
}
}
@ -90,6 +84,20 @@ public class CrookLootModifier extends LootModifier {
return generatedLoot;
}
private static List<ItemStack> reRollDrops(LootContext context, ItemStack nonCrook, BlockState state) {
var builder = new LootParams.Builder(context.getLevel());
builder.withParameter(LootContextParams.BLOCK_STATE, context.getParam(LootContextParams.BLOCK_STATE));
builder.withParameter(LootContextParams.TOOL, nonCrook);
if (context.hasParam(LootContextParams.THIS_ENTITY)) {
builder.withParameter(LootContextParams.THIS_ENTITY, context.getParam(LootContextParams.THIS_ENTITY));
}
if (context.hasParam(LootContextParams.ORIGIN)) {
builder.withParameter(LootContextParams.ORIGIN, context.getParam(LootContextParams.ORIGIN));
}
return state.getDrops(builder);
}
@Override
public Codec<? extends IGlobalLootModifier> codec() {
return CODEC;

View File

@ -0,0 +1,171 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.recipe;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.minecraft.advancements.critereon.StatePropertiesPredicate;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@SuppressWarnings("deprecation")
public sealed interface BlockPredicate extends Predicate<BlockState> {
// used for network
byte SINGLE_BLOCK = 0, BLOCK_STATE = 1, BLOCK_TAG = 2;
JsonObject toJson();
void toNetwork(FriendlyByteBuf buffer);
Stream<BlockState> possibleStates();
static BlockPredicate singleBlock(Block block) {
return new SingleBlockPredicate(block);
}
static BlockPredicate blockState(Block block, StatePropertiesPredicate properties) {
return new BlockStatePredicate(block, properties);
}
static BlockPredicate blockTag(TagKey<Block> tag) {
return new TagPredicate(tag);
}
@Nullable
static BlockPredicate fromJson(@Nullable JsonObject json) {
if (json == null) {
return null;
}
if (json.has("block")) {
var block = BuiltInRegistries.BLOCK.get(new ResourceLocation(json.get("block").getAsString()));
if (block == Blocks.AIR) return null;
if (json.has("state")) {
return new BlockStatePredicate(block, StatePropertiesPredicate.fromJson(json.get("block_state")));
} else {
return new SingleBlockPredicate(block);
}
} else if (json.has("block_tag")) {
return new TagPredicate(TagKey.create(Registries.BLOCK, new ResourceLocation(json.get("block_tag").getAsString())));
} else {
return null;
}
}
@Nullable
static BlockPredicate fromNetwork(FriendlyByteBuf buffer) {
return switch (buffer.readByte()) {
case SINGLE_BLOCK -> new SingleBlockPredicate(buffer.readById(BuiltInRegistries.BLOCK));
case BLOCK_STATE -> new BlockStatePredicate(buffer.readById(BuiltInRegistries.BLOCK), StatePropertiesPredicate.fromJson(JsonParser.parseString(buffer.readUtf())));
case BLOCK_TAG -> new TagPredicate(TagKey.create(Registries.BLOCK, buffer.readResourceLocation()));
default -> null;
};
}
record TagPredicate(TagKey<Block> tag) implements BlockPredicate {
@Override
public JsonObject toJson() {
var json = new JsonObject();
json.addProperty("block_tag", this.tag.location().toString());
return json;
}
@Override
public void toNetwork(FriendlyByteBuf buffer) {
buffer.writeByte(BLOCK_TAG);
buffer.writeResourceLocation(this.tag.location());
}
@Override
public boolean test(BlockState state) {
return state.is(this.tag);
}
@Override
public Stream<BlockState> possibleStates() {
return StreamSupport.stream(BuiltInRegistries.BLOCK.getTagOrEmpty(this.tag).spliterator(), false)
.filter(holder -> holder.is(this.tag))
.flatMap(holder -> holder.get().getStateDefinition().getPossibleStates().stream());
}
}
record BlockStatePredicate(Block block, StatePropertiesPredicate properties) implements BlockPredicate {
@Override
public JsonObject toJson() {
var json = new JsonObject();
json.addProperty("block", BuiltInRegistries.BLOCK.getKey(this.block).toString());
json.add("state", this.properties.serializeToJson());
return json;
}
@Override
public void toNetwork(FriendlyByteBuf buffer) {
buffer.writeByte(BLOCK_STATE);
buffer.writeId(BuiltInRegistries.BLOCK, this.block);
buffer.writeUtf(this.properties.serializeToJson().toString());
}
@Override
public boolean test(BlockState state) {
return state.is(this.block) && this.properties.matches(state);
}
@Override
public Stream<BlockState> possibleStates() {
return this.block.getStateDefinition().getPossibleStates().stream().filter(this.properties::matches);
}
}
record SingleBlockPredicate(Block block) implements BlockPredicate {
@Override
public JsonObject toJson() {
var json = new JsonObject();
json.addProperty("block", BuiltInRegistries.BLOCK.getKey(this.block).toString());
return json;
}
@Override
public void toNetwork(FriendlyByteBuf buffer) {
buffer.writeByte(SINGLE_BLOCK);
buffer.writeId(BuiltInRegistries.BLOCK, this.block);
}
@Override
public boolean test(BlockState state) {
return state.is(this.block);
}
@Override
public Stream<BlockState> possibleStates() {
return this.block.getStateDefinition().getPossibleStates().stream();
}
}
}

View File

@ -35,6 +35,7 @@ import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.storage.loot.LootContext;
@ -50,6 +51,11 @@ import thedarkcolour.exdeorum.item.HammerItem;
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
import thedarkcolour.exdeorum.recipe.cache.BarrelFluidMixingRecipeCache;
import thedarkcolour.exdeorum.recipe.cache.CrookRecipeCache;
import thedarkcolour.exdeorum.recipe.cache.SieveRecipeCache;
import thedarkcolour.exdeorum.recipe.cache.SingleIngredientRecipeCache;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
@ -73,6 +79,7 @@ public final class RecipeUtil {
private static SingleIngredientRecipeCache<HammerRecipe> hammerRecipeCache;
private static SieveRecipeCache sieveRecipeCache;
private static BarrelFluidMixingRecipeCache barrelFluidMixingRecipeCache;
private static CrookRecipeCache crookRecipeCache;
public static void reload(RecipeManager recipes) {
barrelCompostRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.BARREL_COMPOST);
@ -81,6 +88,7 @@ public final class RecipeUtil {
hammerRecipeCache = new SingleIngredientRecipeCache<>(recipes, ERecipeTypes.HAMMER).trackAllRecipes();
sieveRecipeCache = new SieveRecipeCache(recipes);
barrelFluidMixingRecipeCache = new BarrelFluidMixingRecipeCache(recipes);
crookRecipeCache = new CrookRecipeCache(recipes);
HammerItem.refreshValidBlocks();
}
@ -91,6 +99,7 @@ public final class RecipeUtil {
hammerRecipeCache = null;
sieveRecipeCache = null;
barrelFluidMixingRecipeCache = null;
crookRecipeCache = null;
}
public static List<SieveRecipe> getSieveRecipes(Item mesh, ItemStack item) {
@ -310,4 +319,8 @@ public final class RecipeUtil {
public static LootContext emptyLootContext(ServerLevel level) {
return new LootContext.Builder(new LootParams(level, Map.of(), Map.of(), 0)).create(null);
}
public static List<CrookRecipe> getCrookRecipes(BlockState state) {
return crookRecipeCache.getRecipes(state);
}
}

View File

@ -35,7 +35,7 @@ import net.minecraft.world.level.Level;
*/
public abstract class SingleIngredientRecipe implements Recipe<Container> {
private final ResourceLocation id;
protected final Ingredient ingredient;
public final Ingredient ingredient;
public final boolean dependsOnNbt;
public SingleIngredientRecipe(ResourceLocation id, Ingredient ingredient) {

View File

@ -19,11 +19,11 @@
package thedarkcolour.exdeorum.recipe.barrel;
import com.google.gson.JsonObject;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.material.Fluid;
import net.minecraftforge.registries.ForgeRegistries;
import thedarkcolour.exdeorum.recipe.EFinishedRecipe;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
@ -46,11 +46,11 @@ public class FinishedBarrelFluidMixingRecipe implements EFinishedRecipe {
@Override
public void serializeRecipeData(JsonObject json) {
json.addProperty("base_fluid", ForgeRegistries.FLUIDS.getKey(this.baseFluid).toString());
json.addProperty("base_fluid", BuiltInRegistries.FLUID.getKey(this.baseFluid).toString());
json.addProperty("base_fluid_amount", this.baseFluidAmount);
json.addProperty("additive_fluid", ForgeRegistries.FLUIDS.getKey(this.additiveFluid).toString());
json.addProperty("additive_fluid", BuiltInRegistries.FLUID.getKey(this.additiveFluid).toString());
json.addProperty("consumes_additive", this.consumesAdditive);
json.addProperty("result", ForgeRegistries.ITEMS.getKey(this.result).toString());
json.addProperty("result", BuiltInRegistries.ITEM.getKey(this.result).toString());
}
@Override

View File

@ -19,12 +19,12 @@
package thedarkcolour.exdeorum.recipe.barrel;
import com.google.gson.JsonObject;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.material.Fluid;
import net.minecraftforge.registries.ForgeRegistries;
import thedarkcolour.exdeorum.recipe.EFinishedRecipe;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
@ -46,9 +46,9 @@ public class FinishedBarrelMixingRecipe implements EFinishedRecipe {
@Override
public void serializeRecipeData(JsonObject json) {
json.add("ingredient", this.ingredient.toJson());
json.addProperty("fluid", ForgeRegistries.FLUIDS.getKey(this.fluid).toString());
json.addProperty("fluid", BuiltInRegistries.FLUID.getKey(this.fluid).toString());
json.addProperty("fluid_amount", this.fluidAmount);
json.addProperty("result", ForgeRegistries.ITEMS.getKey(this.result).toString());
json.addProperty("result", BuiltInRegistries.ITEM.getKey(this.result).toString());
}
@Override

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.recipe;
package thedarkcolour.exdeorum.recipe.cache;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.level.material.Fluid;

View File

@ -0,0 +1,65 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.recipe.cache;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
import java.util.*;
public class CrookRecipeCache {
private RecipeManager recipeManager;
@Nullable
private Map<BlockState, List<CrookRecipe>> recipes;
public CrookRecipeCache(RecipeManager recipeManager) {
this.recipeManager = recipeManager;
}
public List<CrookRecipe> getRecipes(BlockState state) {
if (this.recipes == null) {
buildRecipes();
}
return this.recipes.getOrDefault(state, List.of());
}
private void buildRecipes() {
this.recipes = new HashMap<>();
// state -> set of possible recipes
var tempRecipes = new HashMap<BlockState, HashSet<CrookRecipe>>();
for (var recipe : this.recipeManager.byType(ERecipeTypes.CROOK.get()).values()) {
recipe.blockPredicate().possibleStates().forEach(state -> {
tempRecipes.computeIfAbsent(state, key -> new HashSet<>()).add(recipe);
});
}
// map equal sets to a single list object instead of using a bunch of duplicate sets
var dedupeMap = new HashMap<HashSet<CrookRecipe>, List<CrookRecipe>>();
for (var entry : tempRecipes.entrySet()) {
this.recipes.put(entry.getKey(), dedupeMap.computeIfAbsent(entry.getValue(), List::copyOf));
}
this.recipeManager = null;
}
}

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.recipe;
package thedarkcolour.exdeorum.recipe.cache;
import com.google.common.collect.ImmutableList;
import net.minecraft.world.item.Item;

View File

@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.recipe;
package thedarkcolour.exdeorum.recipe.cache;
import com.google.common.collect.ImmutableList;
import net.minecraft.world.item.Item;
@ -24,6 +24,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.item.crafting.RecipeType;
import org.jetbrains.annotations.Nullable;
import thedarkcolour.exdeorum.recipe.SingleIngredientRecipe;
import java.util.Collection;
import java.util.HashMap;
@ -84,7 +85,6 @@ public class SingleIngredientRecipeCache<T extends SingleIngredientRecipe> {
if (this.simpleRecipes == null) {
buildRecipes();
}
//noinspection DataFlowIssue
return this.allRecipes;
}

View File

@ -0,0 +1,21 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@net.minecraft.MethodsReturnNonnullByDefault
@javax.annotation.ParametersAreNonnullByDefault
package thedarkcolour.exdeorum.recipe.cache;

View File

@ -0,0 +1,116 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.recipe.crook;
import com.google.gson.JsonObject;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Container;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.recipe.BlockPredicate;
import thedarkcolour.exdeorum.recipe.RecipeUtil;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
import thedarkcolour.exdeorum.registry.ERecipeTypes;
public record CrookRecipe(ResourceLocation id, BlockPredicate blockPredicate, Item result, float chance) implements Recipe<Container> {
@Override
public boolean matches(Container pContainer, Level pLevel) {
return false;
}
@Override
public ItemStack assemble(Container pContainer, RegistryAccess pRegistryAccess) {
return ItemStack.EMPTY;
}
@Override
public boolean canCraftInDimensions(int pWidth, int pHeight) {
return false;
}
@Override
public ItemStack getResultItem(RegistryAccess pRegistryAccess) {
return new ItemStack(this.result);
}
@Override
public ResourceLocation getId() {
return this.id;
}
@Override
public RecipeSerializer<?> getSerializer() {
return ERecipeSerializers.CROOK.get();
}
@Override
public RecipeType<?> getType() {
return ERecipeTypes.CROOK.get();
}
@SuppressWarnings("deprecation")
public static class Serializer implements RecipeSerializer<CrookRecipe> {
@Override
public CrookRecipe fromJson(ResourceLocation id, JsonObject json) {
BlockPredicate blockPredicate = BlockPredicate.fromJson(json.getAsJsonObject("block_predicate"));
if (blockPredicate == null) {
ExDeorum.LOGGER.error("Invalid block_predicate for recipe {}, refer to Ex Deorum documentation for syntax: {}", id, json.getAsJsonObject("block_predicate"));
return null;
}
Item result = RecipeUtil.readItem(json, "result");
float chance = json.get("chance").getAsFloat();
return new CrookRecipe(id, blockPredicate, result, chance);
}
@Override
public CrookRecipe fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
BlockPredicate blockPredicate = BlockPredicate.fromNetwork(buffer);
if (blockPredicate == null) {
ExDeorum.LOGGER.error("Failed to read block_predicate from network for recipe {}", id);
return null;
}
Item result = buffer.readById(BuiltInRegistries.ITEM);
if (result == null || result == Items.AIR) {
return null;
}
float chance = buffer.readFloat();
return new CrookRecipe(id, blockPredicate, result, chance);
}
@Override
public void toNetwork(FriendlyByteBuf buffer, CrookRecipe recipe) {
recipe.blockPredicate.toNetwork(buffer);
buffer.writeId(BuiltInRegistries.ITEM, recipe.result);
buffer.writeFloat(recipe.chance);
}
}
}

View File

@ -0,0 +1,59 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.recipe.crook;
import com.google.gson.JsonObject;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.RecipeSerializer;
import thedarkcolour.exdeorum.recipe.BlockPredicate;
import thedarkcolour.exdeorum.recipe.EFinishedRecipe;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
public class FinishedCrookRecipe implements EFinishedRecipe {
private final ResourceLocation id;
private final BlockPredicate predicate;
private final Item result;
private final float chance;
public FinishedCrookRecipe(ResourceLocation id, BlockPredicate predicate, Item result, float chance) {
this.id = id;
this.predicate = predicate;
this.result = result;
this.chance = chance;
}
@Override
public void serializeRecipeData(JsonObject json) {
json.add("block_predicate", this.predicate.toJson());
json.addProperty("result", BuiltInRegistries.ITEM.getKey(this.result).toString());
json.addProperty("chance", this.chance);
}
@Override
public ResourceLocation getId() {
return this.id;
}
@Override
public RecipeSerializer<?> getType() {
return ERecipeSerializers.CROOK.get();
}
}

View File

@ -0,0 +1,21 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@net.minecraft.MethodsReturnNonnullByDefault
@javax.annotation.ParametersAreNonnullByDefault
package thedarkcolour.exdeorum.recipe.crook;

View File

@ -19,13 +19,13 @@
package thedarkcolour.exdeorum.recipe.hammer;
import com.google.gson.JsonObject;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.storage.loot.LootDataType;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import net.minecraftforge.registries.ForgeRegistries;
import thedarkcolour.exdeorum.recipe.EFinishedRecipe;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
@ -45,7 +45,7 @@ public class FinishedHammerRecipe implements EFinishedRecipe {
@Override
public void serializeRecipeData(JsonObject object) {
object.add("ingredient", this.ingredient.toJson());
object.addProperty("result", ForgeRegistries.ITEMS.getKey(this.result).toString());
object.addProperty("result", BuiltInRegistries.ITEM.getKey(this.result).toString());
object.add("result_amount", LootDataType.PREDICATE.parser().toJsonTree(this.resultAmount));
}

View File

@ -20,6 +20,7 @@ package thedarkcolour.exdeorum.recipe.sieve;
import com.google.gson.JsonObject;
import com.mojang.datafixers.util.Either;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
@ -27,7 +28,6 @@ import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.storage.loot.LootDataType;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import net.minecraftforge.registries.ForgeRegistries;
import thedarkcolour.exdeorum.recipe.EFinishedRecipe;
import thedarkcolour.exdeorum.registry.ERecipeSerializers;
@ -49,9 +49,9 @@ public class FinishedSieveRecipe implements EFinishedRecipe {
@Override
public void serializeRecipeData(JsonObject object) {
object.add("ingredient", this.ingredient.toJson());
object.addProperty("mesh", ForgeRegistries.ITEMS.getKey(this.mesh).toString());
object.addProperty("mesh", BuiltInRegistries.ITEM.getKey(this.mesh).toString());
this.result.ifLeft(item -> {
object.addProperty("result", ForgeRegistries.ITEMS.getKey(item).toString());
object.addProperty("result", BuiltInRegistries.ITEM.getKey(item).toString());
}).ifRight(tag -> {
object.addProperty("result_tag", tag.location().toString());
});

View File

@ -27,6 +27,7 @@ import thedarkcolour.exdeorum.recipe.TagResultRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
@ -39,6 +40,7 @@ public class ERecipeSerializers {
public static final RegistryObject<RecipeSerializer<BarrelFluidMixingRecipe>> BARREL_FLUID_MIXING = RECIPE_SERIALIZERS.register("barrel_fluid_mixing", BarrelFluidMixingRecipe.Serializer::new);
public static final RegistryObject<RecipeSerializer<HammerRecipe>> HAMMER = RECIPE_SERIALIZERS.register("hammer", HammerRecipe.Serializer::new);
public static final RegistryObject<RecipeSerializer<CrookRecipe>> CROOK = RECIPE_SERIALIZERS.register("crook", CrookRecipe.Serializer::new);
public static final RegistryObject<RecipeSerializer<CrucibleRecipe>> LAVA_CRUCIBLE = RECIPE_SERIALIZERS.register("lava_crucible", () -> new CrucibleRecipe.Serializer(ERecipeTypes.LAVA_CRUCIBLE.get()));
public static final RegistryObject<RecipeSerializer<CrucibleRecipe>> WATER_CRUCIBLE = RECIPE_SERIALIZERS.register("water_crucible", () -> new CrucibleRecipe.Serializer(ERecipeTypes.WATER_CRUCIBLE.get()));

View File

@ -26,6 +26,7 @@ import thedarkcolour.exdeorum.ExDeorum;
import thedarkcolour.exdeorum.recipe.barrel.BarrelCompostRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelFluidMixingRecipe;
import thedarkcolour.exdeorum.recipe.barrel.BarrelMixingRecipe;
import thedarkcolour.exdeorum.recipe.crook.CrookRecipe;
import thedarkcolour.exdeorum.recipe.crucible.CrucibleRecipe;
import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe;
import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe;
@ -41,6 +42,7 @@ public class ERecipeTypes {
public static final RegistryObject<RecipeType<CrucibleRecipe>> WATER_CRUCIBLE = RECIPE_TYPES.register("water_crucible", () -> RecipeType.simple(ERecipeTypes.WATER_CRUCIBLE.getId()));
public static final RegistryObject<RecipeType<HammerRecipe>> HAMMER = RECIPE_TYPES.register("hammer", () -> RecipeType.simple(ERecipeTypes.HAMMER.getId()));
public static final RegistryObject<RecipeType<CrookRecipe>> CROOK = RECIPE_TYPES.register("crook", () -> RecipeType.simple(ERecipeTypes.CROOK.getId()));
public static final RegistryObject<RecipeType<SieveRecipe>> SIEVE = RECIPE_TYPES.register("sieve", () -> RecipeType.simple(ERecipeTypes.SIEVE.getId()));
}

View File

@ -0,0 +1,59 @@
/*
* Ex Deorum
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.recipe;
import io.netty.buffer.Unpooled;
import net.minecraft.SharedConstants;
import net.minecraft.advancements.critereon.StatePropertiesPredicate;
import net.minecraft.core.Direction;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.Bootstrap;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class BlockPredicateTest {
@BeforeEach
void setUp() {
SharedConstants.tryDetectVersion();
Bootstrap.bootStrap();
}
@Test
void networkTest() {
var buffer = new FriendlyByteBuf(Unpooled.buffer());
var single = BlockPredicate.singleBlock(Blocks.DIAMOND_BLOCK);
single.toNetwork(buffer);
assertEquals(single, BlockPredicate.fromNetwork(buffer));
var states = BlockPredicate.blockState(Blocks.OAK_LOG, StatePropertiesPredicate.Builder.properties().hasProperty(BlockStateProperties.AXIS, Direction.Axis.X).build());
states.toNetwork(buffer);
var test = BlockPredicate.fromNetwork(buffer);
assertEquals(states.toJson(), test.toJson());
var tag = BlockPredicate.blockTag(BlockTags.OAK_LOGS);
tag.toNetwork(buffer);
assertEquals(tag, BlockPredicate.fromNetwork(buffer));
}
}

View File

@ -1,6 +1,6 @@
/*
* Ex Deorum
* Copyright (c) 2023 thedarkcolour
* Copyright (c) 2024 thedarkcolour
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package thedarkcolour.exdeorum.test.recipe;
package thedarkcolour.exdeorum.recipe;
import net.minecraft.SharedConstants;
import net.minecraft.WorldVersion;
@ -42,7 +42,7 @@ class RecipeUtilTest {
@Test
void areIngredientsEqual() {
Assertions.assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB), Ingredient.of(Items.OAK_SLAB)));
assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB), Ingredient.of(Items.OAK_SLAB)));
assertFalse(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.BIRCH_SLAB), Ingredient.of(Items.OAK_SLAB)));
assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Tags.Items.GEMS_DIAMOND), Ingredient.of(Tags.Items.GEMS_DIAMOND)));
assertFalse(RecipeUtil.areIngredientsEqual(Ingredient.of(Tags.Items.INGOTS_IRON), Ingredient.of(Tags.Items.GEMS_DIAMOND)));