feat: working block implementation
This commit is contained in:
parent
23981fb9ca
commit
802bbb6c7b
31 changed files with 1580 additions and 51 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -19,3 +19,5 @@ hs_err_pid*
|
|||
|
||||
# Common working directory
|
||||
run
|
||||
/src/generated/resources/.cache/
|
||||
/repo/
|
||||
|
|
|
|||
71
.kotlin/errors/errors-1775391978696.log
Normal file
71
.kotlin/errors/errors-1775391978696.log
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
kotlin version: 2.0.0
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 1. The daemon process output:
|
||||
... (53 more lines)
|
||||
54. at java.base/sun.nio.ch.Net.bind0(Native Method)
|
||||
55. at java.base/sun.nio.ch.Net.bind(Net.java:555)
|
||||
56. at java.base/sun.nio.ch.Net.bind(Net.java:544)
|
||||
57. at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:640)
|
||||
58. at java.base/java.net.ServerSocket.bind(ServerSocket.java:392)
|
||||
59. at java.base/java.net.ServerSocket.<init>(ServerSocket.java:274)
|
||||
60. at org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface$ServerLoopbackSocketFactory.createServerSocket(NetworkUtils.kt:69)
|
||||
61. at java.rmi/sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:673)
|
||||
62. at java.rmi/sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:344)
|
||||
63. ... 14 more
|
||||
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #2 with error code: 1. The daemon process output:
|
||||
... (53 more lines)
|
||||
54. at java.base/sun.nio.ch.Net.bind0(Native Method)
|
||||
55. at java.base/sun.nio.ch.Net.bind(Net.java:555)
|
||||
56. at java.base/sun.nio.ch.Net.bind(Net.java:544)
|
||||
57. at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:640)
|
||||
58. at java.base/java.net.ServerSocket.bind(ServerSocket.java:392)
|
||||
59. at java.base/java.net.ServerSocket.<init>(ServerSocket.java:274)
|
||||
60. at org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface$ServerLoopbackSocketFactory.createServerSocket(NetworkUtils.kt:69)
|
||||
61. at java.rmi/sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:673)
|
||||
62. at java.rmi/sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:344)
|
||||
63. ... 14 more
|
||||
|
||||
error message: Failed connecting to the daemon in 3 retries
|
||||
|
||||
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
|
||||
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
|
||||
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
|
||||
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
|
||||
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:187)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:120)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:162)
|
||||
at org.gradle.internal.Factories$1.create(Factories.java:31)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:264)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:128)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:133)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:157)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:126)
|
||||
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
|
||||
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
|
||||
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
|
||||
at java.base/java.lang.Thread.run(Thread.java:833)
|
||||
|
||||
|
||||
71
.kotlin/errors/errors-1775393382933.log
Normal file
71
.kotlin/errors/errors-1775393382933.log
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
kotlin version: 2.0.0
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 1. The daemon process output:
|
||||
... (53 more lines)
|
||||
54. at java.base/sun.nio.ch.Net.bind0(Native Method)
|
||||
55. at java.base/sun.nio.ch.Net.bind(Net.java:565)
|
||||
56. at java.base/sun.nio.ch.Net.bind(Net.java:554)
|
||||
57. at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:636)
|
||||
58. at java.base/java.net.ServerSocket.bind(ServerSocket.java:391)
|
||||
59. at java.base/java.net.ServerSocket.<init>(ServerSocket.java:278)
|
||||
60. at org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface$ServerLoopbackSocketFactory.createServerSocket(NetworkUtils.kt:69)
|
||||
61. at java.rmi/sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:672)
|
||||
62. at java.rmi/sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:344)
|
||||
63. ... 14 more
|
||||
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #2 with error code: 1. The daemon process output:
|
||||
... (53 more lines)
|
||||
54. at java.base/sun.nio.ch.Net.bind0(Native Method)
|
||||
55. at java.base/sun.nio.ch.Net.bind(Net.java:565)
|
||||
56. at java.base/sun.nio.ch.Net.bind(Net.java:554)
|
||||
57. at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:636)
|
||||
58. at java.base/java.net.ServerSocket.bind(ServerSocket.java:391)
|
||||
59. at java.base/java.net.ServerSocket.<init>(ServerSocket.java:278)
|
||||
60. at org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface$ServerLoopbackSocketFactory.createServerSocket(NetworkUtils.kt:69)
|
||||
61. at java.rmi/sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:672)
|
||||
62. at java.rmi/sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:344)
|
||||
63. ... 14 more
|
||||
|
||||
error message: Failed connecting to the daemon in 3 retries
|
||||
|
||||
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
|
||||
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
|
||||
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
|
||||
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
|
||||
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:187)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:120)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:162)
|
||||
at org.gradle.internal.Factories$1.create(Factories.java:31)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:264)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:128)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:133)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:157)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:126)
|
||||
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
|
||||
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
|
||||
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
|
||||
at java.base/java.lang.Thread.run(Thread.java:1583)
|
||||
|
||||
|
||||
71
.kotlin/errors/errors-1775393603849.log
Normal file
71
.kotlin/errors/errors-1775393603849.log
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
kotlin version: 2.0.0
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 1. The daemon process output:
|
||||
... (53 more lines)
|
||||
54. at java.base/sun.nio.ch.Net.bind0(Native Method)
|
||||
55. at java.base/sun.nio.ch.Net.bind(Net.java:565)
|
||||
56. at java.base/sun.nio.ch.Net.bind(Net.java:554)
|
||||
57. at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:636)
|
||||
58. at java.base/java.net.ServerSocket.bind(ServerSocket.java:391)
|
||||
59. at java.base/java.net.ServerSocket.<init>(ServerSocket.java:278)
|
||||
60. at org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface$ServerLoopbackSocketFactory.createServerSocket(NetworkUtils.kt:69)
|
||||
61. at java.rmi/sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:672)
|
||||
62. at java.rmi/sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:344)
|
||||
63. ... 14 more
|
||||
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #2 with error code: 1. The daemon process output:
|
||||
... (53 more lines)
|
||||
54. at java.base/sun.nio.ch.Net.bind0(Native Method)
|
||||
55. at java.base/sun.nio.ch.Net.bind(Net.java:565)
|
||||
56. at java.base/sun.nio.ch.Net.bind(Net.java:554)
|
||||
57. at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:636)
|
||||
58. at java.base/java.net.ServerSocket.bind(ServerSocket.java:391)
|
||||
59. at java.base/java.net.ServerSocket.<init>(ServerSocket.java:278)
|
||||
60. at org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface$ServerLoopbackSocketFactory.createServerSocket(NetworkUtils.kt:69)
|
||||
61. at java.rmi/sun.rmi.transport.tcp.TCPEndpoint.newServerSocket(TCPEndpoint.java:672)
|
||||
62. at java.rmi/sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:344)
|
||||
63. ... 14 more
|
||||
|
||||
error message: Failed connecting to the daemon in 3 retries
|
||||
|
||||
error message: Daemon compilation failed: Could not connect to Kotlin compile daemon
|
||||
java.lang.RuntimeException: Could not connect to Kotlin compile daemon
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemon(GradleKotlinCompilerWork.kt:214)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.compileWithDaemonOrFallbackImpl(GradleKotlinCompilerWork.kt:159)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork.run(GradleKotlinCompilerWork.kt:111)
|
||||
at org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction.execute(GradleCompilerRunnerWithWorkers.kt:76)
|
||||
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:100)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
|
||||
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:166)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
|
||||
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
|
||||
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
|
||||
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
|
||||
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$0(DefaultWorkerExecutor.java:174)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:187)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:120)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:162)
|
||||
at org.gradle.internal.Factories$1.create(Factories.java:31)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:264)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:128)
|
||||
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:133)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:157)
|
||||
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:126)
|
||||
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
|
||||
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
|
||||
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
|
||||
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
|
||||
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
|
||||
at java.base/java.lang.Thread.run(Thread.java:1583)
|
||||
|
||||
|
||||
104
EnchantmentTransfer.ipr
Normal file
104
EnchantmentTransfer.ipr
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac"/>
|
||||
<resourceExtensions>
|
||||
<entry name=".+\.(properties|xml|html|dtd|tld)"/>
|
||||
<entry name=".+\.(gif|png|jpeg|jpg)"/>
|
||||
</resourceExtensions>
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.class"/>
|
||||
<entry name="!?*.scala"/>
|
||||
<entry name="!?*.groovy"/>
|
||||
<entry name="!?*.java"/>
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing enabled="false" useClasspath="true"/>
|
||||
<bytecodeTargetLevel target="21"/>
|
||||
</component>
|
||||
<component name="CopyrightManager" default="">
|
||||
<module2copyright/>
|
||||
</component>
|
||||
<component name="DependencyValidationManager">
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false"/>
|
||||
</component>
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false"/>
|
||||
<component name="GradleUISettings">
|
||||
<setting name="root"/>
|
||||
</component>
|
||||
<component name="GradleUISettings2">
|
||||
<setting name="root"/>
|
||||
</component>
|
||||
<component name="IdProvider" IDEtalkID="11DA1DB66DD62DDA1ED602B7079FE97C"/>
|
||||
<component name="JavadocGenerationManager">
|
||||
<option name="OUTPUT_DIRECTORY"/>
|
||||
<option name="OPTION_SCOPE" value="protected"/>
|
||||
<option name="OPTION_HIERARCHY" value="true"/>
|
||||
<option name="OPTION_NAVIGATOR" value="true"/>
|
||||
<option name="OPTION_INDEX" value="true"/>
|
||||
<option name="OPTION_SEPARATE_INDEX" value="true"/>
|
||||
<option name="OPTION_DOCUMENT_TAG_USE" value="false"/>
|
||||
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false"/>
|
||||
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false"/>
|
||||
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true"/>
|
||||
<option name="OPTION_DEPRECATED_LIST" value="true"/>
|
||||
<option name="OTHER_OPTIONS" value=""/>
|
||||
<option name="HEAP_SIZE"/>
|
||||
<option name="LOCALE"/>
|
||||
<option name="OPEN_IN_BROWSER" value="true"/>
|
||||
</component>
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/EnchantmentTransfer.iml" filepath="$PROJECT_DIR$/EnchantmentTransfer.iml"/>
|
||||
</modules>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" assert-keyword="true" jdk-15="true" project-jdk-type="JavaSDK" assert-jdk-15="true" project-jdk-name="21">
|
||||
<output url="file://$PROJECT_DIR$/out"/>
|
||||
</component>
|
||||
<component name="SvnBranchConfigurationManager">
|
||||
<option name="mySupportsUserInfoFilter" value="true"/>
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs=""/>
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
<state key="ArtifactsStructureConfigurable.UI">
|
||||
<UIState>
|
||||
<splitter-proportions>
|
||||
<SplitterProportionsDataImpl/>
|
||||
</splitter-proportions>
|
||||
<settings/>
|
||||
</UIState>
|
||||
</state>
|
||||
<state key="Copyright.UI">
|
||||
<UIState>
|
||||
<splitter-proportions>
|
||||
<SplitterProportionsDataImpl/>
|
||||
</splitter-proportions>
|
||||
</UIState>
|
||||
</state>
|
||||
<state key="ProjectJDKs.UI">
|
||||
<UIState>
|
||||
<splitter-proportions>
|
||||
<SplitterProportionsDataImpl>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2"/>
|
||||
</list>
|
||||
</option>
|
||||
</SplitterProportionsDataImpl>
|
||||
</splitter-proportions>
|
||||
<last-edited>1.6</last-edited>
|
||||
</UIState>
|
||||
</state>
|
||||
<state key="ScopeChooserConfigurable.UI">
|
||||
<UIState>
|
||||
<splitter-proportions>
|
||||
<SplitterProportionsDataImpl/>
|
||||
</splitter-proportions>
|
||||
<settings/>
|
||||
</UIState>
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
</project>
|
||||
207
EnchantmentTransfer.iws
Normal file
207
EnchantmentTransfer.iws
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<option name="TRACKING_ENABLED" value="true"/>
|
||||
<option name="SHOW_DIALOG" value="false"/>
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true"/>
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false"/>
|
||||
<option name="LAST_RESOLUTION" value="IGNORE"/>
|
||||
</component>
|
||||
<component name="ChangesViewManager" flattened_view="true" show_ignored="false"/>
|
||||
<component name="CreatePatchCommitExecutor">
|
||||
<option name="PATCH_PATH" value=""/>
|
||||
<option name="REVERSE_PATCH" value="false"/>
|
||||
</component>
|
||||
<component name="DaemonCodeAnalyzer">
|
||||
<disable_hints/>
|
||||
</component>
|
||||
<component name="DebuggerManager">
|
||||
<breakpoint_any>
|
||||
<breakpoint>
|
||||
<option name="NOTIFY_CAUGHT" value="true"/>
|
||||
<option name="NOTIFY_UNCAUGHT" value="true"/>
|
||||
<option name="ENABLED" value="false"/>
|
||||
<option name="LOG_ENABLED" value="false"/>
|
||||
<option name="LOG_EXPRESSION_ENABLED" value="false"/>
|
||||
<option name="SUSPEND_POLICY" value="SuspendAll"/>
|
||||
<option name="COUNT_FILTER_ENABLED" value="false"/>
|
||||
<option name="COUNT_FILTER" value="0"/>
|
||||
<option name="CONDITION_ENABLED" value="false"/>
|
||||
<option name="CLASS_FILTERS_ENABLED" value="false"/>
|
||||
<option name="INSTANCE_FILTERS_ENABLED" value="false"/>
|
||||
<option name="CONDITION" value=""/>
|
||||
<option name="LOG_MESSAGE" value=""/>
|
||||
</breakpoint>
|
||||
<breakpoint>
|
||||
<option name="NOTIFY_CAUGHT" value="true"/>
|
||||
<option name="NOTIFY_UNCAUGHT" value="true"/>
|
||||
<option name="ENABLED" value="false"/>
|
||||
<option name="LOG_ENABLED" value="false"/>
|
||||
<option name="LOG_EXPRESSION_ENABLED" value="false"/>
|
||||
<option name="SUSPEND_POLICY" value="SuspendAll"/>
|
||||
<option name="COUNT_FILTER_ENABLED" value="false"/>
|
||||
<option name="COUNT_FILTER" value="0"/>
|
||||
<option name="CONDITION_ENABLED" value="false"/>
|
||||
<option name="CLASS_FILTERS_ENABLED" value="false"/>
|
||||
<option name="INSTANCE_FILTERS_ENABLED" value="false"/>
|
||||
<option name="CONDITION" value=""/>
|
||||
<option name="LOG_MESSAGE" value=""/>
|
||||
</breakpoint>
|
||||
</breakpoint_any>
|
||||
<breakpoint_rules/>
|
||||
<ui_properties/>
|
||||
</component>
|
||||
<component name="ModuleEditorState">
|
||||
<option name="LAST_EDITED_MODULE_NAME"/>
|
||||
<option name="LAST_EDITED_TAB_NAME"/>
|
||||
</component>
|
||||
<component name="ProjectInspectionProfilesVisibleTreeState">
|
||||
<entry key="Project Default">
|
||||
<profile-state/>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager">
|
||||
<OptionsSetting value="true" id="Add"/>
|
||||
<OptionsSetting value="true" id="Remove"/>
|
||||
<OptionsSetting value="true" id="Checkout"/>
|
||||
<OptionsSetting value="true" id="Update"/>
|
||||
<OptionsSetting value="true" id="Status"/>
|
||||
<OptionsSetting value="true" id="Edit"/>
|
||||
<ConfirmationsSetting value="0" id="Add"/>
|
||||
<ConfirmationsSetting value="0" id="Remove"/>
|
||||
</component>
|
||||
<component name="ProjectReloadState">
|
||||
<option name="STATE" value="0"/>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="GoToFile.includeJavaFiles" value="false"/>
|
||||
<property name="GoToClass.toSaveIncludeLibraries" value="false"/>
|
||||
<property name="MemberChooser.sorted" value="false"/>
|
||||
<property name="MemberChooser.showClasses" value="true"/>
|
||||
<property name="GoToClass.includeLibraries" value="false"/>
|
||||
<property name="MemberChooser.copyJavadoc" value="false"/>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration default="true" type="Remote" factoryName="Remote">
|
||||
<option name="USE_SOCKET_TRANSPORT" value="true"/>
|
||||
<option name="SERVER_MODE" value="false"/>
|
||||
<option name="SHMEM_ADDRESS" value="javadebug"/>
|
||||
<option name="HOST" value="localhost"/>
|
||||
<option name="PORT" value="5005"/>
|
||||
<method>
|
||||
<option name="BuildArtifacts" enabled="false"/>
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="Applet" factoryName="Applet">
|
||||
<module name=""/>
|
||||
<option name="MAIN_CLASS_NAME"/>
|
||||
<option name="HTML_FILE_NAME"/>
|
||||
<option name="HTML_USED" value="false"/>
|
||||
<option name="WIDTH" value="400"/>
|
||||
<option name="HEIGHT" value="300"/>
|
||||
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy"/>
|
||||
<option name="VM_PARAMETERS"/>
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false"/>
|
||||
<option name="ALTERNATIVE_JRE_PATH"/>
|
||||
<method>
|
||||
<option name="BuildArtifacts" enabled="false"/>
|
||||
<option name="Make" enabled="true"/>
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="Application" factoryName="Application">
|
||||
<extension name="coverage" enabled="false" merge="false"/>
|
||||
<option name="MAIN_CLASS_NAME"/>
|
||||
<option name="VM_PARAMETERS"/>
|
||||
<option name="PROGRAM_PARAMETERS"/>
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$"/>
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false"/>
|
||||
<option name="ALTERNATIVE_JRE_PATH"/>
|
||||
<option name="ENABLE_SWING_INSPECTOR" value="false"/>
|
||||
<option name="ENV_VARIABLES"/>
|
||||
<option name="PASS_PARENT_ENVS" value="true"/>
|
||||
<module name=""/>
|
||||
<envs/>
|
||||
<method>
|
||||
<option name="BuildArtifacts" enabled="false"/>
|
||||
<option name="Make" enabled="true"/>
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="JUnit" factoryName="JUnit">
|
||||
<extension name="coverage" enabled="false" merge="false"/>
|
||||
<module name=""/>
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false"/>
|
||||
<option name="ALTERNATIVE_JRE_PATH"/>
|
||||
<option name="PACKAGE_NAME"/>
|
||||
<option name="MAIN_CLASS_NAME"/>
|
||||
<option name="METHOD_NAME"/>
|
||||
<option name="TEST_OBJECT" value="class"/>
|
||||
<option name="VM_PARAMETERS"/>
|
||||
<option name="PARAMETERS"/>
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$"/>
|
||||
<option name="ENV_VARIABLES"/>
|
||||
<option name="PASS_PARENT_ENVS" value="true"/>
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="moduleWithDependencies"/>
|
||||
</option>
|
||||
<envs/>
|
||||
<method>
|
||||
<option name="BuildArtifacts" enabled="false"/>
|
||||
<option name="Make" enabled="true"/>
|
||||
</method>
|
||||
</configuration>
|
||||
<list size="0"/>
|
||||
<configuration name="<template>" type="WebApp" default="true" selected="false">
|
||||
<Host>localhost</Host>
|
||||
<Port>5050</Port>
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="ShelveChangesManager" show_recycled="false"/>
|
||||
<component name="SvnConfiguration" maxAnnotateRevisions="500">
|
||||
<option name="USER" value=""/>
|
||||
<option name="PASSWORD" value=""/>
|
||||
<option name="LAST_MERGED_REVISION"/>
|
||||
<option name="UPDATE_RUN_STATUS" value="false"/>
|
||||
<option name="MERGE_DRY_RUN" value="false"/>
|
||||
<option name="MERGE_DIFF_USE_ANCESTRY" value="true"/>
|
||||
<option name="UPDATE_LOCK_ON_DEMAND" value="false"/>
|
||||
<option name="IGNORE_SPACES_IN_MERGE" value="false"/>
|
||||
<option name="DETECT_NESTED_COPIES" value="true"/>
|
||||
<option name="IGNORE_SPACES_IN_ANNOTATE" value="true"/>
|
||||
<option name="SHOW_MERGE_SOURCES_IN_ANNOTATE" value="true"/>
|
||||
<myIsUseDefaultProxy>false</myIsUseDefaultProxy>
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task"/>
|
||||
<servers/>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="true"/>
|
||||
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="true"/>
|
||||
<option name="PERFORM_UPDATE_IN_BACKGROUND" value="true"/>
|
||||
<option name="PERFORM_COMMIT_IN_BACKGROUND" value="true"/>
|
||||
<option name="PERFORM_EDIT_IN_BACKGROUND" value="true"/>
|
||||
<option name="PERFORM_CHECKOUT_IN_BACKGROUND" value="true"/>
|
||||
<option name="PERFORM_ADD_REMOVE_IN_BACKGROUND" value="true"/>
|
||||
<option name="PERFORM_ROLLBACK_IN_BACKGROUND" value="false"/>
|
||||
<option name="CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND" value="false"/>
|
||||
<option name="ENABLE_BACKGROUND_PROCESSES" value="false"/>
|
||||
<option name="CHANGED_ON_SERVER_INTERVAL" value="60"/>
|
||||
<option name="FORCE_NON_EMPTY_COMMENT" value="false"/>
|
||||
<option name="LAST_COMMIT_MESSAGE"/>
|
||||
<option name="MAKE_NEW_CHANGELIST_ACTIVE" value="true"/>
|
||||
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="false"/>
|
||||
<option name="CHECK_FILES_UP_TO_DATE_BEFORE_COMMIT" value="false"/>
|
||||
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="false"/>
|
||||
<option name="REFORMAT_BEFORE_FILE_COMMIT" value="false"/>
|
||||
<option name="FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION" value="0.8"/>
|
||||
<option name="FILE_HISTORY_DIALOG_SPLITTER_PROPORTION" value="0.5"/>
|
||||
<option name="ACTIVE_VCS_NAME"/>
|
||||
<option name="UPDATE_GROUP_BY_PACKAGES" value="false"/>
|
||||
<option name="UPDATE_GROUP_BY_CHANGELIST" value="false"/>
|
||||
<option name="SHOW_FILE_HISTORY_AS_TREE" value="false"/>
|
||||
<option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6"/>
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager/>
|
||||
</component>
|
||||
</project>
|
||||
51
README.en.md
Normal file
51
README.en.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
[Русская версия](README.md)
|
||||
|
||||
# Enchantment Transfer Mod
|
||||
|
||||
A mod for Minecraft 1.21.1 that adds a machine for transferring enchantments between items.
|
||||
|
||||
## Features
|
||||
|
||||
- **Enchantment Transfer**: Transfers enchantments from one item to another (as well as to books)
|
||||
- **Charge System**: Machine requires energy in the form of items
|
||||
- **Redstone Control**: Only works with redstone signal
|
||||
- **Processing Progress**: Processing time depends on amount and level of enchantments
|
||||
|
||||
## Accepted Fuel Sources
|
||||
|
||||
| Item | Charge |
|
||||
|-----------------|-------|
|
||||
| Redstone | 16 |
|
||||
| Copper Ingot | 1 |
|
||||
| Iron Ingot | 4 |
|
||||
| Gold Ingot | 2 |
|
||||
| Diamond | 32 |
|
||||
| Netherite Ingot | 64 |
|
||||
|
||||
Maximum charge capacity: 1 000 000 units
|
||||
|
||||
## How to Use
|
||||
|
||||
1. Place the **Enchantment Transferrer** block in the world
|
||||
2. Put an enchanted item, target item and, optionally, a **book**
|
||||
3. Put **fuel items** in the fuel slot
|
||||
4. Provide a **redstone signal** to activate
|
||||
5. Wait for the process to complete
|
||||
|
||||
## Installation
|
||||
|
||||
1. Install NeoForge 21.1.219 for Minecraft 1.21.1
|
||||
2. Place the `.jar` mod file in the `mods` folder
|
||||
3. Launch the game
|
||||
|
||||
## Building
|
||||
|
||||
```bash
|
||||
gradlew.bat build
|
||||
```
|
||||
|
||||
The built file will be located in `build/libs/`
|
||||
|
||||
## 3rd-party Assets
|
||||
|
||||
UI and block textures were taken from [Ycarx/artoftecharium](https://github.com/Ycarx/artoftecharium) and altered to suite my needs.
|
||||
51
README.md
Normal file
51
README.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
[English version](README.en.md)
|
||||
|
||||
# Мод Enchantment Transfer
|
||||
|
||||
Мод для Minecraft 1.21.1, добавляющий машину для переноса зачарований.
|
||||
|
||||
## Возможности
|
||||
|
||||
- **Перенос зачарований**: Переносит зачарования с одного предмета на другой (в т.ч. - на книги)
|
||||
- **Система заряда**: Машина требует энергию в виде предметов
|
||||
- **Редстоун контроль**: Работает только при наличии редстоун сигнала
|
||||
- **Прогресс обработки**: Время обработки зависит от количества и уровня зачарований
|
||||
|
||||
## Принимаемые источники энергии
|
||||
|
||||
| Предмет | Заряд |
|
||||
|----------|-------|
|
||||
| Редстоун | 16 |
|
||||
| Медь | 1 |
|
||||
| Железо | 4 |
|
||||
| Золото | 2 |
|
||||
| Алмаз | 32 |
|
||||
| Незерит | 64 |
|
||||
|
||||
Максимальная вместимость заряда: 1 000 000 единиц
|
||||
|
||||
## Как использовать
|
||||
|
||||
1. Поместите **Enchantment Transferrer** в мир
|
||||
2. Поместите зачарованный предмет, целевой предмет в **средний слот**, опционально - книгу
|
||||
3. Поместите **топливо** в слот
|
||||
4. Подайте **редстоун сигнал** для активации
|
||||
5. Дождитесь завершения процесса
|
||||
|
||||
## Установка
|
||||
|
||||
1. Установите NeoForge 21.1.219 для Minecraft 1.21.1
|
||||
2. Поместите `.jar` файл мода в папку `mods`
|
||||
3. Запустите игру
|
||||
|
||||
## Сборка
|
||||
|
||||
```bash
|
||||
gradlew.bat build
|
||||
```
|
||||
|
||||
Собранный файл будет находиться в `build/libs/`
|
||||
|
||||
## Чужие ассеты
|
||||
|
||||
Текстуры для UI и блоков были взяты из [Ycarx/artoftecharium](https://github.com/Ycarx/artoftecharium) из изменены по потребности
|
||||
|
|
@ -3,7 +3,7 @@ plugins {
|
|||
id 'maven-publish'
|
||||
id 'idea'
|
||||
id 'net.neoforged.moddev' version '2.0.141'
|
||||
id 'org.jetbrains.kotlin.jvm' version '2.0.0'
|
||||
id 'org.jetbrains.kotlin.jvm' version '2.3.0'
|
||||
}
|
||||
|
||||
version = mod_version
|
||||
|
|
@ -103,7 +103,7 @@ sourceSets.main.resources { srcDir 'src/generated/resources' }
|
|||
|
||||
|
||||
dependencies {
|
||||
implementation 'thedarkcolour:kotlinforforge-neoforge:5.3.0'
|
||||
implementation 'thedarkcolour:kotlinforforge-neoforge:5.11.0'
|
||||
|
||||
// Example mod dependency with JEI
|
||||
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
|
||||
|
|
|
|||
18
generate_textures.py
Normal file
18
generate_textures.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
from PIL import Image
|
||||
import os
|
||||
|
||||
textures_dir = "src/main/resources/assets/enct/textures/block"
|
||||
os.makedirs(textures_dir, exist_ok=True)
|
||||
|
||||
colors = {
|
||||
"enchantment_transferrer_top": (120, 80, 200),
|
||||
"enchantment_transferrer_bottom": (80, 80, 80),
|
||||
"enchantment_transferrer_side": (100, 100, 120),
|
||||
"enchantment_transferrer_front": (140, 100, 220),
|
||||
}
|
||||
|
||||
for name, color in colors.items():
|
||||
img = Image.new('RGBA', (16, 16), color + (255,))
|
||||
img.save(f"{textures_dir}/{name}.png", 'PNG')
|
||||
|
||||
print("Textures generated successfully!")
|
||||
|
|
@ -4,6 +4,7 @@ org.gradle.daemon=true
|
|||
org.gradle.parallel=true
|
||||
org.gradle.caching=true
|
||||
org.gradle.configuration-cache=true
|
||||
kotlin.compiler.execution.strategy=in-process
|
||||
## Environment Properties
|
||||
# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge
|
||||
# The Minecraft version must agree with the Neo version to get a valid artifact
|
||||
|
|
@ -35,6 +36,6 @@ mod_version=1.0.0
|
|||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
mod_group_id=xyz.nuark.mcmod
|
||||
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
|
||||
mod_authors=
|
||||
mod_authors=nuark
|
||||
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
|
||||
mod_description=
|
||||
mod_description=Ever been in a situation, when you have new toy, but now you need to move enchantments from previous one? Say no more!
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"criteria": {
|
||||
"has_ench_table": {
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": "minecraft:enchanting_table"
|
||||
}
|
||||
]
|
||||
},
|
||||
"trigger": "minecraft:inventory_changed"
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"conditions": {
|
||||
"recipe": "enct:enchantment_transferrer"
|
||||
},
|
||||
"trigger": "minecraft:recipe_unlocked"
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_the_recipe",
|
||||
"has_ench_table"
|
||||
]
|
||||
],
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"enct:enchantment_transferrer"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "redstone",
|
||||
"key": {
|
||||
"B": {
|
||||
"item": "minecraft:blaze_rod"
|
||||
},
|
||||
"E": {
|
||||
"item": "minecraft:enchanting_table"
|
||||
},
|
||||
"I": {
|
||||
"item": "minecraft:iron_block"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
"III",
|
||||
"BEB",
|
||||
"III"
|
||||
],
|
||||
"result": {
|
||||
"count": 1,
|
||||
"id": "enct:enchantment_transferrer"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +1,83 @@
|
|||
package xyz.nuark.mcmod.enct
|
||||
|
||||
import xyz.nuark.mcmod.enct.block.ModBlocks
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.world.flag.FeatureFlags
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
import net.minecraft.world.item.CreativeModeTabs
|
||||
import net.neoforged.bus.api.SubscribeEvent
|
||||
import net.neoforged.fml.common.EventBusSubscriber
|
||||
import net.neoforged.fml.common.Mod
|
||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent
|
||||
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent
|
||||
import net.neoforged.fml.event.lifecycle.FMLDedicatedServerSetupEvent
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent
|
||||
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent
|
||||
import net.neoforged.neoforge.network.IContainerFactory
|
||||
import net.neoforged.neoforge.registries.DeferredHolder
|
||||
import net.neoforged.neoforge.registries.DeferredRegister
|
||||
import org.apache.logging.log4j.Level
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Logger
|
||||
import thedarkcolour.kotlinforforge.neoforge.forge.MOD_BUS
|
||||
import thedarkcolour.kotlinforforge.neoforge.forge.runForDist
|
||||
import xyz.nuark.mcmod.enct.block.ModBlocks
|
||||
import xyz.nuark.mcmod.enct.block.entity.EnchantmentTransferrerBlockEntity
|
||||
import xyz.nuark.mcmod.enct.menu.EnchantmentTransferrerMenu
|
||||
import xyz.nuark.mcmod.enct.screen.EnchantmentTransferrerScreen
|
||||
import java.util.function.Supplier
|
||||
|
||||
/**
|
||||
* Main mod class.
|
||||
*
|
||||
* An example for blocks is in the `blocks` package of this mod.
|
||||
*/
|
||||
@Mod(Enchantmenttransfer.ID)
|
||||
@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD)
|
||||
@EventBusSubscriber
|
||||
object Enchantmenttransfer {
|
||||
const val ID = "enct"
|
||||
|
||||
// the logger for our mod
|
||||
val LOGGER: Logger = LogManager.getLogger(ID)
|
||||
val LOGGER = LogManager.getLogger(ID)
|
||||
|
||||
val MENU_TYPES: DeferredRegister<MenuType<*>> = DeferredRegister.create(Registries.MENU, ID)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val ENCHANTMENT_TRANSFERRER_MENU_TYPE: DeferredHolder<MenuType<*>, MenuType<EnchantmentTransferrerMenu>> = MENU_TYPES.register("enchantment_transferrer", Supplier {
|
||||
MenuType<EnchantmentTransferrerMenu>(
|
||||
IContainerFactory { containerId, playerInventory, buf ->
|
||||
val pos = buf.readBlockPos()
|
||||
val level = playerInventory.player.level()
|
||||
val blockEntity = level.getBlockEntity(pos) as? EnchantmentTransferrerBlockEntity
|
||||
if (blockEntity != null) {
|
||||
EnchantmentTransferrerMenu(containerId, playerInventory, blockEntity, blockEntity.dataAccess)
|
||||
} else {
|
||||
throw IllegalStateException("BlockEntity not found at $pos")
|
||||
}
|
||||
},
|
||||
FeatureFlags.VANILLA_SET
|
||||
)
|
||||
})
|
||||
|
||||
init {
|
||||
LOGGER.log(Level.INFO, "Hello world!")
|
||||
ModBlocks.register(MOD_BUS)
|
||||
MENU_TYPES.register(MOD_BUS)
|
||||
|
||||
// Register the KDeferredRegister to the mod-specific event bus
|
||||
ModBlocks.REGISTRY.register(MOD_BUS)
|
||||
|
||||
val obj = runForDist(clientTarget = {
|
||||
MOD_BUS.addListener(::onClientSetup)
|
||||
Minecraft.getInstance()
|
||||
}, serverTarget = {
|
||||
MOD_BUS.addListener(::onServerSetup)
|
||||
"test"
|
||||
})
|
||||
|
||||
println(obj)
|
||||
MOD_BUS.addListener<net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent> { event ->
|
||||
event.registerBlockEntity(
|
||||
Capabilities.ItemHandler.BLOCK,
|
||||
ModBlocks.ENCHANTMENT_TRANSFERRER_BE.value(),
|
||||
{ be, side -> be.getHandlerForSide(side) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used for initializing client specific
|
||||
* things such as renderers and keymaps
|
||||
* Fired on the mod specific event bus.
|
||||
*/
|
||||
private fun onClientSetup(event: FMLClientSetupEvent) {
|
||||
@SubscribeEvent
|
||||
fun onBuildCreativeTabContents(event: BuildCreativeModeTabContentsEvent) {
|
||||
if (event.tabKey == CreativeModeTabs.REDSTONE_BLOCKS) {
|
||||
event.accept(ModBlocks.ENCHANTMENT_TRANSFERRER_ITEM.get())
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onClientSetup(event: FMLClientSetupEvent) {
|
||||
LOGGER.log(Level.INFO, "Initializing client...")
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired on the global Forge bus.
|
||||
*/
|
||||
private fun onServerSetup(event: FMLDedicatedServerSetupEvent) {
|
||||
LOGGER.log(Level.INFO, "Server starting...")
|
||||
@SubscribeEvent
|
||||
fun onRegisterMenuScreens(event: RegisterMenuScreensEvent) {
|
||||
event.register(ENCHANTMENT_TRANSFERRER_MENU_TYPE.value(), ::EnchantmentTransferrerScreen)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
package xyz.nuark.mcmod.enct.block
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import xyz.nuark.mcmod.enct.block.entity.EnchantmentTransferrerBlockEntity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.neoforged.neoforge.capabilities.Capabilities
|
||||
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent
|
||||
import org.jetbrains.annotations.Nullable
|
||||
|
||||
class EnchantmentTransferrerBlock(properties: Properties) : BaseEntityBlock(properties) {
|
||||
|
||||
companion object {
|
||||
val CODEC: MapCodec<EnchantmentTransferrerBlock> = MapCodec.unit { EnchantmentTransferrerBlock(Properties.of()) }
|
||||
|
||||
fun registerCapabilities(event: RegisterCapabilitiesEvent) {
|
||||
event.registerBlockEntity(
|
||||
Capabilities.ItemHandler.BLOCK,
|
||||
ModBlocks.ENCHANTMENT_TRANSFERRER_BE.value(),
|
||||
) { be, side ->
|
||||
be.getHandlerForSide(side)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun codec(): MapCodec<out EnchantmentTransferrerBlock> = CODEC
|
||||
|
||||
@Nullable
|
||||
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity? {
|
||||
return EnchantmentTransferrerBlockEntity(pos, state)
|
||||
}
|
||||
|
||||
override fun useWithoutItem(
|
||||
state: BlockState,
|
||||
level: Level,
|
||||
pos: BlockPos,
|
||||
player: Player,
|
||||
hitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
if (level.isClientSide) {
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
|
||||
val blockEntity = level.getBlockEntity(pos)
|
||||
if (blockEntity is EnchantmentTransferrerBlockEntity) {
|
||||
player.openMenu(blockEntity) { buf ->
|
||||
buf.writeBlockPos(pos)
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.CONSUME
|
||||
}
|
||||
|
||||
override fun setPlacedBy(level: Level, pos: BlockPos, state: BlockState, @Nullable placer: LivingEntity?, stack: ItemStack) {
|
||||
super.setPlacedBy(level, pos, state, placer, stack)
|
||||
if (level.isClientSide) return
|
||||
|
||||
val blockEntity = level.getBlockEntity(pos)
|
||||
// TODO: Maybe link machine to player? XP usage instead of fuel :thinking:
|
||||
}
|
||||
|
||||
override fun onRemove(state: BlockState, level: Level, pos: BlockPos, newState: BlockState, isMoving: Boolean) {
|
||||
if (state.block !== newState.block) {
|
||||
val blockEntity = level.getBlockEntity(pos)
|
||||
if (blockEntity is EnchantmentTransferrerBlockEntity) {
|
||||
for (i in 0 until EnchantmentTransferrerBlockEntity.TOTAL_SLOTS) {
|
||||
val stack = blockEntity.getItemHandler().getStackInSlot(i)
|
||||
if (!stack.isEmpty) {
|
||||
popResource(level, pos, stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onRemove(state, level, pos, newState, isMoving)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRenderShape(state: BlockState): RenderShape {
|
||||
return RenderShape.MODEL
|
||||
}
|
||||
|
||||
@Nullable
|
||||
override fun <T : BlockEntity> getTicker(
|
||||
level: Level,
|
||||
state: BlockState,
|
||||
type: BlockEntityType<T>
|
||||
): BlockEntityTicker<T>? {
|
||||
if (level.isClientSide) return null
|
||||
|
||||
val blockEntityType = ModBlocks.ENCHANTMENT_TRANSFERRER_BE.value()
|
||||
if (type !== blockEntityType) return null
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return BlockEntityTicker<T> { l, pos, s, be ->
|
||||
EnchantmentTransferrerBlockEntity.serverTick(l, pos, s, be as EnchantmentTransferrerBlockEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,41 @@
|
|||
package xyz.nuark.mcmod.enct.block
|
||||
|
||||
import xyz.nuark.mcmod.enct.Enchantmenttransfer
|
||||
import xyz.nuark.mcmod.enct.block.entity.EnchantmentTransferrerBlockEntity
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.world.item.BlockItem
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import net.neoforged.neoforge.registries.DeferredRegister
|
||||
|
||||
// THIS LINE IS REQUIRED FOR USING PROPERTY DELEGATES
|
||||
import thedarkcolour.kotlinforforge.neoforge.forge.getValue
|
||||
import net.neoforged.neoforge.registries.DeferredHolder
|
||||
import java.util.function.Supplier
|
||||
|
||||
object ModBlocks {
|
||||
val REGISTRY = DeferredRegister.createBlocks(Enchantmenttransfer.ID)
|
||||
val BLOCKS = DeferredRegister.create(Registries.BLOCK, Enchantmenttransfer.ID)
|
||||
val ITEMS = DeferredRegister.create(Registries.ITEM, Enchantmenttransfer.ID)
|
||||
val BLOCK_ENTITIES = DeferredRegister.create(Registries.BLOCK_ENTITY_TYPE, Enchantmenttransfer.ID)
|
||||
|
||||
// If you get an "overload resolution ambiguity" error, include the arrow at the start of the closure.
|
||||
val EXAMPLE_BLOCK by REGISTRY.register("example_block") { ->
|
||||
Block(BlockBehaviour.Properties.of().lightLevel { 15 }.strength(3.0f))
|
||||
val ENCHANTMENT_TRANSFERRER: DeferredHolder<Block, Block> = BLOCKS.register("enchantment_transferrer", Supplier {
|
||||
EnchantmentTransferrerBlock(BlockBehaviour.Properties.of().strength(3.0f).requiresCorrectToolForDrops())
|
||||
})
|
||||
|
||||
val ENCHANTMENT_TRANSFERRER_ITEM: DeferredHolder<Item, Item> = ITEMS.register("enchantment_transferrer", Supplier {
|
||||
BlockItem(ENCHANTMENT_TRANSFERRER.get(), Item.Properties())
|
||||
})
|
||||
|
||||
val ENCHANTMENT_TRANSFERRER_BE: DeferredHolder<BlockEntityType<*>, BlockEntityType<EnchantmentTransferrerBlockEntity>> = BLOCK_ENTITIES.register("enchantment_transferrer", Supplier {
|
||||
BlockEntityType.Builder.of(
|
||||
{ pos, state -> EnchantmentTransferrerBlockEntity(pos, state) },
|
||||
ENCHANTMENT_TRANSFERRER.get()
|
||||
).build(null)
|
||||
})
|
||||
|
||||
fun register(eventBus: IEventBus) {
|
||||
BLOCKS.register(eventBus)
|
||||
ITEMS.register(eventBus)
|
||||
BLOCK_ENTITIES.register(eventBus)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,339 @@
|
|||
package xyz.nuark.mcmod.enct.block.entity
|
||||
|
||||
import xyz.nuark.mcmod.enct.Enchantmenttransfer
|
||||
import xyz.nuark.mcmod.enct.block.ModBlocks
|
||||
import xyz.nuark.mcmod.enct.menu.EnchantmentTransferrerMenu
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.component.DataComponents
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.protocol.Packet
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.Nameable
|
||||
import net.minecraft.world.WorldlyContainer
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.ContainerData
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper
|
||||
import net.minecraft.world.item.enchantment.ItemEnchantments
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.neoforged.neoforge.items.IItemHandler
|
||||
import net.neoforged.neoforge.items.ItemStackHandler
|
||||
import net.neoforged.neoforge.items.wrapper.SidedInvWrapper
|
||||
import org.jetbrains.annotations.Nullable
|
||||
|
||||
class EnchantmentTransferrerBlockEntity(
|
||||
pos: BlockPos,
|
||||
state: BlockState
|
||||
) : BlockEntity(ModBlocks.ENCHANTMENT_TRANSFERRER_BE.value(), pos, state), MenuProvider, Nameable, WorldlyContainer {
|
||||
|
||||
companion object {
|
||||
const val SLOT_MAIN = 0
|
||||
const val SLOT_BOOK = 1
|
||||
const val SLOT_TARGET = 2
|
||||
const val SLOT_FUEL = 3
|
||||
const val TOTAL_SLOTS = 4
|
||||
|
||||
const val MAX_CHARGE = 1_000_000
|
||||
|
||||
// Charge values for different items
|
||||
val CHARGE_VALUES = mapOf(
|
||||
Items.COPPER_INGOT to 1,
|
||||
Items.IRON_INGOT to 4,
|
||||
Items.GOLD_INGOT to 2,
|
||||
Items.DIAMOND to 32,
|
||||
Items.NETHERITE_INGOT to 64,
|
||||
Items.REDSTONE to 16
|
||||
)
|
||||
|
||||
// Base time per enchantment (in ticks)
|
||||
const val BASE_TIME_PER_ENCHANTMENT = 100
|
||||
|
||||
@JvmStatic
|
||||
fun serverTick(level: Level, pos: BlockPos, state: BlockState, be: EnchantmentTransferrerBlockEntity) {
|
||||
be.tick()
|
||||
}
|
||||
}
|
||||
|
||||
private val itemHandler = object : ItemStackHandler(TOTAL_SLOTS) {
|
||||
override fun isItemValid(slot: Int, stack: ItemStack): Boolean {
|
||||
return when (slot) {
|
||||
SLOT_MAIN -> EnchantmentHelper.hasAnyEnchantments(stack)
|
||||
SLOT_TARGET -> !EnchantmentHelper.hasAnyEnchantments(stack) && EnchantmentHelper.canStoreEnchantments(stack)
|
||||
SLOT_BOOK -> stack.item == Items.BOOK || stack.item == Items.ENCHANTED_BOOK
|
||||
SLOT_FUEL -> CHARGE_VALUES.containsKey(stack.item)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSlotsForFace(side: Direction): IntArray {
|
||||
return when (side) {
|
||||
Direction.UP -> intArrayOf(SLOT_BOOK)
|
||||
Direction.DOWN -> intArrayOf()
|
||||
else -> intArrayOf(SLOT_FUEL)
|
||||
}
|
||||
}
|
||||
|
||||
override fun canPlaceItemThroughFace(index: Int, itemStack: ItemStack, @Nullable direction: Direction?): Boolean {
|
||||
return itemHandler.isItemValid(index, itemStack)
|
||||
}
|
||||
|
||||
override fun canTakeItemThroughFace(index: Int, itemStack: ItemStack, direction: Direction): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getContainerSize(): Int = TOTAL_SLOTS
|
||||
|
||||
override fun isEmpty(): Boolean = (0 until TOTAL_SLOTS).all { itemHandler.getStackInSlot(it).isEmpty }
|
||||
|
||||
override fun getItem(slot: Int): ItemStack = itemHandler.getStackInSlot(slot)
|
||||
|
||||
override fun removeItem(slot: Int, amount: Int): ItemStack {
|
||||
return itemHandler.extractItem(slot, amount, false)
|
||||
}
|
||||
|
||||
override fun removeItemNoUpdate(slot: Int): ItemStack {
|
||||
val stack = itemHandler.getStackInSlot(slot)
|
||||
itemHandler.setStackInSlot(slot, ItemStack.EMPTY)
|
||||
return stack
|
||||
}
|
||||
|
||||
override fun setItem(slot: Int, stack: ItemStack) {
|
||||
itemHandler.setStackInSlot(slot, stack)
|
||||
}
|
||||
|
||||
override fun stillValid(player: Player): Boolean = true
|
||||
|
||||
override fun clearContent() {
|
||||
for (i in 0 until TOTAL_SLOTS) {
|
||||
itemHandler.setStackInSlot(i, ItemStack.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
private val handlerUp = SidedInvWrapper(this, Direction.UP)
|
||||
private val handlerSides = SidedInvWrapper(this, Direction.NORTH)
|
||||
|
||||
private var charge: Int = 0
|
||||
private var processTime: Int = 0
|
||||
private var totalTime: Int = 0
|
||||
private var isProcessing: Boolean = false
|
||||
private var wasPowered: Boolean = false
|
||||
|
||||
// ContainerData for GUI sync
|
||||
val dataAccess = object : ContainerData {
|
||||
override fun get(index: Int): Int = when (index) {
|
||||
0 -> this@EnchantmentTransferrerBlockEntity.charge
|
||||
1 -> this@EnchantmentTransferrerBlockEntity.processTime
|
||||
2 -> this@EnchantmentTransferrerBlockEntity.totalTime
|
||||
3 -> if (this@EnchantmentTransferrerBlockEntity.isProcessing) 1 else 0
|
||||
else -> 0
|
||||
}
|
||||
|
||||
override fun set(index: Int, value: Int) {
|
||||
when (index) {
|
||||
0 -> this@EnchantmentTransferrerBlockEntity.charge = value
|
||||
1 -> this@EnchantmentTransferrerBlockEntity.processTime = value
|
||||
2 -> this@EnchantmentTransferrerBlockEntity.totalTime = value
|
||||
3 -> this@EnchantmentTransferrerBlockEntity.isProcessing = value == 1
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCount(): Int = 4
|
||||
}
|
||||
|
||||
fun getItemHandler(): IItemHandler = itemHandler
|
||||
|
||||
fun getHandlerForSide(side: Direction?): IItemHandler? {
|
||||
return when (side) {
|
||||
Direction.UP -> handlerUp
|
||||
Direction.DOWN -> null
|
||||
else -> handlerSides
|
||||
}
|
||||
}
|
||||
|
||||
override fun getName(): Component = Component.translatable("block.${Enchantmenttransfer.ID}.enchantment_transferrer")
|
||||
|
||||
override fun getDisplayName(): Component = name
|
||||
|
||||
override fun createMenu(containerId: Int, playerInventory: Inventory, player: Player): AbstractContainerMenu {
|
||||
return EnchantmentTransferrerMenu(containerId, playerInventory, this, dataAccess)
|
||||
}
|
||||
|
||||
override fun saveAdditional(tag: CompoundTag, registries: net.minecraft.core.HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registries)
|
||||
tag.put("items", itemHandler.serializeNBT(registries))
|
||||
tag.putInt("charge", charge)
|
||||
tag.putInt("processTime", processTime)
|
||||
tag.putInt("totalTime", totalTime)
|
||||
tag.putBoolean("isProcessing", isProcessing)
|
||||
}
|
||||
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
|
||||
itemHandler.deserializeNBT(registries, tag.getCompound("items"))
|
||||
charge = tag.getInt("charge")
|
||||
processTime = tag.getInt("processTime")
|
||||
totalTime = tag.getInt("totalTime")
|
||||
isProcessing = tag.getBoolean("isProcessing")
|
||||
|
||||
setChanged()
|
||||
}
|
||||
|
||||
override fun getUpdateTag(registries: HolderLookup.Provider): CompoundTag {
|
||||
val tag = CompoundTag()
|
||||
saveAdditional(tag, registries)
|
||||
return tag
|
||||
}
|
||||
|
||||
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
|
||||
return ClientboundBlockEntityDataPacket.create(this)
|
||||
}
|
||||
|
||||
private fun tick() {
|
||||
if (level?.isClientSide == true) return
|
||||
|
||||
val isPowered = level?.hasNeighborSignal(worldPosition) == true
|
||||
|
||||
if (charge < MAX_CHARGE) {
|
||||
consumeFuel()
|
||||
}
|
||||
|
||||
if (!isPowered) {
|
||||
if (wasPowered) {
|
||||
setChanged()
|
||||
}
|
||||
wasPowered = false
|
||||
return
|
||||
}
|
||||
|
||||
wasPowered = true
|
||||
|
||||
if (!isProcessing) {
|
||||
if (canProcess()) {
|
||||
startProcessing()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (charge > 0) {
|
||||
if (!canProcess()) {
|
||||
processTime = 0
|
||||
setChanged()
|
||||
return
|
||||
}
|
||||
|
||||
processTime++
|
||||
charge--
|
||||
|
||||
if (processTime >= totalTime) {
|
||||
finishProcessing()
|
||||
}
|
||||
setChanged()
|
||||
level?.sendBlockUpdated(worldPosition, blockState, blockState, 3)
|
||||
}
|
||||
}
|
||||
|
||||
private fun consumeFuel() {
|
||||
val stack = getItem(SLOT_FUEL)
|
||||
if (!stack.isEmpty) {
|
||||
val chargeValue = CHARGE_VALUES[stack.item] ?: 0
|
||||
if (chargeValue > 0 && charge + chargeValue <= MAX_CHARGE) {
|
||||
stack.shrink(1)
|
||||
setItem(SLOT_FUEL, stack)
|
||||
charge += chargeValue
|
||||
setChanged()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun canProcess(): Boolean {
|
||||
val mainStack = getItem(SLOT_MAIN)
|
||||
if (mainStack.isEmpty || !EnchantmentHelper.hasAnyEnchantments(mainStack)) return false
|
||||
|
||||
val targetStack = getItem(SLOT_TARGET)
|
||||
|
||||
val mainEnchantments = EnchantmentHelper.getEnchantmentsForCrafting(mainStack)
|
||||
if (mainEnchantments.isEmpty) return false
|
||||
|
||||
val targetEnchantments = EnchantmentHelper.getEnchantmentsForCrafting(targetStack)
|
||||
if (!targetEnchantments.isEmpty) return false
|
||||
|
||||
val hasValidTarget = !targetStack.isEmpty
|
||||
return hasValidTarget
|
||||
}
|
||||
|
||||
private fun startProcessing() {
|
||||
val mainStack = getItem(SLOT_MAIN)
|
||||
val mainEnchantments = EnchantmentHelper.getEnchantmentsForCrafting(mainStack).entrySet()
|
||||
|
||||
var totalLevels = 0
|
||||
mainEnchantments.forEach { entry ->
|
||||
totalLevels += entry.intValue
|
||||
}
|
||||
|
||||
val enchantmentCount = mainEnchantments.size
|
||||
val avgLevel = if (enchantmentCount > 0) totalLevels.toFloat() / enchantmentCount else 1f
|
||||
totalTime = (enchantmentCount * avgLevel * BASE_TIME_PER_ENCHANTMENT).toInt().coerceAtLeast(100)
|
||||
|
||||
processTime = 0
|
||||
isProcessing = true
|
||||
setChanged()
|
||||
}
|
||||
|
||||
private fun finishProcessing() {
|
||||
val mainStack = getItem(SLOT_MAIN)
|
||||
val targetStack = getItem(SLOT_TARGET)
|
||||
val bookStack = getItem(SLOT_BOOK)
|
||||
|
||||
val originalEnchantments = EnchantmentHelper.getEnchantmentsForCrafting(mainStack).entrySet()
|
||||
val (possible, impossible) = originalEnchantments.partition { targetStack.supportsEnchantment(it.key) }
|
||||
|
||||
val possibleEnchantments = ItemEnchantments.Mutable(ItemEnchantments.EMPTY).apply {
|
||||
possible.forEach{
|
||||
set(it.key, it.intValue)
|
||||
}
|
||||
}.toImmutable()
|
||||
val impossibleEnchantments = ItemEnchantments.Mutable(ItemEnchantments.EMPTY).apply {
|
||||
impossible.forEach{
|
||||
set(it.key, it.intValue)
|
||||
}
|
||||
}.toImmutable()
|
||||
|
||||
if (possible.isNotEmpty()) {
|
||||
EnchantmentHelper.setEnchantments(targetStack, possibleEnchantments)
|
||||
}
|
||||
if (bookStack.isEmpty) {
|
||||
setItem(SLOT_MAIN, mainStack.apply {
|
||||
set(DataComponents.ENCHANTMENTS, impossibleEnchantments)
|
||||
})
|
||||
} else {
|
||||
setItem(SLOT_MAIN, mainStack.apply {
|
||||
set(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY)
|
||||
})
|
||||
setItem(SLOT_BOOK, ItemStack(Items.ENCHANTED_BOOK).apply {
|
||||
EnchantmentHelper.setEnchantments(this, impossibleEnchantments)
|
||||
})
|
||||
}
|
||||
|
||||
resetProcessing()
|
||||
}
|
||||
|
||||
private fun resetProcessing() {
|
||||
processTime = 0
|
||||
totalTime = 0
|
||||
isProcessing = false
|
||||
setChanged()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package xyz.nuark.mcmod.enct.datagen
|
||||
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.data.DataGenerator
|
||||
import net.minecraft.data.PackOutput
|
||||
import net.neoforged.bus.api.SubscribeEvent
|
||||
import net.neoforged.fml.common.EventBusSubscriber
|
||||
import net.neoforged.neoforge.data.event.GatherDataEvent
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
@EventBusSubscriber
|
||||
object DataGenerators {
|
||||
|
||||
@SubscribeEvent
|
||||
fun gatherData(event: GatherDataEvent) {
|
||||
val generator: DataGenerator = event.generator
|
||||
val packOutput: PackOutput = generator.packOutput
|
||||
val registries: CompletableFuture<HolderLookup.Provider> = event.lookupProvider
|
||||
|
||||
if (event.includeServer()) {
|
||||
generator.addProvider(true, ModRecipeProvider(packOutput, registries))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package xyz.nuark.mcmod.enct.datagen
|
||||
|
||||
import xyz.nuark.mcmod.enct.block.ModBlocks
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.data.PackOutput
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.data.recipes.RecipeProvider
|
||||
import net.minecraft.data.recipes.ShapedRecipeBuilder
|
||||
import net.minecraft.world.item.Items
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class ModRecipeProvider(
|
||||
output: PackOutput,
|
||||
registries: CompletableFuture<HolderLookup.Provider>
|
||||
) : RecipeProvider(output, registries) {
|
||||
|
||||
override fun buildRecipes(recipeOutput: RecipeOutput) {
|
||||
ShapedRecipeBuilder.shaped(RecipeCategory.REDSTONE, ModBlocks.ENCHANTMENT_TRANSFERRER_ITEM.get())
|
||||
.define('I', Items.IRON_BLOCK)
|
||||
.define('B', Items.BLAZE_ROD)
|
||||
.define('E', Items.ENCHANTING_TABLE)
|
||||
.pattern("III")
|
||||
.pattern("BEB")
|
||||
.pattern("III")
|
||||
.unlockedBy("has_ench_table", has(Items.ENCHANTING_TABLE))
|
||||
.save(recipeOutput)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
package xyz.nuark.mcmod.enct.menu
|
||||
|
||||
import xyz.nuark.mcmod.enct.Enchantmenttransfer
|
||||
import xyz.nuark.mcmod.enct.block.entity.EnchantmentTransferrerBlockEntity
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.ContainerData
|
||||
import net.minecraft.world.inventory.SimpleContainerData
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper
|
||||
import xyz.nuark.mcmod.enct.block.entity.EnchantmentTransferrerBlockEntity.Companion.CHARGE_VALUES
|
||||
|
||||
class EnchantmentTransferrerMenu(
|
||||
containerId: Int,
|
||||
private val playerInventory: Inventory,
|
||||
private val container: Container,
|
||||
private val data: ContainerData = SimpleContainerData(4)
|
||||
) : AbstractContainerMenu(Enchantmenttransfer.ENCHANTMENT_TRANSFERRER_MENU_TYPE.value(), containerId) {
|
||||
|
||||
init {
|
||||
checkContainerSize(container, EnchantmentTransferrerBlockEntity.TOTAL_SLOTS)
|
||||
checkContainerDataCount(data, 4)
|
||||
|
||||
// Block inventory slots
|
||||
addSlot(object : Slot(container, EnchantmentTransferrerBlockEntity.SLOT_MAIN, 35, 23) {
|
||||
override fun mayPlace(stack: ItemStack): Boolean = EnchantmentHelper.hasAnyEnchantments(stack)
|
||||
})
|
||||
addSlot(object : Slot(container, EnchantmentTransferrerBlockEntity.SLOT_BOOK, 65, 23) {
|
||||
override fun mayPlace(stack: ItemStack): Boolean = stack.item == Items.BOOK || stack.item == Items.ENCHANTED_BOOK
|
||||
|
||||
override fun getMaxStackSize(): Int = 1
|
||||
})
|
||||
addSlot(object : Slot(container, EnchantmentTransferrerBlockEntity.SLOT_TARGET, 124, 23) {
|
||||
override fun mayPlace(stack: ItemStack): Boolean = !EnchantmentHelper.hasAnyEnchantments(stack) && EnchantmentHelper.canStoreEnchantments(stack)
|
||||
})
|
||||
addSlot(object : Slot(container, EnchantmentTransferrerBlockEntity.SLOT_FUEL, 3, 23) {
|
||||
override fun mayPlace(stack: ItemStack): Boolean = CHARGE_VALUES.containsKey(stack.item)
|
||||
})
|
||||
|
||||
// Player inventory slots
|
||||
for (row in 0 until 3) {
|
||||
for (col in 0 until 9) {
|
||||
addSlot(Slot(playerInventory, col + row * 9 + 9, 8 + col * 18, 72 + row * 18))
|
||||
}
|
||||
}
|
||||
// Player hotbar
|
||||
for (col in 0 until 9) {
|
||||
addSlot(Slot(playerInventory, col, 8 + col * 18, 130))
|
||||
}
|
||||
|
||||
addDataSlots(data)
|
||||
}
|
||||
|
||||
override fun stillValid(player: Player): Boolean {
|
||||
return container.stillValid(player)
|
||||
}
|
||||
|
||||
override fun quickMoveStack(player: Player, index: Int): ItemStack {
|
||||
var movedStack = ItemStack.EMPTY
|
||||
val slot = this.slots[index]
|
||||
|
||||
if (slot.hasItem()) {
|
||||
val slotStack = slot.item
|
||||
movedStack = slotStack.copy()
|
||||
|
||||
if (index < EnchantmentTransferrerBlockEntity.TOTAL_SLOTS) {
|
||||
if (!this.moveItemStackTo(slotStack, EnchantmentTransferrerBlockEntity.TOTAL_SLOTS, this.slots.size, true)) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
} else {
|
||||
val item = slotStack.item
|
||||
|
||||
if (CHARGE_VALUES.containsKey(item)) {
|
||||
if (!this.moveItemStackTo(slotStack, EnchantmentTransferrerBlockEntity.SLOT_FUEL, EnchantmentTransferrerBlockEntity.SLOT_FUEL+1, false)) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
} else {
|
||||
if (!this.moveItemStackTo(slotStack, 0, EnchantmentTransferrerBlockEntity.SLOT_FUEL, false)) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (slotStack.isEmpty) {
|
||||
slot.setByPlayer(ItemStack.EMPTY)
|
||||
} else {
|
||||
slot.setChanged()
|
||||
}
|
||||
|
||||
if (slotStack.count == movedStack.count) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
slot.onTake(player, slotStack)
|
||||
}
|
||||
|
||||
return movedStack
|
||||
}
|
||||
|
||||
fun getCharge(): Int = data.get(0)
|
||||
fun getProcessTime(): Int = data.get(1)
|
||||
fun getTotalTime(): Int = data.get(2)
|
||||
fun isProcessing(): Boolean = data.get(3) == 1
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
package xyz.nuark.mcmod.enct.screen
|
||||
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import xyz.nuark.mcmod.enct.Enchantmenttransfer
|
||||
import xyz.nuark.mcmod.enct.block.entity.EnchantmentTransferrerBlockEntity
|
||||
import xyz.nuark.mcmod.enct.menu.EnchantmentTransferrerMenu
|
||||
|
||||
class EnchantmentTransferrerScreen(
|
||||
menu: EnchantmentTransferrerMenu,
|
||||
playerInventory: Inventory,
|
||||
title: Component
|
||||
) : AbstractContainerScreen<EnchantmentTransferrerMenu>(menu, playerInventory, title) {
|
||||
|
||||
companion object {
|
||||
val BACKGROUND_LOCATION: ResourceLocation = ResourceLocation.fromNamespaceAndPath(Enchantmenttransfer.ID, "textures/gui/enchantment_transferrer.png")
|
||||
val PROGRESS_GAUGE: ResourceLocation = ResourceLocation.fromNamespaceAndPath(Enchantmenttransfer.ID, "textures/gui/ets_gauge.png")
|
||||
|
||||
const val GAUGE_WIDTH = 117
|
||||
const val GAUGE_HEIGHT = 7
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
|
||||
imageWidth = 176
|
||||
imageHeight = 154
|
||||
}
|
||||
|
||||
override fun renderBg(guiGraphics: GuiGraphics, partialTick: Float, mouseX: Int, mouseY: Int) {
|
||||
guiGraphics.blit(BACKGROUND_LOCATION, leftPos, topPos, 0, 0, imageWidth, imageHeight)
|
||||
|
||||
// Progress bar
|
||||
if (menu.isProcessing()) {
|
||||
val progress = menu.getProcessTime()
|
||||
val total = menu.getTotalTime()
|
||||
if (total > 0) {
|
||||
val progressWidth = ((progress.toDouble() / total) * GAUGE_WIDTH).toInt()
|
||||
guiGraphics.blit(PROGRESS_GAUGE, leftPos+33, topPos+5, 0f, 0f, progressWidth, GAUGE_HEIGHT, GAUGE_WIDTH, GAUGE_HEIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
// Charge bar
|
||||
val charge = menu.getCharge()
|
||||
val maxCharge = EnchantmentTransferrerBlockEntity.MAX_CHARGE
|
||||
if (charge > 0) {
|
||||
val chargeWidth = ((charge.toDouble() / maxCharge) * GAUGE_WIDTH).toInt()
|
||||
guiGraphics.blit(PROGRESS_GAUGE, leftPos+33, topPos+50, 0f, 0f, chargeWidth, GAUGE_HEIGHT, GAUGE_WIDTH, GAUGE_HEIGHT)
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderLabels(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
// No labels for me, thanks
|
||||
}
|
||||
|
||||
override fun renderTooltip(guiGraphics: GuiGraphics, x: Int, y: Int) {
|
||||
val xRange = (leftPos + 33)..(leftPos + 33 + GAUGE_WIDTH)
|
||||
|
||||
when (y) {
|
||||
in (topPos + 5)..(topPos + 5 + GAUGE_HEIGHT) if x in xRange -> { // Over progress bar
|
||||
val progress = menu.getProcessTime()
|
||||
val total = menu.getTotalTime()
|
||||
val processing = menu.isProcessing()
|
||||
|
||||
val status = if (total > 0 && processing) {
|
||||
val perc = ((progress.toDouble() / total) * 100).toInt()
|
||||
"$perc%"
|
||||
} else if (total > 0) {
|
||||
Component.translatable("container.enct.processing.waiting").withColor(0xFFFF00)
|
||||
} else {
|
||||
Component.translatable("container.enct.processing.idle").withColor(0x00FFFF)
|
||||
}
|
||||
|
||||
guiGraphics.renderTooltip(
|
||||
this.font,
|
||||
Component.translatable("container.enct.processing", status),
|
||||
x,
|
||||
y
|
||||
)
|
||||
}
|
||||
in (topPos + 50)..(topPos + 50 + GAUGE_HEIGHT) if x in xRange -> { // Over charge bar
|
||||
val charge = menu.getCharge()
|
||||
guiGraphics.renderTooltip(
|
||||
this.font,
|
||||
Component.translatable("container.enct.charge", charge.toString()),
|
||||
x,
|
||||
y
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
val hoveredSlot = this.hoveredSlot
|
||||
if (hoveredSlot != null && !hoveredSlot.hasItem()) { // Showing tooltips for empty slots
|
||||
when (hoveredSlot.slotIndex) {
|
||||
EnchantmentTransferrerBlockEntity.SLOT_MAIN -> guiGraphics.renderTooltip(
|
||||
this.font,
|
||||
Component.translatable("container.enct.info.main"),
|
||||
x,
|
||||
y
|
||||
)
|
||||
EnchantmentTransferrerBlockEntity.SLOT_TARGET -> guiGraphics.renderTooltip(
|
||||
this.font,
|
||||
Component.translatable("container.enct.info.target"),
|
||||
x,
|
||||
y
|
||||
)
|
||||
EnchantmentTransferrerBlockEntity.SLOT_BOOK -> guiGraphics.renderTooltip(
|
||||
this.font,
|
||||
Component.translatable("container.enct.info.book"),
|
||||
x,
|
||||
y
|
||||
)
|
||||
EnchantmentTransferrerBlockEntity.SLOT_FUEL -> guiGraphics.renderTooltip(
|
||||
this.font,
|
||||
Component.translatable("container.enct.info.fuel"),
|
||||
x,
|
||||
y
|
||||
)
|
||||
}
|
||||
} else {
|
||||
super.renderTooltip(guiGraphics, x, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
renderBackground(guiGraphics, mouseX, mouseY, partialTick)
|
||||
super.render(guiGraphics, mouseX, mouseY, partialTick)
|
||||
renderTooltip(guiGraphics, mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"variants": {
|
||||
"": {
|
||||
"model": "enct:block/enchantment_transferrer"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,12 @@
|
|||
{
|
||||
"itemGroup.enct": "Example Mod Tab",
|
||||
"block.enct.example_block": "Example Block",
|
||||
"item.enct.example_item": "Example Item"
|
||||
"block.enct.enchantment_transferrer": "Enchantment Transferrer",
|
||||
"container.enct.enchantment_transferrer": "Enchantment Transferrer",
|
||||
"container.enct.charge": "Charge: %s",
|
||||
"container.enct.processing": "Process: %s",
|
||||
"container.enct.processing.waiting": "waiting",
|
||||
"container.enct.processing.idle": "idle",
|
||||
"container.enct.info.main": "Item with enchantments",
|
||||
"container.enct.info.target": "Item to transfer enchantments to",
|
||||
"container.enct.info.book": "Optional book",
|
||||
"container.enct.info.fuel": "\"Charge\" fuel: copper, iron, gold, diamonds, redstone or netherite"
|
||||
}
|
||||
|
|
|
|||
12
src/main/resources/assets/enct/lang/ru_ru.json
Normal file
12
src/main/resources/assets/enct/lang/ru_ru.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"block.enct.enchantment_transferrer": "Переносчик зачарований",
|
||||
"container.enct.enchantment_transferrer": "Переносчик зачарований",
|
||||
"container.enct.charge": "Заряд: %s",
|
||||
"container.enct.processing": "Процесс: %s",
|
||||
"container.enct.processing.waiting": "ждём",
|
||||
"container.enct.processing.idle": "спим",
|
||||
"container.enct.info.main": "Зачарованный предмет",
|
||||
"container.enct.info.target": "Цель для переноса",
|
||||
"container.enct.info.book": "Опциональная книга",
|
||||
"container.enct.info.fuel": "Топливо для \"заряда\": медь, железо, золото, алмазы, редстоун or незерит"
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"parent": "block/cube",
|
||||
"textures": {
|
||||
"down": "enct:block/enchantment_transferrer_bottom",
|
||||
"up": "enct:block/enchantment_transferrer_top",
|
||||
"north": "enct:block/enchantment_transferrer_side",
|
||||
"east": "enct:block/enchantment_transferrer_side",
|
||||
"south": "enct:block/enchantment_transferrer_side",
|
||||
"west": "enct:block/enchantment_transferrer_side",
|
||||
"particle": "enct:block/enchantment_transferrer_top"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "enct:block/enchantment_transferrer"
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
BIN
src/main/resources/assets/enct/textures/gui/ets_gauge.png
Normal file
BIN
src/main/resources/assets/enct/textures/gui/ets_gauge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 221 B |
Loading…
Add table
Add a link
Reference in a new issue