feat: working custom arch. cutter machine
This commit is contained in:
parent
4c3f441f41
commit
69b8c79e57
32 changed files with 1334 additions and 93 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -20,3 +20,4 @@ hs_err_pid*
|
|||
# Common working directory
|
||||
run
|
||||
/repo/
|
||||
/.kotlin/
|
||||
|
|
|
|||
56
build.gradle
56
build.gradle
|
|
@ -42,7 +42,6 @@ java.toolchain.languageVersion = JavaLanguageVersion.of(21)
|
|||
kotlin.jvmToolchain(21)
|
||||
|
||||
neoForge {
|
||||
// Specify the version of NeoForge to use.
|
||||
version = project.neo_version
|
||||
|
||||
parchment {
|
||||
|
|
@ -50,16 +49,10 @@ neoForge {
|
|||
minecraftVersion = project.parchment_minecraft_version
|
||||
}
|
||||
|
||||
// This line is optional. Access Transformers are automatically detected
|
||||
// accessTransformers.add('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
|
||||
// Default run configurations.
|
||||
// These can be tweaked, removed, or duplicated as needed.
|
||||
runs {
|
||||
client {
|
||||
client()
|
||||
|
||||
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
|
||||
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
|
||||
}
|
||||
|
||||
|
|
@ -69,9 +62,6 @@ neoForge {
|
|||
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
|
||||
}
|
||||
|
||||
// This run config launches GameTestServer and runs all registered gametests, then exits.
|
||||
// By default, the server will crash when no gametests are provided.
|
||||
// The gametest system is also enabled by default for other run configs under the /test command.
|
||||
gameTestServer {
|
||||
type = "gameTestServer"
|
||||
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
|
||||
|
|
@ -80,41 +70,23 @@ neoForge {
|
|||
data {
|
||||
data()
|
||||
|
||||
// example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
|
||||
// gameDirectory = project.file('run-data')
|
||||
|
||||
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
|
||||
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
|
||||
}
|
||||
|
||||
// applies to all the run configs above
|
||||
configureEach {
|
||||
// Recommended logging data for a userdev environment
|
||||
// The markers can be added/remove as needed separated by commas.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
systemProperty 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
logLevel = org.slf4j.event.Level.DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
mods {
|
||||
// define mod <-> source bindings
|
||||
// these are used to tell the game which sources are for which mod
|
||||
// mostly optional in a single mod project
|
||||
// but multi mod projects should define one per mod
|
||||
"${mod_id}" {
|
||||
sourceSet(sourceSets.main)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Include resources generated by data generators.
|
||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||
|
||||
|
||||
|
|
@ -135,31 +107,8 @@ dependencies {
|
|||
runtimeOnly "curse.maven:sophisticated-core-618298:8046952"
|
||||
runtimeOnly "curse.maven:sophisticated-storage-619320:8034906"
|
||||
runtimeOnly "curse.maven:pocket-storage-367734:6834323"
|
||||
|
||||
// Example mod dependency with JEI
|
||||
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
|
||||
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
|
||||
// compileOnly "mezz.jei:jei-${mc_version}-forge-api:${jei_version}"
|
||||
// runtimeOnly "mezz.jei:jei-${mc_version}-forge:${jei_version}"
|
||||
|
||||
// Example mod dependency using a mod jar from ./libs with a flat dir repository
|
||||
// This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar
|
||||
// The group id is ignored when searching -- in this case, it is "blank"
|
||||
// implementation "blank:coolmod-${mc_version}:${coolmod_version}"
|
||||
|
||||
// Example mod dependency using a file as dependency
|
||||
// implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar")
|
||||
|
||||
// Example project dependency using a sister or child project:
|
||||
// implementation project(":myproject")
|
||||
|
||||
// For more info:
|
||||
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
||||
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||
}
|
||||
|
||||
// This block of code expands all declared replace properties in the specified resource targets.
|
||||
// A missing property will result in an error. Properties are expanded using ${} Groovy notation.
|
||||
var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) {
|
||||
var replaceProperties = [minecraft_version : minecraft_version,
|
||||
minecraft_version_range: minecraft_version_range,
|
||||
|
|
@ -178,13 +127,9 @@ var generateModMetadata = tasks.register("generateModMetadata", ProcessResources
|
|||
into "build/generated/sources/modMetadata"
|
||||
}
|
||||
|
||||
// Include the output of "generateModMetadata" as an input directory for the build
|
||||
// this works with both building through Gradle and the IDE.
|
||||
sourceSets.main.resources.srcDir generateModMetadata
|
||||
// To avoid having to run "generateModMetadata" manually, make it run on every project reload
|
||||
neoForge.ideSyncTask generateModMetadata
|
||||
|
||||
// Example configuration to allow publishing using the maven-publish plugin
|
||||
publishing {
|
||||
publications {
|
||||
register('mavenJava', MavenPublication) {
|
||||
|
|
@ -198,7 +143,6 @@ publishing {
|
|||
}
|
||||
}
|
||||
|
||||
// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.
|
||||
idea {
|
||||
module {
|
||||
downloadSources = true
|
||||
|
|
|
|||
104
mclschcannoncompat.ipr
Normal file
104
mclschcannoncompat.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$/mclschcannoncompat.iml" filepath="$PROJECT_DIR$/mclschcannoncompat.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
mclschcannoncompat.iws
Normal file
207
mclschcannoncompat.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>
|
||||
|
|
@ -7,5 +7,5 @@ pluginManagement {
|
|||
}
|
||||
|
||||
plugins {
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// 1.21.1 2026-05-05T23:41:11.6384884 Item Models: mclschcannoncompat
|
||||
// 1.21.1 2026-05-07T18:31:21.2712371 Item Models: mclschcannoncompat
|
||||
52b70fbe9824ebbf99b2c3464e62faeb93a3ce63 assets/mclschcannoncompat/models/item/builder_assistant_staff.json
|
||||
acd5e3967cb0dcf277da711c0b8f0efbc6271d6c assets/mclschcannoncompat/models/item/builder_assistant_staff_t2.json
|
||||
d996164a02ec5598f0d421cc1ad0755b29621414 assets/mclschcannoncompat/models/item/builder_assistant_staff_t3.json
|
||||
a395cfa9425fbce9e6dad13f0044deceb4df8dcc assets/mclschcannoncompat/models/item/ornament_fabricator.json
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
// 1.21.1 2026-05-07T13:46:09.9996673 Languages: ru_ru for mod: mclschcannoncompat
|
||||
3deacd406d126128077ef1e97aa26c68ef1759e7 assets/mclschcannoncompat/lang/ru_ru.json
|
||||
// 1.21.1 2026-05-09T02:10:42.4551668 Languages: ru_ru for mod: mclschcannoncompat
|
||||
a1fbe8c5922e6b9c566a16b14d42d6c67cc7e9d2 assets/mclschcannoncompat/lang/ru_ru.json
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
// 1.21.1 2026-05-07T13:46:10.0056649 Languages: en_us for mod: mclschcannoncompat
|
||||
a01abd18da057bba316103cb554505de33093034 assets/mclschcannoncompat/lang/en_us.json
|
||||
// 1.21.1 2026-05-09T02:10:42.4571469 Languages: en_us for mod: mclschcannoncompat
|
||||
f808ba452243bef6c6dc1efa6ce3a9d2ae74cb9e assets/mclschcannoncompat/lang/en_us.json
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
// 1.21.1 2026-05-05T23:41:11.6364906 Recipes
|
||||
// 1.21.1 2026-05-07T18:31:21.2702367 Recipes
|
||||
895b7a18109dacaaa77bafba58a50c941a9c2f56 data/mclschcannoncompat/advancement/recipes/decorations/ornament_fabricator.json
|
||||
a4d166c9c7d5b081e15495f87588fa70f62bee84 data/mclschcannoncompat/advancement/recipes/tools/rec_fct1.json
|
||||
c1b2ebefe2e42c4a01db164c8fbf90dd0aadea78 data/mclschcannoncompat/advancement/recipes/tools/rec_fct2.json
|
||||
909da6934e35b03c890689105c7f29bae51ef330 data/mclschcannoncompat/advancement/recipes/tools/rec_fct3.json
|
||||
f42203a3bee2a747b9a5e1637a27fb043b1b97bd data/mclschcannoncompat/recipe/ornament_fabricator.json
|
||||
594aec36a3be123023816c430342c9f081fd5bd4 data/mclschcannoncompat/recipe/rec_fct1.json
|
||||
4d05680c3a8c9923bf0610a8429a821cf57bbfff data/mclschcannoncompat/recipe/rec_fct2.json
|
||||
e4bfc8d84f08ce1637c0d24090653218ba04f5be data/mclschcannoncompat/recipe/rec_fct3.json
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
{
|
||||
"item.asdf.assistantstaff.maxdepth": "Maximum depth: %s",
|
||||
"block.mclschcannoncompat.ornament_fabricator": "Ornament Fabricator",
|
||||
"item.assistantstaff.hover.maxdepth": "Maximum depth: %s",
|
||||
"item.mclschcannoncompat.builder_assistant_staff": "Builder staff T1",
|
||||
"item.mclschcannoncompat.builder_assistant_staff_t2": "Builder staff T2",
|
||||
"item.mclschcannoncompat.builder_assistant_staff_t3": "Builder staff T3"
|
||||
"item.mclschcannoncompat.builder_assistant_staff_t3": "Builder staff T3",
|
||||
"tooltip.btn.cyclestyle.down": "Cycle style backward",
|
||||
"tooltip.btn.cyclestyle.up": "Cycle style forward",
|
||||
"tooltip.btn.cyclevariant.down": "Cycle variant backward",
|
||||
"tooltip.btn.cyclevariant.up": "Cycle variant forward",
|
||||
"tooltip.btn.startcrafting": "Start crafting",
|
||||
"tooltip.ornament_fabricator.no_preview": "Recipe is not supported for provided ingredients"
|
||||
}
|
||||
|
|
@ -1,6 +1,13 @@
|
|||
{
|
||||
"item.asdf.assistantstaff.maxdepth": "Максимальная блоков: %s",
|
||||
"block.mclschcannoncompat.ornament_fabricator": "Орнаментный фабрикатор",
|
||||
"item.assistantstaff.hover.maxdepth": "Максимальная глубина: %s",
|
||||
"item.mclschcannoncompat.builder_assistant_staff": "Посох строителя T1",
|
||||
"item.mclschcannoncompat.builder_assistant_staff_t2": "Посох строителя T2",
|
||||
"item.mclschcannoncompat.builder_assistant_staff_t3": "Посох строителя T3"
|
||||
"item.mclschcannoncompat.builder_assistant_staff_t3": "Посох строителя T3",
|
||||
"tooltip.btn.cyclestyle.down": "Переключить стиль назад",
|
||||
"tooltip.btn.cyclestyle.up": "Переключить стиль вперёд",
|
||||
"tooltip.btn.cyclevariant.down": "Переключить вариант назад",
|
||||
"tooltip.btn.cyclevariant.up": "Переключить вариант вперёд",
|
||||
"tooltip.btn.startcrafting": "Начать крафт",
|
||||
"tooltip.ornament_fabricator.no_preview": "Рецепт не подходит этим ингредиентам"
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"parent": "mclschcannoncompat:block/ornament_fabricator"
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"criteria": {
|
||||
"has_amethyst": {
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": "minecraft:amethyst_shard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"trigger": "minecraft:inventory_changed"
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"conditions": {
|
||||
"recipe": "mclschcannoncompat:ornament_fabricator"
|
||||
},
|
||||
"trigger": "minecraft:recipe_unlocked"
|
||||
}
|
||||
},
|
||||
"requirements": [
|
||||
[
|
||||
"has_the_recipe",
|
||||
"has_amethyst"
|
||||
]
|
||||
],
|
||||
"rewards": {
|
||||
"recipes": [
|
||||
"mclschcannoncompat:ornament_fabricator"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "misc",
|
||||
"key": {
|
||||
"A": {
|
||||
"item": "minecraft:amethyst_shard"
|
||||
},
|
||||
"C": {
|
||||
"item": "minecraft:crafting_table"
|
||||
},
|
||||
"I": {
|
||||
"item": "minecraft:iron_ingot"
|
||||
}
|
||||
},
|
||||
"pattern": [
|
||||
"III",
|
||||
"ACA",
|
||||
"III"
|
||||
],
|
||||
"result": {
|
||||
"count": 1,
|
||||
"id": "mclschcannoncompat:ornament_fabricator"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat.utils;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.Mclschcannoncompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class ODBlockRecipiesCache {
|
||||
private static final Logger LOGGER = LogManager.getLogger(Mclschcannoncompat.ID);
|
||||
|
||||
private static final List<ResourceLocation> blockTypesCache = new ArrayList<>();
|
||||
private static final TreeMap<Integer, List<ItemStack>> blockVariantsCache = new TreeMap<>();
|
||||
private static final TreeMap<ResourceLocation, List<ItemStack>> recipesCache = new TreeMap<>();
|
||||
|
||||
public static List<ResourceLocation> getBlockTypesCache() {
|
||||
return blockTypesCache;
|
||||
}
|
||||
public static Map<Integer, List<ItemStack>> getBlockVariantsCache() {
|
||||
return blockVariantsCache;
|
||||
}
|
||||
public static Map<ResourceLocation, List<ItemStack>> getRecipesCache() {
|
||||
return recipesCache;
|
||||
}
|
||||
|
||||
public static void initRecipesCache() {
|
||||
if (!recipesCache.isEmpty()) return;
|
||||
|
||||
LOGGER.info("Started caching DO recipes...");
|
||||
var startTime = System.currentTimeMillis();
|
||||
var compIG = com.ldtteam.domumornamentum.block.ModBlocks.getInstance().getOrComputeItemGroups();
|
||||
for (var ig : compIG.entrySet()) {
|
||||
var loc = ig.getKey();
|
||||
|
||||
var variantsList = new ArrayList<ItemStack>();
|
||||
for (var variant : ig.getValue()) {
|
||||
variantsList.add(variant.copy());
|
||||
}
|
||||
|
||||
if (variantsList.isEmpty()) continue;
|
||||
|
||||
blockTypesCache.add(loc);
|
||||
blockVariantsCache.put(blockTypesCache.size() - 1, variantsList);
|
||||
recipesCache.put(loc, variantsList);
|
||||
}
|
||||
var elapsedTime = System.currentTimeMillis() - startTime;
|
||||
LOGGER.info("Done caching DO recipes in $elapsedTime millis");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat
|
||||
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.CreativeModeTabs
|
||||
import net.neoforged.bus.api.SubscribeEvent
|
||||
|
|
@ -10,6 +9,7 @@ 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.client.event.RegisterMenuScreensEvent
|
||||
import net.neoforged.neoforge.data.event.GatherDataEvent
|
||||
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent
|
||||
import net.neoforged.neoforge.event.RegisterCommandsEvent
|
||||
|
|
@ -19,12 +19,16 @@ 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.mclschcannoncompat.block.ModBlockEntityTypes
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.block.ModBlocks
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.comands.ModCommands
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.datagen.ModItemModelProvider
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.datagen.ModLanguageProviders
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.datagen.ModRecipeProvider
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.item.ModItems
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.menu.ModMenuTypes
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.menu.OrnamentFabricatorMenu
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.screen.OrnamentFabricatorScreen
|
||||
|
||||
@Mod(Mclschcannoncompat.ID)
|
||||
@EventBusSubscriber
|
||||
|
|
@ -37,23 +41,28 @@ object Mclschcannoncompat {
|
|||
LOGGER.log(Level.INFO, "Hello world!")
|
||||
|
||||
ModBlocks.REGISTRY.register(MOD_BUS)
|
||||
|
||||
val obj = runForDist(clientTarget = {
|
||||
MOD_BUS.addListener(::onClientSetup)
|
||||
Minecraft.getInstance()
|
||||
}, serverTarget = {
|
||||
MOD_BUS.addListener(::onServerSetup)
|
||||
"test"
|
||||
})
|
||||
|
||||
ModBlockEntityTypes.REGISTRY.register(MOD_BUS)
|
||||
ModMenuTypes.REGISTRY.register(MOD_BUS)
|
||||
ModItems.REGISTRY.register(MOD_BUS)
|
||||
|
||||
println(obj)
|
||||
runForDist(
|
||||
clientTarget = {
|
||||
MOD_BUS.addListener(::onClientSetup)
|
||||
MOD_BUS.addListener(::onRegisterMenuScreens)
|
||||
},
|
||||
serverTarget = {
|
||||
MOD_BUS.addListener(::onServerSetup)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun onClientSetup(@Suppress("unused") event: FMLClientSetupEvent) {
|
||||
}
|
||||
|
||||
private fun onRegisterMenuScreens(event: RegisterMenuScreensEvent) {
|
||||
event.register(ModMenuTypes.ORNAMENT_FABRICATOR.get(), ::OrnamentFabricatorScreen)
|
||||
}
|
||||
|
||||
private fun onServerSetup(@Suppress("unused") event: FMLDedicatedServerSetupEvent) {
|
||||
}
|
||||
|
||||
|
|
@ -68,6 +77,9 @@ object Mclschcannoncompat {
|
|||
event.accept(ModItems.BUILDER_ASSISTANT_STAFF_T2.get())
|
||||
event.accept(ModItems.BUILDER_ASSISTANT_STAFF_T3.get())
|
||||
}
|
||||
if (event.tabKey === CreativeModeTabs.FUNCTIONAL_BLOCKS) {
|
||||
event.accept(ModItems.ORNAMENT_FABRICATOR_ITEM.get())
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
@ -76,10 +88,9 @@ object Mclschcannoncompat {
|
|||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onNetworkRegistry(event: RegisterPayloadHandlersEvent)
|
||||
{
|
||||
val modVersion = ModList.get().getModContainerById(ID).get().getModInfo().getVersion().toString()
|
||||
@Suppress("unused") val registry = event.registrar(ID).versioned(modVersion)
|
||||
fun onNetworkRegistry(event: RegisterPayloadHandlersEvent) {
|
||||
val modVersion = ModList.get().getModContainerById(ID).get().modInfo.version.toString()
|
||||
@Suppress("unused") val registrar = event.registrar(ID).versioned(modVersion)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat.block
|
||||
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.neoforged.neoforge.registries.DeferredRegister
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.Mclschcannoncompat
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.block.entity.OrnamentFabricatorBlockEntity
|
||||
import java.util.function.Supplier
|
||||
|
||||
object ModBlockEntityTypes {
|
||||
val REGISTRY = DeferredRegister.create(
|
||||
net.minecraft.core.registries.BuiltInRegistries.BLOCK_ENTITY_TYPE,
|
||||
Mclschcannoncompat.ID
|
||||
)
|
||||
|
||||
val ORNAMENT_FABRICATOR: Supplier<BlockEntityType<OrnamentFabricatorBlockEntity>> = REGISTRY.register(
|
||||
"ornament_fabricator",
|
||||
Supplier {
|
||||
BlockEntityType.Builder.of(
|
||||
::OrnamentFabricatorBlockEntity,
|
||||
ModBlocks.ORNAMENT_FABRICATOR.get()
|
||||
).build(null) as BlockEntityType<OrnamentFabricatorBlockEntity>
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -1,8 +1,19 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat.block
|
||||
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour
|
||||
import net.minecraft.world.level.material.MapColor
|
||||
import net.neoforged.neoforge.registries.DeferredRegister
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.Mclschcannoncompat
|
||||
|
||||
object ModBlocks {
|
||||
val REGISTRY = DeferredRegister.createBlocks(Mclschcannoncompat.ID)
|
||||
|
||||
val ORNAMENT_FABRICATOR = REGISTRY.registerBlock(
|
||||
"ornament_fabricator",
|
||||
::OrnamentFabricatorBlock,
|
||||
BlockBehaviour.Properties.ofFullCopy(Blocks.STONE)
|
||||
.mapColor(MapColor.STONE)
|
||||
.strength(3.0f, 6.0f)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat.block
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
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.level.storage.loot.LootParams
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.neoforged.neoforge.common.extensions.IPlayerExtension
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.block.entity.OrnamentFabricatorBlockEntity
|
||||
|
||||
class OrnamentFabricatorBlock(properties: Properties) : BaseEntityBlock(properties) {
|
||||
override fun codec(): MapCodec<out OrnamentFabricatorBlock> = simpleCodec(::OrnamentFabricatorBlock)
|
||||
|
||||
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity =
|
||||
OrnamentFabricatorBlockEntity(pos, state)
|
||||
|
||||
override fun getRenderShape(state: BlockState): RenderShape = RenderShape.MODEL
|
||||
|
||||
override fun useWithoutItem(
|
||||
state: BlockState,
|
||||
level: Level,
|
||||
pos: BlockPos,
|
||||
player: Player,
|
||||
hitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
if (level.isClientSide) return InteractionResult.SUCCESS
|
||||
|
||||
if (player is ServerPlayer) {
|
||||
player.openMenu(state.getMenuProvider(level, pos), pos)
|
||||
}
|
||||
|
||||
return InteractionResult.sidedSuccess(level.isClientSide)
|
||||
}
|
||||
|
||||
override fun <T : BlockEntity> getTicker(
|
||||
level: Level,
|
||||
state: BlockState,
|
||||
type: BlockEntityType<T>
|
||||
): BlockEntityTicker<T>? {
|
||||
if (level.isClientSide) return null
|
||||
return createTickerHelper(type, ModBlockEntityTypes.ORNAMENT_FABRICATOR.get()) { _, _, _, be ->
|
||||
be.tick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class OrnamentFabricatorEntry(
|
||||
val block: net.minecraft.world.level.block.Block,
|
||||
val components: List<com.ldtteam.domumornamentum.block.IMateriallyTexturedBlockComponent>
|
||||
)
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat.block.entity
|
||||
|
||||
import com.ldtteam.domumornamentum.block.IMateriallyTexturedBlock
|
||||
import com.ldtteam.domumornamentum.client.model.data.MaterialTextureData
|
||||
import com.ldtteam.domumornamentum.recipe.ModRecipeTypes
|
||||
import com.ldtteam.domumornamentum.recipe.architectscutter.ArchitectsCutterRecipeInput
|
||||
import com.minecolonies.api.util.ItemStackUtils
|
||||
import net.minecraft.core.BlockPos
|
||||
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.world.Containers
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.SimpleContainer
|
||||
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.BlockItem
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.component.BlockItemStateProperties
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.neoforged.neoforge.items.ItemStackHandler
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.block.ModBlockEntityTypes
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.menu.OrnamentFabricatorMenu
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.utils.ODBlockRecipiesCache
|
||||
|
||||
class OrnamentFabricatorBlockEntity(
|
||||
pos: BlockPos,
|
||||
state: BlockState
|
||||
) : BlockEntity(
|
||||
ModBlockEntityTypes.ORNAMENT_FABRICATOR.get(), pos, state
|
||||
), MenuProvider {
|
||||
init {
|
||||
ODBlockRecipiesCache.initRecipesCache()
|
||||
}
|
||||
|
||||
val itemHandler = object : ItemStackHandler(TOTAL_SLOTS) {
|
||||
override fun onContentsChanged(slot: Int) {
|
||||
if (slot != SLOT_PREVIEW) {
|
||||
updateRecipe()
|
||||
}
|
||||
setChanged()
|
||||
}
|
||||
|
||||
override fun isItemValid(slot: Int, stack: ItemStack): Boolean =
|
||||
slot != SLOT_PREVIEW
|
||||
|
||||
override fun extractItem(slot: Int, amount: Int, simulate: Boolean): ItemStack {
|
||||
if (slot == SLOT_PREVIEW) return ItemStack.EMPTY
|
||||
return super.extractItem(slot, amount, simulate)
|
||||
}
|
||||
}
|
||||
|
||||
var blockTypeIndex: Int = 0
|
||||
set(value) {
|
||||
field = value; setChanged()
|
||||
}
|
||||
|
||||
var blockSubtypeIndex: Int = 0
|
||||
set(value) {
|
||||
field = value; setChanged()
|
||||
}
|
||||
|
||||
var currentProcess: Int = 0
|
||||
set(value) {
|
||||
field = value; setChanged()
|
||||
}
|
||||
|
||||
var maxProcess: Int = DEFAULT_PROCESS_TIME
|
||||
set(value) {
|
||||
field = value; setChanged()
|
||||
}
|
||||
|
||||
var craftingEnabled: Boolean = false
|
||||
set(value) {
|
||||
field = value; setChanged()
|
||||
}
|
||||
|
||||
private var cachedRecipe: FabricatorRecipe? = null
|
||||
|
||||
val containerData = object : ContainerData {
|
||||
override fun get(index: Int): Int = when (index) {
|
||||
DATA_BLOCK_TYPE -> blockTypeIndex
|
||||
DATA_BLOCK_SUBTYPE -> blockSubtypeIndex
|
||||
DATA_CURRENT -> currentProcess
|
||||
DATA_MAX -> maxProcess
|
||||
DATA_CRAFTING_ENABLED -> if (craftingEnabled) 1 else 0
|
||||
else -> 0
|
||||
}
|
||||
|
||||
override fun set(index: Int, value: Int) {
|
||||
when (index) {
|
||||
DATA_BLOCK_TYPE -> blockTypeIndex = value
|
||||
DATA_BLOCK_SUBTYPE -> blockSubtypeIndex = value
|
||||
DATA_CURRENT -> currentProcess = value
|
||||
DATA_MAX -> maxProcess = value
|
||||
DATA_CRAFTING_ENABLED -> craftingEnabled = value == 1
|
||||
}
|
||||
|
||||
updateRecipe()
|
||||
}
|
||||
|
||||
override fun getCount(): Int = DATA_SIZE
|
||||
}
|
||||
|
||||
override fun getDisplayName(): Component =
|
||||
Component.translatable("block.mclschcannoncompat.ornament_fabricator")
|
||||
|
||||
override fun createMenu(containerId: Int, playerInventory: Inventory, player: Player): AbstractContainerMenu =
|
||||
OrnamentFabricatorMenu(containerId, playerInventory, this, containerData)
|
||||
|
||||
fun tick() {
|
||||
val level = level ?: return
|
||||
if (level.isClientSide) return
|
||||
|
||||
val inputA = itemHandler.getStackInSlot(SLOT_INPUT_A)
|
||||
val inputB = itemHandler.getStackInSlot(SLOT_INPUT_B)
|
||||
val output = itemHandler.getStackInSlot(SLOT_OUTPUT)
|
||||
|
||||
updateRecipe()
|
||||
val recipe = cachedRecipe?.takeIf { ItemStackUtils.compareItemStacksIgnoreStackSize(it.result, itemHandler.getStackInSlot(SLOT_PREVIEW)) } ?: updateRecipe()
|
||||
|
||||
if (recipe != null && craftingEnabled) {
|
||||
val canOutput = output.isEmpty ||
|
||||
(ItemStack.isSameItemSameComponents(output, recipe.result) &&
|
||||
output.count + recipe.result.count <= output.maxStackSize)
|
||||
|
||||
if (canOutput) {
|
||||
currentProcess++
|
||||
if (currentProcess >= maxProcess) {
|
||||
currentProcess = 0
|
||||
craftingEnabled = false
|
||||
|
||||
itemHandler.extractItem(SLOT_INPUT_A, 1, false)
|
||||
itemHandler.extractItem(SLOT_INPUT_B, 1, false)
|
||||
|
||||
if (output.isEmpty) {
|
||||
itemHandler.setStackInSlot(SLOT_OUTPUT, recipe.result.copy())
|
||||
} else {
|
||||
output.grow(recipe.result.count)
|
||||
}
|
||||
setChanged()
|
||||
}
|
||||
} else {
|
||||
currentProcess = 0
|
||||
}
|
||||
} else if (recipe == null) {
|
||||
currentProcess = 0
|
||||
maxProcess = DEFAULT_PROCESS_TIME
|
||||
}
|
||||
}
|
||||
|
||||
private data class FabricatorRecipe(
|
||||
val result: ItemStack,
|
||||
val resultPreview: ItemStack,
|
||||
val processTicks: Int
|
||||
)
|
||||
|
||||
private fun findRecipe(inputA: ItemStack, inputB: ItemStack): FabricatorRecipe? {
|
||||
if (inputA.isEmpty) return null
|
||||
val level = level ?: return null
|
||||
|
||||
val input = ArchitectsCutterRecipeInput(SimpleContainer(inputA, inputB))
|
||||
|
||||
val type = ODBlockRecipiesCache.getBlockTypesCache().getOrNull(blockTypeIndex) ?: return null
|
||||
val variant = ODBlockRecipiesCache.getBlockVariantsCache().getOrDefault(blockTypeIndex, emptyList())
|
||||
.getOrNull(blockSubtypeIndex) ?: return null
|
||||
|
||||
val matchedRecipe = level.recipeManager.getAllRecipesFor(ModRecipeTypes.ARCHITECTS_CUTTER.get())
|
||||
.firstNotNullOfOrNull { recipeHolder ->
|
||||
val recipe = recipeHolder.value
|
||||
val resultItem = recipe.getResultItem(level.registryAccess())
|
||||
if (resultItem.item == variant.item) {
|
||||
val resultBlockState =
|
||||
resultItem.getOrDefault(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY)
|
||||
val currentBlockState =
|
||||
variant.getOrDefault(DataComponents.BLOCK_STATE, BlockItemStateProperties.EMPTY)
|
||||
|
||||
if (resultBlockState.isEmpty && currentBlockState.isEmpty || resultBlockState == currentBlockState) {
|
||||
val output = recipe.assemble(input, level.registryAccess())
|
||||
|
||||
val textureData = MaterialTextureData.readFromItemStack(output)?.takeIf { !it.isEmpty }
|
||||
?: return@firstNotNullOfOrNull null
|
||||
|
||||
val generatedBlock =
|
||||
recipe.block as? IMateriallyTexturedBlock ?: return@firstNotNullOfOrNull null
|
||||
val recipeComponents = generatedBlock.components.toList()
|
||||
|
||||
return@firstNotNullOfOrNull when (textureData.getTexturedComponents.size) {
|
||||
2 if (!inputA.isEmpty && !inputB.isEmpty) -> {
|
||||
val itemA = inputA.item.takeIf { it is BlockItem } as? BlockItem
|
||||
?: return@firstNotNullOfOrNull null
|
||||
val itemB = inputB.item.takeIf { it is BlockItem } as? BlockItem
|
||||
?: return@firstNotNullOfOrNull null
|
||||
|
||||
val aOk = itemA.block.defaultBlockState().`is`(recipeComponents[0].validSkins)
|
||||
val bOk = itemB.block.defaultBlockState().`is`(recipeComponents[1].validSkins)
|
||||
|
||||
aOk && bOk
|
||||
recipeHolder to output
|
||||
}
|
||||
|
||||
1 if (inputB.isEmpty) -> {
|
||||
val itemA = inputA.item.takeIf { it is BlockItem } as? BlockItem
|
||||
?: return@firstNotNullOfOrNull null
|
||||
|
||||
itemA.block.defaultBlockState().`is`(recipeComponents[0].validSkins)
|
||||
recipeHolder to output
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
null
|
||||
} ?: return null
|
||||
|
||||
val (recipeUsed, output) = matchedRecipe
|
||||
|
||||
return FabricatorRecipe(
|
||||
output,
|
||||
output,
|
||||
100
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateRecipe(): FabricatorRecipe? {
|
||||
val inputA = itemHandler.getStackInSlot(SLOT_INPUT_A)
|
||||
val inputB = itemHandler.getStackInSlot(SLOT_INPUT_B)
|
||||
|
||||
val prevRecipe = cachedRecipe
|
||||
val recipe = findRecipe(inputA, inputB)
|
||||
cachedRecipe = recipe
|
||||
|
||||
recipe?.let {
|
||||
val previewStack = recipe.resultPreview.copy().also { it.count = recipe.result.count }
|
||||
itemHandler.setStackInSlot(SLOT_PREVIEW, previewStack)
|
||||
|
||||
maxProcess = recipe.processTicks
|
||||
} ?: run {
|
||||
if (!itemHandler.getStackInSlot(SLOT_PREVIEW).isEmpty) {
|
||||
itemHandler.setStackInSlot(SLOT_PREVIEW, ItemStack.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
level.takeIf { it != null && !it.isClientSide && !ItemStackUtils.compareItemStacksIgnoreStackSize(prevRecipe?.result, cachedRecipe?.result) }?.let {
|
||||
craftingEnabled = false
|
||||
currentProcess = 0
|
||||
}
|
||||
|
||||
return recipe
|
||||
}
|
||||
|
||||
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registries)
|
||||
tag.put("Inventory", itemHandler.serializeNBT(registries))
|
||||
tag.putInt("BlockTypeIndex", blockTypeIndex)
|
||||
tag.putInt("BlockSubtypeIndex", blockSubtypeIndex)
|
||||
tag.putInt("CurrentProcess", currentProcess)
|
||||
tag.putInt("MaxProcess", maxProcess)
|
||||
tag.putBoolean("CraftingEnabled", craftingEnabled)
|
||||
}
|
||||
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
itemHandler.deserializeNBT(registries, tag.getCompound("Inventory"))
|
||||
blockTypeIndex = tag.getInt("BlockTypeIndex")
|
||||
blockSubtypeIndex = tag.getInt("BlockSubtypeIndex")
|
||||
currentProcess = tag.getInt("CurrentProcess")
|
||||
maxProcess = tag.getInt("MaxProcess")
|
||||
craftingEnabled = tag.getBoolean("CraftingEnabled")
|
||||
}
|
||||
|
||||
override fun onLoad() {
|
||||
super.onLoad()
|
||||
|
||||
updateRecipe()
|
||||
}
|
||||
|
||||
fun drops() {
|
||||
val inventory = SimpleContainer(TOTAL_SLOTS)
|
||||
for (i in 0 until TOTAL_SLOTS) {
|
||||
if (i == SLOT_PREVIEW) continue
|
||||
|
||||
inventory.setItem(i, itemHandler.getStackInSlot(i))
|
||||
}
|
||||
level?.let { Containers.dropContents(it, blockPos, inventory) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SLOT_INPUT_A = 0
|
||||
const val SLOT_INPUT_B = 1
|
||||
const val SLOT_OUTPUT = 2
|
||||
const val SLOT_PREVIEW = 3
|
||||
const val TOTAL_SLOTS = 4
|
||||
|
||||
const val DATA_BLOCK_TYPE = 0
|
||||
const val DATA_BLOCK_SUBTYPE = 1
|
||||
const val DATA_CURRENT = 2
|
||||
const val DATA_MAX = 3
|
||||
const val DATA_CRAFTING_ENABLED = 4
|
||||
const val DATA_SIZE = 5
|
||||
|
||||
const val DEFAULT_PROCESS_TIME = 200 // in ticks
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import net.minecraft.data.PackOutput
|
|||
import net.neoforged.neoforge.client.model.generators.ItemModelProvider
|
||||
import net.neoforged.neoforge.common.data.ExistingFileHelper
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.Mclschcannoncompat
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.block.ModBlocks
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.item.ModItems
|
||||
|
||||
class ModItemModelProvider(output: PackOutput, existingFileHelper: ExistingFileHelper) : ItemModelProvider(output, Mclschcannoncompat.ID, existingFileHelper) {
|
||||
|
|
@ -11,5 +12,6 @@ class ModItemModelProvider(output: PackOutput, existingFileHelper: ExistingFileH
|
|||
basicItem(ModItems.BUILDER_ASSISTANT_STAFF_T1.get())
|
||||
basicItem(ModItems.BUILDER_ASSISTANT_STAFF_T2.get())
|
||||
basicItem(ModItems.BUILDER_ASSISTANT_STAFF_T3.get())
|
||||
simpleBlockItem(ModBlocks.ORNAMENT_FABRICATOR.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,15 @@ object ModLanguageProviders {
|
|||
add(ModItems.BUILDER_ASSISTANT_STAFF_T1.get(), "Посох строителя T1")
|
||||
add(ModItems.BUILDER_ASSISTANT_STAFF_T2.get(), "Посох строителя T2")
|
||||
add(ModItems.BUILDER_ASSISTANT_STAFF_T3.get(), "Посох строителя T3")
|
||||
add("item.asdf.assistantstaff.maxdepth", "Максимальная блоков: %s")
|
||||
add(ModItems.ORNAMENT_FABRICATOR_ITEM.get(), "Орнаментный фабрикатор")
|
||||
add("item.assistantstaff.hover.maxdepth", "Максимальная глубина: %s")
|
||||
|
||||
add("tooltip.ornament_fabricator.no_preview", "Рецепт не подходит этим ингредиентам")
|
||||
add("tooltip.btn.cyclestyle.up", "Переключить стиль вперёд")
|
||||
add("tooltip.btn.cyclestyle.down", "Переключить стиль назад")
|
||||
add("tooltip.btn.cyclevariant.up", "Переключить вариант вперёд")
|
||||
add("tooltip.btn.cyclevariant.down", "Переключить вариант назад")
|
||||
add("tooltip.btn.startcrafting", "Начать крафт")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -21,7 +29,15 @@ object ModLanguageProviders {
|
|||
add(ModItems.BUILDER_ASSISTANT_STAFF_T1.get(), "Builder staff T1")
|
||||
add(ModItems.BUILDER_ASSISTANT_STAFF_T2.get(), "Builder staff T2")
|
||||
add(ModItems.BUILDER_ASSISTANT_STAFF_T3.get(), "Builder staff T3")
|
||||
add("item.asdf.assistantstaff.maxdepth", "Maximum depth: %s")
|
||||
add(ModItems.ORNAMENT_FABRICATOR_ITEM.get(), "Ornament Fabricator")
|
||||
add("item.assistantstaff.hover.maxdepth", "Maximum depth: %s")
|
||||
|
||||
add("tooltip.ornament_fabricator.no_preview", "Recipe is not supported for provided ingredients")
|
||||
add("tooltip.btn.cyclestyle.up", "Cycle style forward")
|
||||
add("tooltip.btn.cyclestyle.down", "Cycle style backward")
|
||||
add("tooltip.btn.cyclevariant.up", "Cycle variant forward")
|
||||
add("tooltip.btn.cyclevariant.down", "Cycle variant backward")
|
||||
add("tooltip.btn.startcrafting", "Start crafting")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -29,4 +45,4 @@ object ModLanguageProviders {
|
|||
generator.addProvider(shouldRun, ModRuRuLanguageProvider(generator.packOutput))
|
||||
generator.addProvider(shouldRun, ModEnUsLanguageProvider(generator.packOutput))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import xyz.nuark.mcmod.mclschcannoncompat.Mclschcannoncompat
|
|||
import xyz.nuark.mcmod.mclschcannoncompat.item.ModItems
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
|
||||
class ModRecipeProvider(output: PackOutput, registries: CompletableFuture<HolderLookup.Provider>) : RecipeProvider(output, registries) {
|
||||
override fun buildRecipes(recipeOutput: RecipeOutput) {
|
||||
ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, ModItems.BUILDER_ASSISTANT_STAFF_T1.get())
|
||||
|
|
@ -43,5 +42,15 @@ class ModRecipeProvider(output: PackOutput, registries: CompletableFuture<Holder
|
|||
.define('S', ModItems.BUILDER_ASSISTANT_STAFF_T2.get())
|
||||
.unlockedBy("has_netherite_block", has(Items.NETHERITE_BLOCK))
|
||||
.save(recipeOutput, Mclschcannoncompat.resource("rec_fct3"))
|
||||
|
||||
ShapedRecipeBuilder.shaped(RecipeCategory.DECORATIONS, ModItems.ORNAMENT_FABRICATOR_ITEM.get())
|
||||
.pattern("III")
|
||||
.pattern("ACA")
|
||||
.pattern("III")
|
||||
.define('I', Items.IRON_INGOT)
|
||||
.define('A', Items.AMETHYST_SHARD)
|
||||
.define('C', Items.CRAFTING_TABLE)
|
||||
.unlockedBy("has_amethyst", has(Items.AMETHYST_SHARD))
|
||||
.save(recipeOutput, Mclschcannoncompat.resource("ornament_fabricator"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class BuilderAssistantStaff(
|
|||
flagIn: TooltipFlag
|
||||
) {
|
||||
tooltipList.add(
|
||||
Component.translatable("item.asdf.assistantstaff.maxdepth", reach * MAX_PROPAGATION_DEPTH).withStyle(ChatFormatting.BLUE)
|
||||
Component.translatable("item.assistantstaff.hover.maxdepth", reach * MAX_PROPAGATION_DEPTH).withStyle(ChatFormatting.BLUE)
|
||||
)
|
||||
tooltipList.add(
|
||||
Component.translatable("item.minecolonies.assistanthammer.desc").withStyle(ChatFormatting.ITALIC)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,20 @@ package xyz.nuark.mcmod.mclschcannoncompat.item
|
|||
|
||||
import net.neoforged.neoforge.registries.DeferredRegister
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.Mclschcannoncompat
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.block.ModBlocks
|
||||
|
||||
object ModItems {
|
||||
val REGISTRY = DeferredRegister.createItems(Mclschcannoncompat.ID)
|
||||
|
||||
val BUILDER_ASSISTANT_STAFF_T1 = REGISTRY.registerItem("builder_assistant_staff") { props -> BuilderAssistantStaff("builder_assistant_staff", props, 1) }
|
||||
val BUILDER_ASSISTANT_STAFF_T2 = REGISTRY.registerItem("builder_assistant_staff_t2") { props -> BuilderAssistantStaff("builder_assistant_staff_t2", props, 3) }
|
||||
val BUILDER_ASSISTANT_STAFF_T3 = REGISTRY.registerItem("builder_assistant_staff_t3") { props -> BuilderAssistantStaff("builder_assistant_staff_t3", props, 5) }
|
||||
}
|
||||
val BUILDER_ASSISTANT_STAFF_T1 = REGISTRY.registerItem("builder_assistant_staff") { props ->
|
||||
BuilderAssistantStaff("builder_assistant_staff", props, 1)
|
||||
}
|
||||
val BUILDER_ASSISTANT_STAFF_T2 = REGISTRY.registerItem("builder_assistant_staff_t2") { props ->
|
||||
BuilderAssistantStaff("builder_assistant_staff_t2", props, 3)
|
||||
}
|
||||
val BUILDER_ASSISTANT_STAFF_T3 = REGISTRY.registerItem("builder_assistant_staff_t3") { props ->
|
||||
BuilderAssistantStaff("builder_assistant_staff_t3", props, 5)
|
||||
}
|
||||
|
||||
val ORNAMENT_FABRICATOR_ITEM = REGISTRY.registerSimpleBlockItem(ModBlocks.ORNAMENT_FABRICATOR)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat.menu
|
||||
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension
|
||||
import net.neoforged.neoforge.registries.DeferredRegister
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.Mclschcannoncompat
|
||||
import java.util.function.Supplier
|
||||
|
||||
object ModMenuTypes {
|
||||
val REGISTRY = DeferredRegister.create(
|
||||
net.minecraft.core.registries.BuiltInRegistries.MENU,
|
||||
Mclschcannoncompat.ID
|
||||
)
|
||||
|
||||
val ORNAMENT_FABRICATOR: Supplier<MenuType<OrnamentFabricatorMenu>> =
|
||||
REGISTRY.register("ornament_fabricator", Supplier {
|
||||
IMenuTypeExtension.create(OrnamentFabricatorMenu::fromNetwork)
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat.menu
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.protocol.game.ServerboundContainerButtonClickPacket
|
||||
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.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.neoforged.neoforge.items.SlotItemHandler
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.block.entity.OrnamentFabricatorBlockEntity
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.utils.ODBlockRecipiesCache
|
||||
|
||||
class OrnamentFabricatorMenu(
|
||||
containerId: Int,
|
||||
private val playerInventory: Inventory,
|
||||
private val blockEntity: OrnamentFabricatorBlockEntity,
|
||||
private val data: ContainerData
|
||||
) : AbstractContainerMenu(
|
||||
ModMenuTypes.ORNAMENT_FABRICATOR.get(), containerId
|
||||
) {
|
||||
init {
|
||||
require(blockEntity.itemHandler.slots >= OrnamentFabricatorBlockEntity.TOTAL_SLOTS) { "Container size ${blockEntity.itemHandler.slots} is smaller than expected ${OrnamentFabricatorBlockEntity.TOTAL_SLOTS}" }
|
||||
checkContainerDataCount(data, OrnamentFabricatorBlockEntity.DATA_SIZE)
|
||||
|
||||
addSlot(SlotItemHandler(blockEntity.itemHandler, OrnamentFabricatorBlockEntity.SLOT_INPUT_A, 12, 50))
|
||||
addSlot(SlotItemHandler(blockEntity.itemHandler, OrnamentFabricatorBlockEntity.SLOT_INPUT_B, 30, 50))
|
||||
addSlot(SlotItemHandler(blockEntity.itemHandler, OrnamentFabricatorBlockEntity.SLOT_OUTPUT, 84, 50))
|
||||
|
||||
addSlot(object : SlotItemHandler(
|
||||
blockEntity.itemHandler, OrnamentFabricatorBlockEntity.SLOT_PREVIEW, 156, 50
|
||||
) {
|
||||
override fun mayPlace(stack: ItemStack) = false
|
||||
override fun mayPickup(player: Player) = false
|
||||
override fun isActive() = true
|
||||
})
|
||||
|
||||
for (row in 0..2) {
|
||||
for (col in 0..8) {
|
||||
addSlot(Slot(playerInventory, col + row * 9 + 9, INV_X + col * 18, INV_Y + row * 18))
|
||||
}
|
||||
}
|
||||
|
||||
for (col in 0..8) {
|
||||
addSlot(Slot(playerInventory, col, INV_X + col * 18, HOTBAR_Y))
|
||||
}
|
||||
|
||||
addDataSlots(data)
|
||||
}
|
||||
|
||||
val blockTypeIndex: Int get() = data.get(OrnamentFabricatorBlockEntity.DATA_BLOCK_TYPE)
|
||||
val blockSubtypeIndex: Int get() = data.get(OrnamentFabricatorBlockEntity.DATA_BLOCK_SUBTYPE)
|
||||
val currentProcess: Int get() = data.get(OrnamentFabricatorBlockEntity.DATA_CURRENT)
|
||||
val maxProcess: Int get() = data.get(OrnamentFabricatorBlockEntity.DATA_MAX)
|
||||
val craftingEnabled: Boolean get() = data.get(OrnamentFabricatorBlockEntity.DATA_CRAFTING_ENABLED) == 1
|
||||
|
||||
val progressFraction: Float
|
||||
get() = if (maxProcess > 0) currentProcess.toFloat() / maxProcess.toFloat() else 0f
|
||||
|
||||
override fun quickMoveStack(player: Player, slotIndex: Int): ItemStack {
|
||||
var remainder = ItemStack.EMPTY
|
||||
val slot = slots.getOrNull(slotIndex) ?: return remainder
|
||||
if (!slot.hasItem()) return remainder
|
||||
|
||||
val stack = slot.item
|
||||
remainder = stack.copy()
|
||||
|
||||
val beSlots = 0 until OrnamentFabricatorBlockEntity.TOTAL_SLOTS
|
||||
val invSlots = OrnamentFabricatorBlockEntity.TOTAL_SLOTS until
|
||||
OrnamentFabricatorBlockEntity.TOTAL_SLOTS + 27
|
||||
val barSlots = OrnamentFabricatorBlockEntity.TOTAL_SLOTS + 27 until
|
||||
OrnamentFabricatorBlockEntity.TOTAL_SLOTS + 36
|
||||
|
||||
if (slotIndex in beSlots) {
|
||||
if (!moveItemStackTo(stack, invSlots.first, barSlots.last + 1, true))
|
||||
return ItemStack.EMPTY
|
||||
} else {
|
||||
if (!moveItemStackTo(
|
||||
stack, OrnamentFabricatorBlockEntity.SLOT_INPUT_A,
|
||||
OrnamentFabricatorBlockEntity.SLOT_INPUT_B + 1, false
|
||||
)
|
||||
) {
|
||||
if (slotIndex in invSlots) {
|
||||
if (!moveItemStackTo(stack, barSlots.first, barSlots.last + 1, false))
|
||||
return ItemStack.EMPTY
|
||||
} else {
|
||||
if (!moveItemStackTo(stack, invSlots.first, invSlots.last + 1, false))
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stack.isEmpty) slot.set(ItemStack.EMPTY) else slot.setChanged()
|
||||
if (stack.count == remainder.count) return ItemStack.EMPTY
|
||||
slot.onTake(player, stack)
|
||||
return remainder
|
||||
}
|
||||
|
||||
override fun stillValid(player: Player): Boolean =
|
||||
!blockEntity.isRemoved && player.canInteractWithBlock(blockEntity.blockPos, 8.0)
|
||||
|
||||
fun cycleBlockTypeUp() = sendTypeChangePacket(ButtonIds.BUTTON_TYPE_UP)
|
||||
fun cycleBlockTypeDown() = sendTypeChangePacket(ButtonIds.BUTTON_TYPE_DOWN)
|
||||
fun cycleSubtypeUp() = sendTypeChangePacket(ButtonIds.BUTTON_SUBTYPE_UP)
|
||||
fun cycleSubtypeDown() = sendTypeChangePacket(ButtonIds.BUTTON_SUBTYPE_DOWN)
|
||||
fun startCrafting() = sendTypeChangePacket(ButtonIds.BUTTON_BUTTON_START_CRAFTING)
|
||||
|
||||
/**
|
||||
* Client-side handler for button clicks made by the user.
|
||||
*/
|
||||
private fun sendTypeChangePacket(buttonId: Int) {
|
||||
(playerInventory.player as? LocalPlayer)?.connection?.send(
|
||||
ServerboundContainerButtonClickPacket(containerId, buttonId)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side handler for button clicks sent by the client.
|
||||
*/
|
||||
override fun clickMenuButton(player: Player, id: Int): Boolean {
|
||||
when (id) {
|
||||
ButtonIds.BUTTON_TYPE_UP -> {
|
||||
blockEntity.blockTypeIndex = (blockEntity.blockTypeIndex + 1).coerceIn(
|
||||
ODBlockRecipiesCache.getBlockTypesCache().indices
|
||||
)
|
||||
blockEntity.blockSubtypeIndex = 0
|
||||
|
||||
blockEntity.craftingEnabled = false
|
||||
blockEntity.currentProcess = 0
|
||||
}
|
||||
|
||||
ButtonIds.BUTTON_TYPE_DOWN -> {
|
||||
blockEntity.blockTypeIndex = (blockEntity.blockTypeIndex - 1).coerceIn(
|
||||
ODBlockRecipiesCache.getBlockTypesCache().indices
|
||||
)
|
||||
blockEntity.blockSubtypeIndex = 0
|
||||
|
||||
blockEntity.craftingEnabled = false
|
||||
blockEntity.currentProcess = 0
|
||||
}
|
||||
|
||||
ButtonIds.BUTTON_SUBTYPE_UP -> {
|
||||
val range = ODBlockRecipiesCache.getBlockVariantsCache()[blockEntity.blockTypeIndex]?.indices ?: 0..0
|
||||
blockEntity.blockSubtypeIndex = (blockEntity.blockSubtypeIndex + 1).coerceIn(range)
|
||||
|
||||
blockEntity.craftingEnabled = false
|
||||
blockEntity.currentProcess = 0
|
||||
}
|
||||
|
||||
ButtonIds.BUTTON_SUBTYPE_DOWN -> {
|
||||
val range = ODBlockRecipiesCache.getBlockVariantsCache()[blockEntity.blockTypeIndex]?.indices ?: 0..0
|
||||
blockEntity.blockSubtypeIndex = (blockEntity.blockSubtypeIndex - 1).coerceIn(range)
|
||||
|
||||
blockEntity.craftingEnabled = false
|
||||
blockEntity.currentProcess = 0
|
||||
}
|
||||
|
||||
ButtonIds.BUTTON_BUTTON_START_CRAFTING -> {
|
||||
blockEntity.craftingEnabled = true
|
||||
}
|
||||
|
||||
else -> {
|
||||
return false
|
||||
}
|
||||
}
|
||||
blockEntity.setChanged()
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromNetwork(containerId: Int, playerInventory: Inventory, buf: FriendlyByteBuf): OrnamentFabricatorMenu {
|
||||
val pos = buf.readBlockPos()
|
||||
val be = playerInventory.player.level().getBlockEntity(pos) as OrnamentFabricatorBlockEntity
|
||||
return OrnamentFabricatorMenu(containerId, playerInventory, be, be.containerData)
|
||||
}
|
||||
|
||||
const val INV_X = 12
|
||||
const val INV_Y = 81
|
||||
const val HOTBAR_Y = 139
|
||||
|
||||
object ButtonIds {
|
||||
const val BUTTON_TYPE_UP = 0
|
||||
const val BUTTON_TYPE_DOWN = 1
|
||||
const val BUTTON_SUBTYPE_UP = 2
|
||||
const val BUTTON_SUBTYPE_DOWN = 3
|
||||
const val BUTTON_BUTTON_START_CRAFTING = 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
package xyz.nuark.mcmod.mclschcannoncompat.screen
|
||||
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
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.mclschcannoncompat.Mclschcannoncompat
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.block.entity.OrnamentFabricatorBlockEntity
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.menu.OrnamentFabricatorMenu
|
||||
import xyz.nuark.mcmod.mclschcannoncompat.utils.ODBlockRecipiesCache
|
||||
|
||||
class OrnamentFabricatorScreen(
|
||||
menu: OrnamentFabricatorMenu,
|
||||
playerInventory: Inventory,
|
||||
title: Component
|
||||
) : AbstractContainerScreen<OrnamentFabricatorMenu>(menu, playerInventory, title) {
|
||||
private lateinit var btnTypeUp: Button
|
||||
private lateinit var btnTypeDown: Button
|
||||
private lateinit var btnSubtypeUp: Button
|
||||
private lateinit var btnSubtypeDown: Button
|
||||
private lateinit var btnStartCrafting: Button
|
||||
|
||||
init {
|
||||
imageWidth = BG_WIDTH
|
||||
imageHeight = BG_HEIGHT
|
||||
|
||||
titleLabelX = 11
|
||||
inventoryLabelY = 6
|
||||
|
||||
inventoryLabelX = 11
|
||||
inventoryLabelY = 70
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
|
||||
val bx = leftPos
|
||||
val by = topPos
|
||||
|
||||
btnTypeUp = Button.builder(Component.literal(">")) { menu.cycleBlockTypeUp() }
|
||||
.pos(bx + 161, by + 17)
|
||||
.size(BTN_W, BTN_H)
|
||||
.tooltip(Tooltip.create(Component.translatable("tooltip.btn.cyclestyle.up")))
|
||||
.build()
|
||||
.also { addRenderableWidget(it) }
|
||||
|
||||
btnTypeDown = Button.builder(Component.literal("<")) { menu.cycleBlockTypeDown() }
|
||||
.pos(bx + 11, by + 17)
|
||||
.size(BTN_W, BTN_H)
|
||||
.tooltip(Tooltip.create(Component.translatable("tooltip.btn.cyclestyle.down")))
|
||||
.build()
|
||||
.also { addRenderableWidget(it) }
|
||||
|
||||
btnSubtypeUp = Button.builder(Component.literal(">")) { menu.cycleSubtypeUp() }
|
||||
.pos(bx + 161, by + 33)
|
||||
.size(BTN_W, BTN_H)
|
||||
.tooltip(Tooltip.create(Component.translatable("tooltip.btn.cyclevariant.up")))
|
||||
.build()
|
||||
.also { addRenderableWidget(it) }
|
||||
|
||||
btnSubtypeDown = Button.builder(Component.literal("<")) { menu.cycleSubtypeDown() }
|
||||
.pos(bx + 11, by + 33)
|
||||
.size(BTN_W, BTN_H)
|
||||
.tooltip(Tooltip.create(Component.translatable("tooltip.btn.cyclevariant.down")))
|
||||
.build()
|
||||
.also { addRenderableWidget(it) }
|
||||
|
||||
btnStartCrafting = Button.builder(Component.literal("v")) { menu.startCrafting() }
|
||||
.pos(bx + 105, by + 52)
|
||||
.size(BTN_W, BTN_H)
|
||||
.tooltip(Tooltip.create(Component.translatable("tooltip.btn.startcrafting")))
|
||||
.build()
|
||||
.also { addRenderableWidget(it) }
|
||||
}
|
||||
|
||||
override fun renderBg(graphics: GuiGraphics, partialTick: Float, mouseX: Int, mouseY: Int) {
|
||||
graphics.blit(
|
||||
TEXTURE,
|
||||
leftPos, topPos, // screen position
|
||||
0f, 0f, // UV origin of background
|
||||
imageWidth, imageHeight, // size to blit
|
||||
TEX_WIDTH, TEX_HEIGHT
|
||||
)
|
||||
|
||||
val progressWidth = (PROGRESS_WIDTH * menu.progressFraction).toInt().coerceAtLeast(0)
|
||||
if (progressWidth > 0) {
|
||||
graphics.blit(
|
||||
TEXTURE,
|
||||
leftPos + PROGRESS_X,
|
||||
topPos + PROGRESS_Y,
|
||||
PROGRESS_U.toFloat(), PROGRESS_V.toFloat(),
|
||||
progressWidth, PROGRESS_HEIGHT,
|
||||
TEX_WIDTH, TEX_HEIGHT
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(graphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
super.render(graphics, mouseX, mouseY, partialTick)
|
||||
renderTooltip(graphics, mouseX, mouseY)
|
||||
|
||||
val type = ODBlockRecipiesCache.getBlockTypesCache().getOrNull(menu.blockTypeIndex)
|
||||
val variant = ODBlockRecipiesCache.getBlockVariantsCache().getOrDefault(menu.blockTypeIndex, emptyList()).getOrNull(menu.blockSubtypeIndex)
|
||||
|
||||
graphics.drawString(
|
||||
font,
|
||||
if (type != null) Component.literal("${menu.blockTypeIndex}. ").append(Component.translatable("cuttergroup.${type.namespace}.${type.path}")) else Component.translatable("tooltip.ornament_fabricator.no_preview"),
|
||||
leftPos + 29, topPos + 19,
|
||||
0xBEBEBE, false
|
||||
)
|
||||
graphics.drawString(
|
||||
font,
|
||||
if (variant != null) Component.literal("${menu.blockSubtypeIndex}. ${variant.displayName.string}") else Component.translatable("tooltip.ornament_fabricator.no_preview"),
|
||||
leftPos + 29, topPos + 35,
|
||||
0xBEBEBE, false
|
||||
)
|
||||
}
|
||||
|
||||
override fun renderTooltip(graphics: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
super.renderTooltip(graphics, mouseX, mouseY)
|
||||
|
||||
val previewAbsX = leftPos + 156
|
||||
val previewAbsY = topPos + 50
|
||||
|
||||
if (mouseX in previewAbsX..(previewAbsX + 16) &&
|
||||
mouseY in previewAbsY..(previewAbsY + 16)
|
||||
) {
|
||||
val previewStack = menu.slots[3].item
|
||||
if (!previewStack.isEmpty) {
|
||||
graphics.renderTooltip(
|
||||
this.font,
|
||||
this.getTooltipFromContainerItem(previewStack),
|
||||
previewStack.getTooltipImage(),
|
||||
previewStack,
|
||||
mouseX,
|
||||
mouseY
|
||||
)
|
||||
} else {
|
||||
graphics.renderTooltip(
|
||||
font,
|
||||
Component.translatable("tooltip.ornament_fabricator.no_preview"),
|
||||
mouseX, mouseY
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderLabels(graphics: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
graphics.drawString(font, title, titleLabelX, titleLabelY, 0xBEBEBE, false)
|
||||
graphics.drawString(font, playerInventoryTitle, inventoryLabelX, inventoryLabelY, 0xBEBEBE, false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TEXTURE = ResourceLocation.fromNamespaceAndPath(
|
||||
Mclschcannoncompat.ID, "textures/gui/ornament_fabricator.png"
|
||||
)
|
||||
|
||||
// Background size (must match your PNG atlas dimensions you blit)
|
||||
private const val BG_WIDTH = 184
|
||||
private const val BG_HEIGHT = 163
|
||||
|
||||
// Progress bar (blitted as a partial sprite)
|
||||
private const val PROGRESS_X = 51
|
||||
private const val PROGRESS_Y = 53
|
||||
private const val PROGRESS_U = 184 // UV X in texture
|
||||
private const val PROGRESS_V = 0 // UV Y in texture
|
||||
private const val PROGRESS_WIDTH = 28
|
||||
private const val PROGRESS_HEIGHT = 10
|
||||
|
||||
// Texture sheet total size (usually 256×256)
|
||||
private const val TEX_WIDTH = 256
|
||||
private const val TEX_HEIGHT = 256
|
||||
|
||||
// Button positions (relative to background top-left, i.e. imageX / imageY)
|
||||
private const val BTN_W = 12
|
||||
private const val BTN_H = 12
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"variants": {
|
||||
"": { "model": "mclschcannoncompat:block/ornament_fabricator" }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "mclschcannoncompat:block/ornament_fabricator"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Loading…
Add table
Add a link
Reference in a new issue