diff --git a/gradle.properties b/gradle.properties index 3b3167c..090abf2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.14.9 # Mod Properties - mod_version = 0.1 + mod_version = 0.3 maven_group = com.github.zly2006 archives_base_name = carpet-sls-addition diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/SLSCarpetSettings.java b/src/main/java/com/github/zly2006/carpetslsaddition/SLSCarpetSettings.java index 18a5cb6..d033c67 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/SLSCarpetSettings.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/SLSCarpetSettings.java @@ -1,10 +1,19 @@ package com.github.zly2006.carpetslsaddition; +import carpet.CarpetSettings; +import carpet.api.settings.CarpetRule; import carpet.api.settings.Rule; +import carpet.api.settings.RuleCategory; import static com.github.zly2006.carpetslsaddition.ServerMain.*; public class SLSCarpetSettings { @Rule(categories = {CARPET_ID}) public static boolean obtainableReinforcedDeepSlate = false; + @Rule(categories = {CARPET_ID}) + public static int skipTicksForJoblessVillager = 0; + @Rule(categories = {CARPET_ID}, options = {"-1", "24", "50"}) + public static int maxVillagersInABlock = -1; + @Rule(categories = {CARPET_ID, RuleCategory.CREATIVE}) + public static boolean creativeNoInfinitePickup = false; } diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java index d8deebe..7f889bb 100644 --- a/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java +++ b/src/main/java/com/github/zly2006/carpetslsaddition/ServerMain.java @@ -7,11 +7,14 @@ import com.google.common.collect.MapMaker; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.JsonObject; +import com.mojang.brigadier.CommandDispatcher; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.Version; +import net.minecraft.command.CommandRegistryAccess; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.Text; import org.spongepowered.asm.mixin.injection.struct.InjectorGroupInfo; @@ -23,6 +26,8 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import static net.minecraft.server.command.CommandManager.*; + public class ServerMain implements ModInitializer, CarpetExtension { public static final String MOD_ID = "carpet-sls-addition"; public static final String MOD_NAME = "Carpet SLS Addition"; @@ -48,12 +53,18 @@ public class ServerMain implements ModInitializer, CarpetExtension { public Map canHasTranslations(String lang) { Map translation = Maps.newHashMap(); String jsonFile; - try (InputStream stream = ServerMain.class.getResourceAsStream("/assets/slsaddition/lang/%s.json".formatted(lang))) { - jsonFile = new String(stream.readAllBytes()); - } catch (IOException ignored) { - try (InputStream stream = ServerMain.class.getResourceAsStream("/assets/slsaddition/lang/%s.json".formatted("en_us"))) { + try { + try (InputStream stream = ServerMain.class.getResourceAsStream("/assets/slsaddition/lang/%s.json".formatted(lang))) { + assert stream != null; jsonFile = new String(stream.readAllBytes()); - } catch (IOException e) { + } + } catch (IOException | NullPointerException ignored) { + try { + try (InputStream stream = ServerMain.class.getResourceAsStream("/assets/slsaddition/lang/%s.json".formatted("en_us"))) { + assert stream != null; + jsonFile = new String(stream.readAllBytes()); + } + } catch (IOException | NullPointerException e) { return translation; } } @@ -64,4 +75,8 @@ public class ServerMain implements ModInitializer, CarpetExtension { .forEach(entry -> translation.put(entry.getKey(), entry.getValue())); return translation; } + + @Override + public void registerCommands(CommandDispatcher dispatcher, CommandRegistryAccess commandBuildContext) { + } } diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/AccessorPlayerAbilities.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/AccessorPlayerAbilities.java new file mode 100644 index 0000000..57f67bf --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/AccessorPlayerAbilities.java @@ -0,0 +1,38 @@ +package com.github.zly2006.carpetslsaddition.mixin; + +import net.minecraft.entity.player.PlayerAbilities; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(PlayerAbilities.class) +public interface AccessorPlayerAbilities { + @Accessor("flySpeed") + void setFlyingSpeed(float speed); + @Accessor("walkSpeed") + void setWalkingSpeed(float speed); + @Accessor("flying") + void setFlying(boolean flying); + @Accessor("invulnerable") + void setInvulnerable(boolean invulnerable); + @Accessor("allowFlying") + void setAllowFlying(boolean allowFlying); + @Accessor("creativeMode") + void setCreativeMode(boolean creativeMode); + @Accessor("allowModifyWorld") + void setAllowModifyWorld(boolean allowModifyWorld); + + @Accessor("flySpeed") + float getFlyingSpeed(); + @Accessor("walkSpeed") + float getWalkingSpeed(); + @Accessor("flying") + boolean isFlying(); + @Accessor("invulnerable") + boolean isInvulnerable(); + @Accessor("allowFlying") + boolean isAllowFlying(); + @Accessor("creativeMode") + boolean isCreativeMode(); + @Accessor("allowModifyWorld") + boolean isAllowModifyWorld(); +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinPlayerInventory.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinPlayerInventory.java new file mode 100644 index 0000000..133e049 --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinPlayerInventory.java @@ -0,0 +1,35 @@ +package com.github.zly2006.carpetslsaddition.mixin; + +import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; +import net.minecraft.entity.player.PlayerAbilities; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerInventory.class) +public class MixinPlayerInventory { + @Redirect(method = "insertStack(ILnet/minecraft/item/ItemStack;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;getAbilities()Lnet/minecraft/entity/player/PlayerAbilities;")) + private PlayerAbilities insertStack(PlayerEntity instance) { + if (SLSCarpetSettings.creativeNoInfinitePickup) { + AccessorPlayerAbilities accessor = (AccessorPlayerAbilities) instance.getAbilities(); + PlayerAbilities abilities = new PlayerAbilities(); + AccessorPlayerAbilities accessor1 = (AccessorPlayerAbilities) abilities; + accessor1.setCreativeMode(false); + accessor1.setFlying(accessor.isFlying()); + accessor1.setFlyingSpeed(accessor.getFlyingSpeed()); + accessor1.setInvulnerable(accessor.isInvulnerable()); + accessor1.setAllowFlying(accessor.isAllowFlying()); + accessor1.setAllowModifyWorld(accessor.isAllowModifyWorld()); + accessor1.setWalkingSpeed(accessor.getWalkingSpeed()); + return abilities; + } + return instance.getAbilities(); + } +} diff --git a/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinVillagerEntity.java b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinVillagerEntity.java new file mode 100644 index 0000000..24d78fe --- /dev/null +++ b/src/main/java/com/github/zly2006/carpetslsaddition/mixin/MixinVillagerEntity.java @@ -0,0 +1,50 @@ +package com.github.zly2006.carpetslsaddition.mixin; + +import com.github.zly2006.carpetslsaddition.SLSCarpetSettings; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.passive.MerchantEntity; +import net.minecraft.entity.passive.VillagerEntity; +import net.minecraft.village.VillagerData; +import net.minecraft.village.VillagerProfession; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(VillagerEntity.class) +public abstract class MixinVillagerEntity extends MerchantEntity { + @Shadow public abstract VillagerData getVillagerData(); + + @Shadow protected abstract void decayGossip(); + + int tickCount = 0; + public MixinVillagerEntity(EntityType entityType, World world) { + super(entityType, world); + } + + @Inject(at = @At("HEAD"), method = "tick", cancellable = true) + private void onTick(CallbackInfo ci) { + if (SLSCarpetSettings.skipTicksForJoblessVillager != 0) { + VillagerProfession profession = this.getVillagerData().getProfession(); + if (profession != VillagerProfession.NONE && profession != VillagerProfession.NITWIT) { + tickCount = 0; + return; + } + + if (tickCount > 0) { + tickCount--; + } + else { + tickCount = SLSCarpetSettings.skipTicksForJoblessVillager + 1; + ci.cancel(); + + if (this.getHeadRollingTimeLeft() > 0) { + this.setHeadRollingTimeLeft(this.getHeadRollingTimeLeft() - 1); + } + this.decayGossip(); + } + } + } +} diff --git a/src/main/resources/assets/slsaddition/lang/en_us.json b/src/main/resources/assets/slsaddition/lang/en_us.json index eb22787..e2705ed 100644 --- a/src/main/resources/assets/slsaddition/lang/en_us.json +++ b/src/main/resources/assets/slsaddition/lang/en_us.json @@ -1,3 +1,6 @@ { - "carpet.rule.obtainableReinforcedDeepSlate.desc": "When an anvil falls on 64 dropped deepslates, they will be turned in a reinforced deepslate instead of disappearing." + "carpet.rule.obtainableReinforcedDeepSlate.desc": "When an anvil falls on 64 dropped deepslates, they will be turned in a reinforced deepslate instead of disappearing.", + "carpet.rule.skipTicksForJoblessVillager.desc": "Villagers will skip ticks if they have no job.", + "carpet.rule.maxVillagersInABlock.desc": "The maximum number of villagers that can be in a block, set to -1 to disable.", + "carpet.rule.creativeNoInfinitePickup.desc": "If my inventory is full, don't pick up items in creative mode." } diff --git a/src/main/resources/assets/slsaddition/lang/zh_cn.json b/src/main/resources/assets/slsaddition/lang/zh_cn.json new file mode 100644 index 0000000..ba4e1ae --- /dev/null +++ b/src/main/resources/assets/slsaddition/lang/zh_cn.json @@ -0,0 +1,6 @@ +{ + "carpet.rule.maxVillagersInABlock.desc": "每个方块中最大村民数量,设置-1为无限制", + "carpet.rule.obtainableReinforcedDeepSlate.desc": "当铁砧在64个深板岩的凋落物上时,可以获得强化深板岩", + "carpet.rule.skipTicksForJoblessVillager.desc": "村民没有工作时,跳过村民的tick", + "carpet.rule.creativeNoInfinitePickup.desc": "创造模式下,玩家不能无限制地拾取物品" +} \ No newline at end of file diff --git a/src/main/resources/slsaddition.mixins.json b/src/main/resources/slsaddition.mixins.json index cf57d1b..df2b9dd 100644 --- a/src/main/resources/slsaddition.mixins.json +++ b/src/main/resources/slsaddition.mixins.json @@ -4,8 +4,11 @@ "package": "com.github.zly2006.carpetslsaddition.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ + "AccessorPlayerAbilities", "MixinFallingBlockEntity", - "MixinItemEntity" + "MixinItemEntity", + "MixinPlayerInventory", + "MixinVillagerEntity" ], "client": [ ],