From 447cc19749499e3f695df43ed16706f6bbea7be3 Mon Sep 17 00:00:00 2001 From: 3944Realms Date: Mon, 22 Jun 2026 09:46:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AF=B9AE=E6=89=A9?= =?UTF-8?q?=E5=B1=95Plus=E7=9A=84=E6=9C=8D=E5=8A=A1=E5=99=A8=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=E4=BF=AE=E6=94=B9=EF=BC=8C=E6=97=A8=E5=9C=A8=E6=B6=88?= =?UTF-8?q?=E9=99=A4=E8=AF=A5=E6=A8=A1=E7=BB=84=E5=9C=A8=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E4=B8=96=E7=95=8C=E6=97=B6=E4=BF=AE=E6=94=B9=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E5=85=B3=E9=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 83 +++++++++--- gradle.properties | 20 +-- settings.gradle | 10 +- .../java/com/example/examplemod/Config.java | 63 --------- .../com/example/examplemod/ExampleMod.java | 128 ------------------ .../serverpatch/CommonHandler.java | 42 ++++++ .../leisuretimedock/serverpatch/Patch.java | 11 ++ .../serverpatch/compat/SPCompatManager.java | 12 ++ ...LabeledWirelessTransceiverBlockEntity.java | 50 +++++++ .../MixinWirelessTransceiverBlockEntity.java | 42 ++++++ .../assets/examplemod/lang/en_us.json | 5 - src/main/resources/ltdserverpatch.mixins.json | 17 +++ src/main/templates/META-INF/mods.toml | 7 + 13 files changed, 267 insertions(+), 223 deletions(-) delete mode 100644 src/main/java/com/example/examplemod/Config.java delete mode 100644 src/main/java/com/example/examplemod/ExampleMod.java create mode 100644 src/main/java/top/leisuretimedock/serverpatch/CommonHandler.java create mode 100644 src/main/java/top/leisuretimedock/serverpatch/Patch.java create mode 100644 src/main/java/top/leisuretimedock/serverpatch/compat/SPCompatManager.java create mode 100644 src/main/java/top/leisuretimedock/serverpatch/mixin/MixinLabeledWirelessTransceiverBlockEntity.java create mode 100644 src/main/java/top/leisuretimedock/serverpatch/mixin/MixinWirelessTransceiverBlockEntity.java delete mode 100644 src/main/resources/assets/examplemod/lang/en_us.json create mode 100644 src/main/resources/ltdserverpatch.mixins.json diff --git a/build.gradle b/build.gradle index 3fce4be..adc3264 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,8 @@ plugins { id 'idea' id 'java-library' id 'maven-publish' - id 'net.neoforged.moddev.legacyforge' version '2.0.91' + id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'net.neoforged.moddev.legacyforge' version '2.0.103' } tasks.named('wrapper', Wrapper).configure { @@ -14,11 +15,27 @@ tasks.named('wrapper', Wrapper).configure { distributionType = Wrapper.DistributionType.BIN } + version = mod_version -group = mod_group_id +group = "${minecraft_version}-${mod_version}" repositories { mavenLocal() + maven { url = "https://libraries.minecraft.net/" } + maven { url = "https://neoforged.forgecdn.net/releases" } + maven { url = "https://neoforged.forgecdn.net/mojang-meta" } + maven { + name = "BlameJared" + url = "https://maven.blamejared.com/" + } + maven { + url "https://cursemaven.com" + content { includeGroup "curse.maven" } + } + maven { + name = "LTD Maven" + url = "https://nexus.bot.leisuretimedock.top/repository/maven-public/" + } } base { @@ -49,10 +66,13 @@ legacyForge { // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } - + clientAuth { + devLogin = true + client() + systemProperty 'forge.enabledGameTestNamespaces', mod_id + } server { server() - programArgument '--nogui' systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } @@ -101,8 +121,15 @@ legacyForge { } } +processResources { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE +} + // Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } +sourceSets.main.resources { + srcDir 'src/generated/resources' + srcDir 'src/main/resources' +} // Sets up a dependency configuration called 'localRuntime' and a deobfuscating one called 'modLocalRuntime' // These configurations should be used instead of 'runtimeOnly' to declare @@ -111,11 +138,24 @@ sourceSets.main.resources { srcDir 'src/generated/resources' } configurations { runtimeClasspath.extendsFrom localRuntime } + obfuscation { createRemappingConfiguration(configurations.localRuntime) } dependencies { + modRuntimeOnly("curse.maven:debug-utils-forge-783008:5337491") + modCompileOnly("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}") + modCompileOnly("mezz.jei:jei-${minecraft_version}-common-api:${jei_version}") + modRuntimeOnly("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") + modImplementation("top.r3944realms.lib39:lib39-forge-1.20.1:${lib39_version}") + implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1")) + modImplementation(jarJar("io.github.llamalad7:mixinextras-forge:0.4.1")) + modImplementation("curse.maven:timeless-and-classics-zero-1028108:6654541") + modImplementation("curse.maven:camera-mod-289310:6480231") + modImplementation("curse.maven:extendedae-plus-1337639:8141730") + modImplementation("curse.maven:applied-energistics-2-223794:7148487") + modImplementation("curse.maven:ex-pattern-provider-892005:8291632") // If you wish to declare dependencies against mods, make sure to use the 'mod*' configurations so that they're remapped. // See https://github.com/neoforged/ModDevGradle/blob/main/LEGACY.md#remapping-mod-dependencies for more information. @@ -141,24 +181,15 @@ dependencies { // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html // http://www.gradle.org/docs/current/userguide/dependency_management.html } - -// Uncomment the lines below if you wish to configure mixin. The mixin file should be named modid.mixins.json. -/* mixin { add sourceSets.main, "${mod_id}.refmap.json" config "${mod_id}.mixins.json" } - dependencies { annotationProcessor 'org.spongepowered:mixin:0.8.5:processor' } -jar { - manifest.attributes([ - "MixinConfigs": "${mod_id}.mixins.json" - ]) -} -*/ + // 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. @@ -174,11 +205,15 @@ var generateModMetadata = tasks.register("generateModMetadata", ProcessResources mod_license : mod_license, mod_version : mod_version, mod_authors : mod_authors, - mod_description : mod_description + mod_description : mod_description, + lib39_version : lib39_version ] inputs.properties replaceProperties - expand replaceProperties from "src/main/templates" + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] + } + duplicatesStrategy = DuplicatesStrategy.EXCLUDE into "build/generated/sources/modMetadata" } // Include the output of "generateModMetadata" as an input directory for the build @@ -204,6 +239,20 @@ publishing { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation } +jar { + manifest { + attributes([ + 'Specification-Title' : mod_id, + 'Specification-Vendor' : mod_authors, + 'Specification-Version' : '1', + 'Implementation-Title' : project.name, + 'Implementation-Version' : archiveVersion, + 'Implementation-Vendor' : mod_authors, + 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + 'MixinConfigs' : "${mod_id}.mixins.json" + ]) + } +} // IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior. idea { diff --git a/gradle.properties b/gradle.properties index 0f61595..0380b66 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,9 @@ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. -org.gradle.jvmargs=-Xmx1G -org.gradle.daemon=true +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false org.gradle.parallel=true org.gradle.caching=true -org.gradle.configuration-cache=true +org.gradle.configuration-cache=false #read more on this at https://github.com/neoforged/ModDevGradle?tab=readme-ov-file#better-minecraft-parameter-names--javadoc-parchment # you can also find the latest versions at: https://parchmentmc.org/docs/getting-started @@ -28,18 +28,20 @@ loader_version_range=[47,) # The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} # Must match the String constant located in the main mod class annotated with @Mod. -mod_id=examplemod +mod_id=ltdserverpatch # The human-readable display name for the mod. -mod_name=Example Mod +mod_name=LTD Server Patch # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=All Rights Reserved # The mod version. See https://semver.org/ -mod_version=1.0.0 +jei_version=15.20.0.112 +lib39_version=0.5.6 +mod_version=1.0.1 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html -mod_group_id=com.example.examplemod +mod_group_id=top.leisuretimedock.serverpatch # The authors of the mod. This is a simple text string that is used for display purposes in the mod list. -mod_authors=YourNameHere, OtherNameHere +mod_authors=R3944Realms # The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. -mod_description=Example mod description.\nNewline characters can be used and will be replaced properly. +mod_description=LTD Server Patch Mod diff --git a/settings.gradle b/settings.gradle index 4ced2d9..497a012 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,11 @@ +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + maven { url = 'https://maven.neoforged.net/releases' } + maven { url = 'https://maven.parchmentmc.org' } // Add this line + } +} plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0' -} +} \ No newline at end of file diff --git a/src/main/java/com/example/examplemod/Config.java b/src/main/java/com/example/examplemod/Config.java deleted file mode 100644 index ca8e088..0000000 --- a/src/main/java/com/example/examplemod/Config.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.example.examplemod; - -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.config.ModConfigEvent; - -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -// An example config class. This is not required, but it's a good idea to have one to keep your config organized. -// Demonstrates how to use Forge's config APIs -@Mod.EventBusSubscriber(modid = ExampleMod.MODID, bus = Mod.EventBusSubscriber.Bus.MOD) -public class Config -{ - private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder(); - - private static final ForgeConfigSpec.BooleanValue LOG_DIRT_BLOCK = BUILDER - .comment("Whether to log the dirt block on common setup") - .define("logDirtBlock", true); - - private static final ForgeConfigSpec.IntValue MAGIC_NUMBER = BUILDER - .comment("A magic number") - .defineInRange("magicNumber", 42, 0, Integer.MAX_VALUE); - - public static final ForgeConfigSpec.ConfigValue MAGIC_NUMBER_INTRODUCTION = BUILDER - .comment("What you want the introduction message to be for the magic number") - .define("magicNumberIntroduction", "The magic number is... "); - - // a list of strings that are treated as resource locations for items - private static final ForgeConfigSpec.ConfigValue> ITEM_STRINGS = BUILDER - .comment("A list of items to log on common setup.") - .defineListAllowEmpty("items", List.of("minecraft:iron_ingot"), Config::validateItemName); - - static final ForgeConfigSpec SPEC = BUILDER.build(); - - public static boolean logDirtBlock; - public static int magicNumber; - public static String magicNumberIntroduction; - public static Set items; - - private static boolean validateItemName(final Object obj) - { - return obj instanceof String itemName && BuiltInRegistries.ITEM.containsKey(new ResourceLocation(itemName)); - } - - @SubscribeEvent - static void onLoad(final ModConfigEvent event) - { - logDirtBlock = LOG_DIRT_BLOCK.get(); - magicNumber = MAGIC_NUMBER.get(); - magicNumberIntroduction = MAGIC_NUMBER_INTRODUCTION.get(); - - // convert the list of strings into a set of items - items = ITEM_STRINGS.get().stream() - .map(itemName -> BuiltInRegistries.ITEM.get(new ResourceLocation(itemName))) - .collect(Collectors.toSet()); - } -} diff --git a/src/main/java/com/example/examplemod/ExampleMod.java b/src/main/java/com/example/examplemod/ExampleMod.java deleted file mode 100644 index 990fd63..0000000 --- a/src/main/java/com/example/examplemod/ExampleMod.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.example.examplemod; - -import com.mojang.logging.LogUtils; -import net.minecraft.client.Minecraft; -import net.minecraft.core.registries.Registries; -import net.minecraft.world.food.FoodProperties; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.CreativeModeTabs; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.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.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; -import net.minecraftforge.event.server.ServerStartingEvent; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.config.ModConfig; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.registries.DeferredRegister; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegistryObject; -import org.slf4j.Logger; - -// The value here should match an entry in the META-INF/mods.toml file -@Mod(ExampleMod.MODID) -public class ExampleMod -{ - // Define mod id in a common place for everything to reference - public static final String MODID = "examplemod"; - // Directly reference a slf4j logger - private static final Logger LOGGER = LogUtils.getLogger(); - // Create a Deferred Register to hold Blocks which will all be registered under the "examplemod" namespace - public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MODID); - // Create a Deferred Register to hold Items which will all be registered under the "examplemod" namespace - public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); - // Create a Deferred Register to hold CreativeModeTabs which will all be registered under the "examplemod" namespace - public static final DeferredRegister CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MODID); - - // Creates a new Block with the id "examplemod:example_block", combining the namespace and path - public static final RegistryObject EXAMPLE_BLOCK = BLOCKS.register("example_block", () -> new Block(BlockBehaviour.Properties.of().mapColor(MapColor.STONE))); - // Creates a new BlockItem with the id "examplemod:example_block", combining the namespace and path - public static final RegistryObject EXAMPLE_BLOCK_ITEM = ITEMS.register("example_block", () -> new BlockItem(EXAMPLE_BLOCK.get(), new Item.Properties())); - - // Creates a new food item with the id "examplemod:example_id", nutrition 1 and saturation 2 - public static final RegistryObject EXAMPLE_ITEM = ITEMS.register("example_item", () -> new Item(new Item.Properties().food(new FoodProperties.Builder() - .alwaysEat().nutrition(1).saturationMod(2f).build()))); - - // Creates a creative tab with the id "examplemod:example_tab" for the example item, that is placed after the combat tab - public static final RegistryObject EXAMPLE_TAB = CREATIVE_MODE_TABS.register("example_tab", () -> CreativeModeTab.builder() - .withTabsBefore(CreativeModeTabs.COMBAT) - .icon(() -> EXAMPLE_ITEM.get().getDefaultInstance()) - .displayItems((parameters, output) -> { - output.accept(EXAMPLE_ITEM.get()); // Add the example item to the tab. For your own tabs, this method is preferred over the event - }).build()); - - public ExampleMod() - { - IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); - - // Register the commonSetup method for modloading - modEventBus.addListener(this::commonSetup); - - // Register the Deferred Register to the mod event bus so blocks get registered - BLOCKS.register(modEventBus); - // Register the Deferred Register to the mod event bus so items get registered - ITEMS.register(modEventBus); - // Register the Deferred Register to the mod event bus so tabs get registered - CREATIVE_MODE_TABS.register(modEventBus); - - // Register ourselves for server and other game events we are interested in - MinecraftForge.EVENT_BUS.register(this); - - // Register the item to a creative tab - modEventBus.addListener(this::addCreative); - - // Register our mod's ForgeConfigSpec so that Forge can create and load the config file for us - ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, Config.SPEC); - } - - private void commonSetup(final FMLCommonSetupEvent event) - { - // Some common setup code - LOGGER.info("HELLO FROM COMMON SETUP"); - - if (Config.logDirtBlock) - LOGGER.info("DIRT BLOCK >> {}", ForgeRegistries.BLOCKS.getKey(Blocks.DIRT)); - - LOGGER.info(Config.magicNumberIntroduction + Config.magicNumber); - - Config.items.forEach((item) -> LOGGER.info("ITEM >> {}", item.toString())); - } - - // Add the example block item to the building blocks tab - private void addCreative(BuildCreativeModeTabContentsEvent event) - { - if (event.getTabKey() == CreativeModeTabs.BUILDING_BLOCKS) - event.accept(EXAMPLE_BLOCK_ITEM); - } - - // You can use SubscribeEvent and let the Event Bus discover methods to call - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) - { - // Do something when the server starts - LOGGER.info("HELLO from server starting"); - } - - // You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent - @Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) - public static class ClientModEvents - { - @SubscribeEvent - public static void onClientSetup(FMLClientSetupEvent event) - { - // Some client setup code - LOGGER.info("HELLO FROM CLIENT SETUP"); - LOGGER.info("MINECRAFT NAME >> {}", Minecraft.getInstance().getUser().getName()); - } - } -} diff --git a/src/main/java/top/leisuretimedock/serverpatch/CommonHandler.java b/src/main/java/top/leisuretimedock/serverpatch/CommonHandler.java new file mode 100644 index 0000000..809bf5c --- /dev/null +++ b/src/main/java/top/leisuretimedock/serverpatch/CommonHandler.java @@ -0,0 +1,42 @@ +package top.leisuretimedock.serverpatch; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.event.lifecycle.FMLConstructModEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import org.jetbrains.annotations.NotNull; +import top.leisuretimedock.serverpatch.compat.SPCompatManager; +import top.r3944realms.lib39.core.compat.ICompatManager; +import top.r3944realms.lib39.core.event.CommonEventHandler; + +public class CommonHandler { + + @net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = Patch.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.FORGE) + public static class Game extends CommonHandler { + public static final IEventBus EVENT_BUS = FMLJavaModLoadingContext.get().getModEventBus(); + static volatile ICompatManager compatManager; + public static ICompatManager getOrCreateCompatManager() { + if (compatManager == null) { + synchronized(CommonEventHandler.Mod.class) { + if (compatManager == null) { + compatManager = new SPCompatManager("compat", EVENT_BUS, MinecraftForge.EVENT_BUS); + } + } + } + + return compatManager; + } + + @SubscribeEvent + public static void init(@NotNull FMLConstructModEvent event) { + event.enqueueWork(() -> { + getOrCreateCompatManager(); + }); + } + } + //@net.minecraftforge.fml.common.Mod.EventBusSubscriber(bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD) + public static class Mod extends CommonHandler { + + } +} diff --git a/src/main/java/top/leisuretimedock/serverpatch/Patch.java b/src/main/java/top/leisuretimedock/serverpatch/Patch.java new file mode 100644 index 0000000..2413bbb --- /dev/null +++ b/src/main/java/top/leisuretimedock/serverpatch/Patch.java @@ -0,0 +1,11 @@ +package top.leisuretimedock.serverpatch; + +import net.minecraftforge.fml.common.Mod; + +@Mod(value = Patch.MOD_ID) +public class Patch { + public static final String MOD_ID = "ltdserverpatch"; + public Patch() { + + } +} diff --git a/src/main/java/top/leisuretimedock/serverpatch/compat/SPCompatManager.java b/src/main/java/top/leisuretimedock/serverpatch/compat/SPCompatManager.java new file mode 100644 index 0000000..7ece23a --- /dev/null +++ b/src/main/java/top/leisuretimedock/serverpatch/compat/SPCompatManager.java @@ -0,0 +1,12 @@ +package top.leisuretimedock.serverpatch.compat; + +import net.minecraftforge.eventbus.api.IEventBus; +import top.r3944realms.lib39.Lib39; +import top.r3944realms.lib39.core.compat.ForgeCompatManager; + +public class SPCompatManager extends ForgeCompatManager { + + public SPCompatManager(String id, IEventBus modEventBus, IEventBus gameEventBus) { + super(Lib39.rl("sp", id), modEventBus, gameEventBus); + } +} diff --git a/src/main/java/top/leisuretimedock/serverpatch/mixin/MixinLabeledWirelessTransceiverBlockEntity.java b/src/main/java/top/leisuretimedock/serverpatch/mixin/MixinLabeledWirelessTransceiverBlockEntity.java new file mode 100644 index 0000000..2279cd8 --- /dev/null +++ b/src/main/java/top/leisuretimedock/serverpatch/mixin/MixinLabeledWirelessTransceiverBlockEntity.java @@ -0,0 +1,50 @@ +package top.leisuretimedock.serverpatch.mixin; + +import com.extendedae_plus.content.wireless.LabeledWirelessTransceiverBlockEntity; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import net.minecraft.core.BlockPos; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(value = LabeledWirelessTransceiverBlockEntity.class, remap = false) +public class MixinLabeledWirelessTransceiverBlockEntity { + /** + * 拦截 updateState 方法 + * 如果服务器正在关闭,直接跳过,不执行任何操作 + * 避免在关闭过程中调用 setBlock 触发区块加载 + */ + @WrapMethod( + method = "updateState" + ) + private void SP$onUpdateState(Operation original) { + LabeledWirelessTransceiverBlockEntity self = (LabeledWirelessTransceiverBlockEntity) (Object) this; + Level level = self.getLevel(); + if (level instanceof ServerLevel serverLevel) { + MinecraftServer server = serverLevel.getServer(); + if (server != null && server.isRunning()) { + original.call(); + } + } + } + + /** + * 拦截 serverTick 静态方法 + * 如果服务器正在关闭,直接跳过 tick 逻辑 + * 避免在关闭过程中触发 updateState 和 setBlock + */ + @WrapMethod( + method = "serverTick" + ) + private static void SP$onServerTick(Level level, BlockPos pos, BlockState state, LabeledWirelessTransceiverBlockEntity be, Operation original) { + if (level instanceof ServerLevel serverLevel) { + MinecraftServer server = serverLevel.getServer(); + if (server.isRunning()) { + original.call(level, pos, state, be); + } + } + } +} diff --git a/src/main/java/top/leisuretimedock/serverpatch/mixin/MixinWirelessTransceiverBlockEntity.java b/src/main/java/top/leisuretimedock/serverpatch/mixin/MixinWirelessTransceiverBlockEntity.java new file mode 100644 index 0000000..7995a83 --- /dev/null +++ b/src/main/java/top/leisuretimedock/serverpatch/mixin/MixinWirelessTransceiverBlockEntity.java @@ -0,0 +1,42 @@ +package top.leisuretimedock.serverpatch.mixin; + +import com.extendedae_plus.content.wireless.WirelessTransceiverBlockEntity; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import net.minecraft.core.BlockPos; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(value = WirelessTransceiverBlockEntity.class ,remap = false) +public class MixinWirelessTransceiverBlockEntity { + /** + * 如果服务器正在关闭,直接跳过 updateState + */ + @WrapMethod( + method = "updateState" + ) + private void SP$onUpdateState(Operation original) { + Level level = ((WirelessTransceiverBlockEntity)(Object)this).getLevel(); + if (level instanceof ServerLevel serverLevel) { + MinecraftServer server = serverLevel.getServer(); + if (server != null && server.isRunning()) { + original.call(); + } + } + } + + @WrapMethod( + method = "serverTick" + ) + private static void SP$onServerTick(Level level, BlockPos pos, BlockState state, WirelessTransceiverBlockEntity be, Operation original) { + if (level instanceof ServerLevel serverLevel) { + MinecraftServer server = serverLevel.getServer(); + if (server.isRunning()) { + original.call(level, pos, state, be); + } + } + } +} diff --git a/src/main/resources/assets/examplemod/lang/en_us.json b/src/main/resources/assets/examplemod/lang/en_us.json deleted file mode 100644 index 3b34651..0000000 --- a/src/main/resources/assets/examplemod/lang/en_us.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "itemGroup.examplemod": "Example Mod Tab", - "block.examplemod.example_block": "Example Block", - "item.examplemod.example_item": "Example Item" -} diff --git a/src/main/resources/ltdserverpatch.mixins.json b/src/main/resources/ltdserverpatch.mixins.json new file mode 100644 index 0000000..f5c59f2 --- /dev/null +++ b/src/main/resources/ltdserverpatch.mixins.json @@ -0,0 +1,17 @@ +{ + "required": true, + "minVersion": "0.8", + "package": "top.leisuretimedock.serverpatch.mixin", + "compatibilityLevel": "JAVA_17", + "refmap": "ltdserverpatch.refmap.json", + "plugin": "top.leisuretimedock.serverpatch.mixin.SPMixinPlugin", + "mixins": [ + "MixinLabeledWirelessTransceiverBlockEntity", + "MixinWirelessTransceiverBlockEntity" + ], + "client": [ + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/templates/META-INF/mods.toml b/src/main/templates/META-INF/mods.toml index 7d3d6bc..859d364 100644 --- a/src/main/templates/META-INF/mods.toml +++ b/src/main/templates/META-INF/mods.toml @@ -81,6 +81,13 @@ description='''${mod_description}''' ordering="NONE" side="BOTH" +[[dependencies.${mod_id}]] + modId="lib39" + mandatory=true + # This version range declares a minimum of the current minecraft version up to but not including the next major version + versionRange="[${lib39_version},)" + ordering="AFTER" + side="BOTH" # Features are specific properties of the game environment, that you may want to declare you require. This example declares # that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't # stop your mod loading on the server for example.