diff --git a/build.gradle b/build.gradle index 3cb5040e..827b3714 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'org.spongepowered.mixin' version '0.7.+' } -version = '1.20' +version = '1.21' group = 'thedarkcolour.exdeorum' base { archivesName = 'exdeorum' diff --git a/changelog.md b/changelog.md index cb59c249..7c56455e 100644 --- a/changelog.md +++ b/changelog.md @@ -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) diff --git a/logs/debug-1.log.gz b/logs/debug-1.log.gz new file mode 100644 index 00000000..fd8e792e Binary files /dev/null and b/logs/debug-1.log.gz differ diff --git a/logs/debug-2.log.gz b/logs/debug-2.log.gz new file mode 100644 index 00000000..e0b30466 Binary files /dev/null and b/logs/debug-2.log.gz differ diff --git a/logs/debug-3.log.gz b/logs/debug-3.log.gz new file mode 100644 index 00000000..f7778419 Binary files /dev/null and b/logs/debug-3.log.gz differ diff --git a/logs/debug.log b/logs/debug.log new file mode 100644 index 00000000..a4a45f83 --- /dev/null +++ b/logs/debug.log @@ -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.(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.(PlatformDependent.java:88) ~[netty-common-4.1.82.Final.jar:4.1.82.Final] + at io.netty.buffer.UnpooledByteBufAllocator.(UnpooledByteBufAllocator.java:37) ~[netty-buffer-4.1.82.Final.jar:4.1.82.Final] + at io.netty.buffer.Unpooled.(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.(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.(PlatformDependent.java:88) ~[netty-common-4.1.82.Final.jar:4.1.82.Final] + at io.netty.buffer.UnpooledByteBufAllocator.(UnpooledByteBufAllocator.java:37) ~[netty-buffer-4.1.82.Final.jar:4.1.82.Final] + at io.netty.buffer.Unpooled.(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.(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 diff --git a/logs/latest.log b/logs/latest.log new file mode 100644 index 00000000..e69de29b diff --git a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e index ee23721e..52488d5a 100644 --- a/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e +++ b/src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e @@ -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 diff --git a/src/generated/resources/data/exdeorum/recipes/crook/silkworm.json b/src/generated/resources/data/exdeorum/recipes/crook/silkworm.json new file mode 100644 index 00000000..84ba19fc --- /dev/null +++ b/src/generated/resources/data/exdeorum/recipes/crook/silkworm.json @@ -0,0 +1,8 @@ +{ + "type": "exdeorum:crook", + "block_predicate": { + "block_tag": "minecraft:leaves" + }, + "chance": 0.01, + "result": "exdeorum:silk_worm" +} \ No newline at end of file diff --git a/src/generated/resources/data/exdeorum/recipes/crook/silkworm_bonus.json b/src/generated/resources/data/exdeorum/recipes/crook/silkworm_bonus.json new file mode 100644 index 00000000..c88cf1b9 --- /dev/null +++ b/src/generated/resources/data/exdeorum/recipes/crook/silkworm_bonus.json @@ -0,0 +1,11 @@ +{ + "type": "exdeorum:crook", + "block_predicate": { + "block": "exdeorum:infested_leaves", + "state": { + "fully_infested": "true" + } + }, + "chance": 0.01, + "result": "exdeorum:silk_worm" +} \ No newline at end of file diff --git a/src/main/java/thedarkcolour/exdeorum/compat/jei/CrookCategory.java b/src/main/java/thedarkcolour/exdeorum/compat/jei/CrookCategory.java new file mode 100644 index 00000000..9b066364 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/compat/jei/CrookCategory.java @@ -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 . + */ + +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 { + 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 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 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(); + 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(); + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/compat/jei/CrookJeiRecipe.java b/src/main/java/thedarkcolour/exdeorum/compat/jei/CrookJeiRecipe.java new file mode 100644 index 00000000..50090dc5 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/compat/jei/CrookJeiRecipe.java @@ -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 . + */ + +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 states; + public Item result; + public float chance; + + public CrookJeiRecipe(List 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(); + + 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 itemIngredients; + + StatesRecipe(List states, Item result, float chance) { + super(states, result, chance); + ImmutableList.Builder temp = ImmutableList.builder(); + + var blocks = new HashSet(); + + 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 tag; + + public TagRecipe(TagKey tag, List 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); + } + } + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/compat/jei/CycleTimer.java b/src/main/java/thedarkcolour/exdeorum/compat/jei/CycleTimer.java new file mode 100644 index 00000000..3a270914 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/compat/jei/CycleTimer.java @@ -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 . + */ + +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 getCycledItem(List 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; + } + } +} \ No newline at end of file diff --git a/src/main/java/thedarkcolour/exdeorum/compat/jei/ExDeorumJeiPlugin.java b/src/main/java/thedarkcolour/exdeorum/compat/jei/ExDeorumJeiPlugin.java index 5bed7c6f..39237011 100644 --- a/src/main/java/thedarkcolour/exdeorum/compat/jei/ExDeorumJeiPlugin.java +++ b/src/main/java/thedarkcolour/exdeorum/compat/jei/ExDeorumJeiPlugin.java @@ -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 CRUCIBLE_HEAT_SOURCES = RecipeType.create(ExDeorum.ID, "crucible_heat_sources", CrucibleHeatSourceRecipe.class); static final RecipeType SIEVE = RecipeType.create(ExDeorum.ID, "sieve", GroupedSieveRecipe.class); static final RecipeType HAMMER = RecipeType.create(ExDeorum.ID, "hammer", HammerRecipe.class); + static final RecipeType 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(); + 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); diff --git a/src/main/java/thedarkcolour/exdeorum/data/English.java b/src/main/java/thedarkcolour/exdeorum/data/English.java index 71d423da..b947bc0d 100644 --- a/src/main/java/thedarkcolour/exdeorum/data/English.java +++ b/src/main/java/thedarkcolour/exdeorum/data/English.java @@ -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"); diff --git a/src/main/java/thedarkcolour/exdeorum/data/TranslationKeys.java b/src/main/java/thedarkcolour/exdeorum/data/TranslationKeys.java index f53c9e81..5eeec326 100644 --- a/src/main/java/thedarkcolour/exdeorum/data/TranslationKeys.java +++ b/src/main/java/thedarkcolour/exdeorum/data/TranslationKeys.java @@ -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"; diff --git a/src/main/java/thedarkcolour/exdeorum/data/recipe/Recipes.java b/src/main/java/thedarkcolour/exdeorum/data/recipe/Recipes.java index 43937616..f55cc8e6 100644 --- a/src/main/java/thedarkcolour/exdeorum/data/recipe/Recipes.java +++ b/src/main/java/thedarkcolour/exdeorum/data/recipe/Recipes.java @@ -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 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 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 writer) { // plants barrelCompost(writer, "saplings", ingredient(ItemTags.SAPLINGS), 125); diff --git a/src/main/java/thedarkcolour/exdeorum/loot/CrookLootModifier.java b/src/main/java/thedarkcolour/exdeorum/loot/CrookLootModifier.java index 1afc676f..b554269b 100644 --- a/src/main/java/thedarkcolour/exdeorum/loot/CrookLootModifier.java +++ b/src/main/java/thedarkcolour/exdeorum/loot/CrookLootModifier.java @@ -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 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 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 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 codec() { return CODEC; diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/BlockPredicate.java b/src/main/java/thedarkcolour/exdeorum/recipe/BlockPredicate.java new file mode 100644 index 00000000..32b5df13 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/BlockPredicate.java @@ -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 . + */ + +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 { + // used for network + byte SINGLE_BLOCK = 0, BLOCK_STATE = 1, BLOCK_TAG = 2; + + JsonObject toJson(); + + void toNetwork(FriendlyByteBuf buffer); + + Stream 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 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 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 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 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 possibleStates() { + return this.block.getStateDefinition().getPossibleStates().stream(); + } + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java b/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java index 63fba00f..fdd83b7c 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/RecipeUtil.java @@ -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 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 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 getCrookRecipes(BlockState state) { + return crookRecipeCache.getRecipes(state); + } } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/SingleIngredientRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/SingleIngredientRecipe.java index 1d993d44..860e1401 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/SingleIngredientRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/SingleIngredientRecipe.java @@ -35,7 +35,7 @@ import net.minecraft.world.level.Level; */ public abstract class SingleIngredientRecipe implements Recipe { private final ResourceLocation id; - protected final Ingredient ingredient; + public final Ingredient ingredient; public final boolean dependsOnNbt; public SingleIngredientRecipe(ResourceLocation id, Ingredient ingredient) { diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelFluidMixingRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelFluidMixingRecipe.java index 2b3b0d2a..201e55ef 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelFluidMixingRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelFluidMixingRecipe.java @@ -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 diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelMixingRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelMixingRecipe.java index 37322ac1..9a9194d7 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelMixingRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/barrel/FinishedBarrelMixingRecipe.java @@ -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 diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/BarrelFluidMixingRecipeCache.java b/src/main/java/thedarkcolour/exdeorum/recipe/cache/BarrelFluidMixingRecipeCache.java similarity index 97% rename from src/main/java/thedarkcolour/exdeorum/recipe/BarrelFluidMixingRecipeCache.java rename to src/main/java/thedarkcolour/exdeorum/recipe/cache/BarrelFluidMixingRecipeCache.java index ba26f04f..78b720b3 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/BarrelFluidMixingRecipeCache.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/cache/BarrelFluidMixingRecipeCache.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package thedarkcolour.exdeorum.recipe; +package thedarkcolour.exdeorum.recipe.cache; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.level.material.Fluid; diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/cache/CrookRecipeCache.java b/src/main/java/thedarkcolour/exdeorum/recipe/cache/CrookRecipeCache.java new file mode 100644 index 00000000..e2f310e9 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/cache/CrookRecipeCache.java @@ -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 . + */ + +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> recipes; + + public CrookRecipeCache(RecipeManager recipeManager) { + this.recipeManager = recipeManager; + } + + public List 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>(); + + 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, List>(); + + for (var entry : tempRecipes.entrySet()) { + this.recipes.put(entry.getKey(), dedupeMap.computeIfAbsent(entry.getValue(), List::copyOf)); + } + + this.recipeManager = null; + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/SieveRecipeCache.java b/src/main/java/thedarkcolour/exdeorum/recipe/cache/SieveRecipeCache.java similarity index 98% rename from src/main/java/thedarkcolour/exdeorum/recipe/SieveRecipeCache.java rename to src/main/java/thedarkcolour/exdeorum/recipe/cache/SieveRecipeCache.java index 5679ae51..37b562d8 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/SieveRecipeCache.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/cache/SieveRecipeCache.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package thedarkcolour.exdeorum.recipe; +package thedarkcolour.exdeorum.recipe.cache; import com.google.common.collect.ImmutableList; import net.minecraft.world.item.Item; diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/SingleIngredientRecipeCache.java b/src/main/java/thedarkcolour/exdeorum/recipe/cache/SingleIngredientRecipeCache.java similarity index 97% rename from src/main/java/thedarkcolour/exdeorum/recipe/SingleIngredientRecipeCache.java rename to src/main/java/thedarkcolour/exdeorum/recipe/cache/SingleIngredientRecipeCache.java index eed4ec7c..6254a7f7 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/SingleIngredientRecipeCache.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/cache/SingleIngredientRecipeCache.java @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -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 { if (this.simpleRecipes == null) { buildRecipes(); } - //noinspection DataFlowIssue return this.allRecipes; } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/cache/package-info.java b/src/main/java/thedarkcolour/exdeorum/recipe/cache/package-info.java new file mode 100644 index 00000000..81711aae --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/cache/package-info.java @@ -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 . + */ + +@net.minecraft.MethodsReturnNonnullByDefault +@javax.annotation.ParametersAreNonnullByDefault +package thedarkcolour.exdeorum.recipe.cache; diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crook/CrookRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/crook/CrookRecipe.java new file mode 100644 index 00000000..776bc0d6 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crook/CrookRecipe.java @@ -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 . + */ + +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 { + @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 { + @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); + } + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crook/FinishedCrookRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/crook/FinishedCrookRecipe.java new file mode 100644 index 00000000..31b42ae6 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crook/FinishedCrookRecipe.java @@ -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 . + */ + +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(); + } +} diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/crook/package-info.java b/src/main/java/thedarkcolour/exdeorum/recipe/crook/package-info.java new file mode 100644 index 00000000..9513bdd4 --- /dev/null +++ b/src/main/java/thedarkcolour/exdeorum/recipe/crook/package-info.java @@ -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 . + */ + +@net.minecraft.MethodsReturnNonnullByDefault +@javax.annotation.ParametersAreNonnullByDefault +package thedarkcolour.exdeorum.recipe.crook; diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/hammer/FinishedHammerRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/hammer/FinishedHammerRecipe.java index 3e6b38e3..7ac47031 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/hammer/FinishedHammerRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/hammer/FinishedHammerRecipe.java @@ -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)); } diff --git a/src/main/java/thedarkcolour/exdeorum/recipe/sieve/FinishedSieveRecipe.java b/src/main/java/thedarkcolour/exdeorum/recipe/sieve/FinishedSieveRecipe.java index 40ab2056..9c06acac 100644 --- a/src/main/java/thedarkcolour/exdeorum/recipe/sieve/FinishedSieveRecipe.java +++ b/src/main/java/thedarkcolour/exdeorum/recipe/sieve/FinishedSieveRecipe.java @@ -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()); }); diff --git a/src/main/java/thedarkcolour/exdeorum/registry/ERecipeSerializers.java b/src/main/java/thedarkcolour/exdeorum/registry/ERecipeSerializers.java index 28b0762d..d5061c0c 100644 --- a/src/main/java/thedarkcolour/exdeorum/registry/ERecipeSerializers.java +++ b/src/main/java/thedarkcolour/exdeorum/registry/ERecipeSerializers.java @@ -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> BARREL_FLUID_MIXING = RECIPE_SERIALIZERS.register("barrel_fluid_mixing", BarrelFluidMixingRecipe.Serializer::new); public static final RegistryObject> HAMMER = RECIPE_SERIALIZERS.register("hammer", HammerRecipe.Serializer::new); + public static final RegistryObject> CROOK = RECIPE_SERIALIZERS.register("crook", CrookRecipe.Serializer::new); public static final RegistryObject> LAVA_CRUCIBLE = RECIPE_SERIALIZERS.register("lava_crucible", () -> new CrucibleRecipe.Serializer(ERecipeTypes.LAVA_CRUCIBLE.get())); public static final RegistryObject> WATER_CRUCIBLE = RECIPE_SERIALIZERS.register("water_crucible", () -> new CrucibleRecipe.Serializer(ERecipeTypes.WATER_CRUCIBLE.get())); diff --git a/src/main/java/thedarkcolour/exdeorum/registry/ERecipeTypes.java b/src/main/java/thedarkcolour/exdeorum/registry/ERecipeTypes.java index e7892780..cd841d2a 100644 --- a/src/main/java/thedarkcolour/exdeorum/registry/ERecipeTypes.java +++ b/src/main/java/thedarkcolour/exdeorum/registry/ERecipeTypes.java @@ -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> WATER_CRUCIBLE = RECIPE_TYPES.register("water_crucible", () -> RecipeType.simple(ERecipeTypes.WATER_CRUCIBLE.getId())); public static final RegistryObject> HAMMER = RECIPE_TYPES.register("hammer", () -> RecipeType.simple(ERecipeTypes.HAMMER.getId())); + public static final RegistryObject> CROOK = RECIPE_TYPES.register("crook", () -> RecipeType.simple(ERecipeTypes.CROOK.getId())); public static final RegistryObject> SIEVE = RECIPE_TYPES.register("sieve", () -> RecipeType.simple(ERecipeTypes.SIEVE.getId())); } diff --git a/src/test/java/thedarkcolour/exdeorum/recipe/BlockPredicateTest.java b/src/test/java/thedarkcolour/exdeorum/recipe/BlockPredicateTest.java new file mode 100644 index 00000000..f884f257 --- /dev/null +++ b/src/test/java/thedarkcolour/exdeorum/recipe/BlockPredicateTest.java @@ -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 . + */ + +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)); + } +} \ No newline at end of file diff --git a/src/test/java/thedarkcolour/exdeorum/test/recipe/RecipeUtilTest.java b/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java similarity index 91% rename from src/test/java/thedarkcolour/exdeorum/test/recipe/RecipeUtilTest.java rename to src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java index 9a0592d8..bf8486ce 100644 --- a/src/test/java/thedarkcolour/exdeorum/test/recipe/RecipeUtilTest.java +++ b/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java @@ -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 . */ -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)));