From d059cd4b8d5dc5ade90baf46b9cfa6cbd47f3a0a Mon Sep 17 00:00:00 2001 From: Oth3r Date: Tue, 18 Jun 2024 23:13:07 -0500 Subject: [PATCH] Revert "undo next version" This reverts commit 4a7624d5 --- src/main/java/one/oth3r/sit/Events.java | 83 ++++----- src/main/java/one/oth3r/sit/ModMenu.java | 168 ++++++++---------- src/main/java/one/oth3r/sit/Sit.java | 29 ++- src/main/java/one/oth3r/sit/SitClient.java | 16 +- src/main/java/one/oth3r/sit/SitCommand.java | 31 ++-- src/main/java/one/oth3r/sit/Utl.java | 90 +++++----- src/main/java/one/oth3r/sit/file/Config.java | 45 +++-- src/main/resources/assets/sit/lang/en_us.json | 102 ++++++----- 8 files changed, 274 insertions(+), 290 deletions(-) diff --git a/src/main/java/one/oth3r/sit/Events.java b/src/main/java/one/oth3r/sit/Events.java index fa5d50c..9ed4bc3 100644 --- a/src/main/java/one/oth3r/sit/Events.java +++ b/src/main/java/one/oth3r/sit/Events.java @@ -23,8 +23,9 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import one.oth3r.sit.Utl.HandSettings.HandType; -import one.oth3r.sit.file.Config; +import one.oth3r.sit.Utl.HandType; +import one.oth3r.sit.Utl.PlayerSettings; +import one.oth3r.sit.Utl.PlayerSettings.Setting; import java.util.*; @@ -39,25 +40,25 @@ public class Events { ArrayList notUsable = new ArrayList<>(food); notUsable.add(UseAction.NONE); HashMap itemMap = new HashMap<>(); - itemMap.put(Utl.HandSettings.HandType.main,player.getMainHandStack()); - itemMap.put(Utl.HandSettings.HandType.off,player.getOffHandStack()); + itemMap.put(HandType.main,player.getMainHandStack()); + itemMap.put(HandType.off,player.getOffHandStack()); // if sneaking cant sit if (player.isSneaking()) return false; // for both hands - for (HandType type: Utl.HandSettings.HandType.values()) { + for (HandType type:HandType.values()) { ItemStack targetStack = itemMap.get(type); // if req is empty and the item isn't empty, false - if (Utl.HandSettings.getReq(player,type).equals(Config.HandRequirement.empty) && !targetStack.isEmpty()) return false; + if (PlayerSettings.getRequirement(player,type).equals(config.HandRequirement.empty) && !targetStack.isEmpty()) return false; // if req is restrictive - if (Utl.HandSettings.getReq(player,type).equals(Config.HandRequirement.restrictive)) { + if (PlayerSettings.getRequirement(player,type).equals(config.HandRequirement.restrictive)) { // if item is in blacklist, false - if (checkList(Utl.HandSettings.getList(player,type,"blacklist"),targetStack)) return false; + if (checkList(PlayerSettings.getList(player,type,Setting.blacklist),targetStack)) return false; // if item is NOT in whitelist - if (!checkList(Utl.HandSettings.getList(player,type,"whitelist"),targetStack)) { + if (!checkList(PlayerSettings.getList(player,type,Setting.whitelist),targetStack)) { // if block is restricted and items is block, false, ect - if (Utl.HandSettings.getBool(player,type,"block") && (targetStack.getItem() instanceof BlockItem)) return false; - if (Utl.HandSettings.getBool(player,type,"food") && food.contains(targetStack.getUseAction())) return false; - if (Utl.HandSettings.getBool(player,type,"usable") && !notUsable.contains(targetStack.getUseAction())) return false; + if (PlayerSettings.getToggle(player,type,Setting.block) && (targetStack.getItem() instanceof BlockItem)) return false; + if (PlayerSettings.getToggle(player,type,Setting.food) && food.contains(targetStack.getUseAction())) return false; + if (PlayerSettings.getToggle(player,type,Setting.usable) && !notUsable.contains(targetStack.getUseAction())) return false; } } } @@ -73,7 +74,7 @@ public class Events { // get a hashmap of custom blocks HashMap> map = new HashMap<>(); int i = 1; - for (String s: Config.customBlocks) { + for (String s:config.customBlocks) { String[] split = s.split("\\|"); HashMap data = new HashMap<>(); data.put("block",split[0]); @@ -101,12 +102,12 @@ public class Events { for (Entity entity:entities.values()) if (entity.getBlockPos().equals(pos) || entity.getBlockPos().add(0,1,0).equals(pos)) return false; // return for the 4 default types - if (block instanceof StairsBlock && Config.stairsOn) return blockState.get(StairsBlock.HALF) == BlockHalf.BOTTOM; - if (block instanceof SlabBlock && Config.slabsOn) return blockState.get(SlabBlock.TYPE) == SlabType.BOTTOM; - if (block instanceof CarpetBlock && Config.carpetsOn) return true; - if (blockState.isFullCube(world,pos.add(0,1,0)) && Config.fullBlocksOn) return true; + if (block instanceof StairsBlock && config.stairsOn) return blockState.get(StairsBlock.HALF) == BlockHalf.BOTTOM; + if (block instanceof SlabBlock && config.slabsOn) return blockState.get(SlabBlock.TYPE) == SlabType.BOTTOM; + if (block instanceof CarpetBlock && config.carpetsOn) return true; + if (blockState.isFullCube(world,pos.add(0,1,0)) && config.fullBlocksOn) return true; // custom checker - if (Config.customOn && Config.customBlocks.size() != 0) { + if (config.customOn && !config.customBlocks.isEmpty()) { for (HashMap map:getCustomBlocks().values()) { String blockID = Registries.BLOCK.getId(block).toString(); if (map.get("block").equals(blockID)) { @@ -150,7 +151,7 @@ public class Events { entity.updatePositionAndAngles(pos.getX() + 0.5, pos.getY()+.78, pos.getZ() + 0.5, 0, 0); hitBoxY = 2; } - if (Config.customOn && !Config.customBlocks.isEmpty()) { + if (config.customOn && !config.customBlocks.isEmpty()) { for (HashMap map:getCustomBlocks().values()) { String blockID = Registries.BLOCK.getId(block).toString(); if (map.get("block").equals(blockID)) { @@ -168,24 +169,6 @@ public class Events { if (entity.getY() <= pos.getY()+.35+oneTwentyTwo) entity.setPitch(90); // below else entity.setPitch(-90); // above } - public static boolean sit(ServerPlayerEntity player, BlockPos pos) { - // todo interactions entity to make the sitting hitbox? - World world = player.getWorld(); - DisplayEntity.TextDisplayEntity entity = new DisplayEntity.TextDisplayEntity(EntityType.TEXT_DISPLAY,player.getServerWorld()); - setEntity(pos,world,entity); - if (checkBlocks(pos,world,isAboveBlockheight(entity))) { - if (entities.containsKey(player)) { - if (!Config.sitWhileSeated) return false; - entities.get(player).setRemoved(Entity.RemovalReason.DISCARDED); - entities.remove(player); - } - player.getServerWorld().spawnEntity(entity); - player.startRiding(entity); - entities.put(player,entity); - return true; - } - return false; - } public static void register() { ServerTickEvents.END_SERVER_TICK.register(minecraftServer -> minecraftServer.execute(Events::cleanUp)); // PLAYER JOIN @@ -193,12 +176,12 @@ public class Events { ServerPlayerEntity player = handler.player; checkPlayers.put(player,2); // put server settings in the player settings - Sit.playerSettings.put(player, Utl.HandSettings.getHandSettings()); + Sit.playerSettings.put(player, PlayerSettings.getHandSettings()); }); ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> { ServerPlayerEntity player = handler.player; if (entities.containsKey(player)) { - if (!Config.keepActive) { + if (!config.keepActive) { player.dismountVehicle(); entities.get(player).setRemoved(Entity.RemovalReason.DISCARDED); } @@ -215,12 +198,22 @@ public class Events { if (player == null) return ActionResult.PASS; if (hand == net.minecraft.util.Hand.MAIN_HAND && hitResult.getType() == HitResult.Type.BLOCK) { BlockPos pos = hitResult.getBlockPos(); - // check the players hands if (!checkLogic(player)) return ActionResult.PASS; - // make the player sit - boolean status = sit(player,pos); - // if sat, cancel / FAIL the use block event - if (status) return ActionResult.FAIL; + // todo interactions entity to make the hitbox? + // make the entity first before checking to make sure the blocks around are fine + DisplayEntity.TextDisplayEntity entity = new DisplayEntity.TextDisplayEntity(EntityType.TEXT_DISPLAY,player.getServerWorld()); + setEntity(pos,world,entity); + if (checkBlocks(pos,world,isAboveBlockheight(entity))) { + if (entities.containsKey(player)) { + if (!config.sitWhileSeated) return ActionResult.PASS; + entities.get(player).setRemoved(Entity.RemovalReason.DISCARDED); + entities.remove(player); + } + player.getServerWorld().spawnEntity(entity); + player.startRiding(entity); + entities.put(player,entity); + return ActionResult.FAIL; + } } return ActionResult.PASS; }); @@ -247,7 +240,7 @@ public class Events { BlockState blockState = player.getWorld().getBlockState(pos); // check if said block is still there if (blockState.isAir()) { - player.teleport(player.getX(),player.getBlockY()+1,player.getZ(),false); + player.teleport(player.getX(),player.getBlockY()+1,player.getZ()); entity.setRemoved(Entity.RemovalReason.DISCARDED); entityLoop.remove(); } diff --git a/src/main/java/one/oth3r/sit/ModMenu.java b/src/main/java/one/oth3r/sit/ModMenu.java index 189c77f..c61cd40 100644 --- a/src/main/java/one/oth3r/sit/ModMenu.java +++ b/src/main/java/one/oth3r/sit/ModMenu.java @@ -10,34 +10,27 @@ import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.text.TextColor; import net.minecraft.util.Formatting; -import one.oth3r.sit.file.Config; public class ModMenu implements ModMenuApi { - private static MutableText lang(String key) { - return Text.translatable("config.sit."+key); - } private static MutableText lang(String key, Object... args) { - return Text.translatable("config.sit."+key,args); + return Utl.lang("config."+key,args); } @Override public ConfigScreenFactory getModConfigScreenFactory() { - // return null if YACL isn't installed to not throw an error - if (!yaclCheck()) return screen -> null; - return parent -> YetAnotherConfigLib.createBuilder().save(Config::save) + return parent -> YetAnotherConfigLib.createBuilder().save(config::save) .title(Text.of("Sit!")) .category(ConfigCategory.createBuilder() .name(lang("category.general")) - .tooltip(lang("category.general.tooltip")) .option(Option.createBuilder() .name(lang("general.keep_active")) .description(OptionDescription.of(lang("general.keep_active.description"))) - .binding(Config.defaults.keepActive, () -> Config.keepActive, n -> Config.keepActive = n) + .binding(config.defaults.keepActive, () -> config.keepActive, n -> config.keepActive = n) .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter()) .build()) .option(Option.createBuilder() .name(lang("general.sit_while_seated")) .description(OptionDescription.of(lang("general.sit_while_seated.description"))) - .binding(Config.defaults.sitWhileSeated, () -> Config.sitWhileSeated, n -> Config.sitWhileSeated = n) + .binding(config.defaults.sitWhileSeated, () -> config.sitWhileSeated, n -> config.sitWhileSeated = n) .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter()) .build()) .group(OptionGroup.createBuilder() @@ -45,28 +38,28 @@ public class ModMenu implements ModMenuApi { .description(OptionDescription.of(lang("general.sittable.description"))) .option(Option.createBuilder() .name(lang("general.sittable.stairs")) - .binding(Config.defaults.stairsOn, () -> Config.stairsOn, n -> Config.stairsOn = n) + .binding(config.defaults.stairsOn, () -> config.stairsOn, n -> config.stairsOn = n) .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter()) .build()) .option(Option.createBuilder() .name(lang("general.sittable.slabs")) - .binding(Config.defaults.slabsOn, () -> Config.slabsOn, n -> Config.slabsOn = n) + .binding(config.defaults.slabsOn, () -> config.slabsOn, n -> config.slabsOn = n) .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter()) .build()) .option(Option.createBuilder() .name(lang("general.sittable.carpets")) - .binding(Config.defaults.carpetsOn, () -> Config.carpetsOn, n -> Config.carpetsOn = n) + .binding(config.defaults.carpetsOn, () -> config.carpetsOn, n -> config.carpetsOn = n) .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter()) .build()) .option(Option.createBuilder() .name(lang("general.sittable.full_blocks")) - .binding(Config.defaults.fullBlocksOn, () -> Config.fullBlocksOn, n -> Config.fullBlocksOn = n) + .binding(config.defaults.fullBlocksOn, () -> config.fullBlocksOn, n -> config.fullBlocksOn = n) .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter()) .build()) .option(Option.createBuilder() .name(lang("general.sittable.custom")) .description(OptionDescription.of(lang("general.sittable.custom.description"))) - .binding(Config.defaults.customOn, () -> Config.customOn, n -> Config.customOn = n) + .binding(config.defaults.customOn, () -> config.customOn, n -> config.customOn = n) .controller(opt -> BooleanControllerBuilder.create(opt).onOffFormatter()) .build()) .build()) @@ -74,7 +67,7 @@ public class ModMenu implements ModMenuApi { .name(lang("general.sittable_blocks")) .description(OptionDescription.of( lang("general.sittable_blocks.description") - .append("\n\n").append(lang("general.sittable_blocks.description_2", + .append("\n\n").append(lang("example", Text.literal("\"") .append(Text.literal("minecraft:campfire").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA)))) .append("|") @@ -83,134 +76,119 @@ public class ModMenu implements ModMenuApi { .append(Text.literal("1").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))) .append("|") .append(Text.literal("lit=false").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GOLD)))) - .append("\"").styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY))))) - .append("\n\n").append(lang("general.sittable_blocks.description_4").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA)))) - .append("\n").append(lang("general.sittable_blocks.description_5").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED)))) - .append("\n").append(lang("general.sittable_blocks.description_6").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))) - .append("\n").append(lang("general.sittable_blocks.description_7").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GOLD)))) - .append("\n\n").append(lang("general.sittable_blocks.description_8").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.YELLOW)))))) - .binding(Config.defaults.customBlocks, () -> Config.customBlocks, n -> Config.customBlocks = n) + .append("\"").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GRAY))))) + .append("\n\n").append(lang("general.sittable_blocks.description.2").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA)))) + .append("\n").append(lang("general.sittable_blocks.description.3").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED)))) + .append("\n").append(lang("general.sittable_blocks.description.4").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))) + .append("\n").append(lang("general.sittable_blocks.description.5").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GOLD)))) + .append("\n\n").append(lang("general.sittable_blocks.description.6").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.YELLOW)))))) + .binding(config.defaults.customBlocks, () -> config.customBlocks, n -> config.customBlocks = n) .controller(StringControllerBuilder::create) .initial("") .build()) .build()) .category(ConfigCategory.createBuilder() .name(lang("category.main_hand")) - .tooltip(lang("category.main_hand.tooltip")) - .option(Option.createBuilder() - .name(lang("hand.requirements")) - .description(OptionDescription.of(lang("hand.requirements.description") - .append("\n\n").append(lang("hand.requirements.description_2").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA)))) - .append("\n").append(lang("hand.requirements.description_3").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))) - .append("\n").append(lang("hand.requirements.description_4").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED)))))) - .binding(Config.defaults.mainReq, () -> Config.mainReq, n -> Config.mainReq = n) - .controller(opt -> EnumControllerBuilder.create(opt).enumClass(Config.HandRequirement.class) - .formatValue(v -> Text.translatable("config.sit."+v.name().toLowerCase()))) + .option(Option.createBuilder() + .name(lang("hand.requirement")) + .description(OptionDescription.of(lang("hand.requirement.description") + .append("\n\n").append(lang("hand.requirement.description.2",lang("hand.requirement.empty")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA)))) + .append("\n").append(lang("hand.requirement.description.3",lang("hand.requirement.restrictive")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))) + .append("\n").append(lang("hand.requirement.description.4",lang("hand.requirement.none")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED)))))) + .binding(config.defaults.mainReq, () -> config.mainReq, n -> config.mainReq = n) + .controller(opt -> EnumControllerBuilder.create(opt).enumClass(config.HandRequirement.class) + .formatValue(v -> lang("hand.requirement."+v.toString()))) .build()) .group(OptionGroup.createBuilder() - .name(lang("hand.restrictions")) - .description(OptionDescription.of(lang("hand.restrictions.description"))) + .name(lang("hand.restriction")) + .description(OptionDescription.of(lang("hand.restriction.description"))) .option(Option.createBuilder() - .name(lang("hand.restrictions.blocks")) - .binding(Config.defaults.mainBlock,()-> Config.mainBlock, n -> Config.mainBlock = n) + .name(lang("hand.restriction.blocks")) + .binding(config.defaults.mainBlock,()-> config.mainBlock,n -> config.mainBlock = n) .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter()) .build()) .option(Option.createBuilder() - .name(lang("hand.restrictions.food")) - .binding(Config.defaults.mainFood,()-> Config.mainFood, n -> Config.mainFood = n) + .name(lang("hand.restriction.food")) + .binding(config.defaults.mainFood,()-> config.mainFood,n -> config.mainFood = n) .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter()) .build()) .option(Option.createBuilder() - .name(lang("hand.restrictions.usable")) - .description(OptionDescription.of(lang("hand.restrictions.usable.description"))) - .binding(Config.defaults.mainUsable,()-> Config.mainUsable, n -> Config.mainUsable = n) + .name(lang("hand.restriction.usable")) + .description(OptionDescription.of(lang("hand.restriction.usable.description"))) + .binding(config.defaults.mainUsable,()-> config.mainUsable,n -> config.mainUsable = n) .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter()) .build()) .build()) .group(ListOption.createBuilder() - .name(lang("hand.whitelist")) - .description(OptionDescription.of(lang("hand.whitelist.description") - .append("\n\n").append(lang("hand.list.description")) - .append(lang("hand.list.description_2").styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY)))))) - .binding(Config.defaults.mainWhitelist, () -> Config.mainWhitelist, n -> Config.mainWhitelist = n) + .name(lang("hand.restriction.whitelist")) + .description(OptionDescription.of(lang("hand.restriction.list.description") + .append("\n\n").append(lang("example", + Text.empty().append(Utl.Assets.LIST).styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY))))))) + .binding(config.defaults.mainWhitelist, () -> config.mainWhitelist, n -> config.mainWhitelist = n) .controller(StringControllerBuilder::create) .initial("") .build()) .group(ListOption.createBuilder() - .name(lang("hand.blacklist")) - .description(OptionDescription.of(lang("hand.blacklist.description") - .append("\n\n").append(lang("hand.list.description")) - .append(lang("hand.list.description_2").styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY)))))) - .binding(Config.defaults.mainBlacklist, () -> Config.mainBlacklist, n -> Config.mainBlacklist = n) + .name(lang("hand.restriction.blacklist")) + .description(OptionDescription.of(lang("hand.restriction.list.description") + .append("\n\n").append(lang("example", + Text.empty().append(Utl.Assets.LIST).styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY))))))) + .binding(config.defaults.mainBlacklist, () -> config.mainBlacklist, n -> config.mainBlacklist = n) .controller(StringControllerBuilder::create) .initial("") .build()) .build()) .category(ConfigCategory.createBuilder() .name(lang("category.off_hand")) - .tooltip(lang("category.off_hand.tooltip")) - .option(Option.createBuilder() - .name(lang("hand.requirements")) - .description(OptionDescription.of(lang("hand.requirements.description") - .append("\n\n").append(lang("hand.requirements.description_2").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA)))) - .append("\n").append(lang("hand.requirements.description_3").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))) - .append("\n").append(lang("hand.requirements.description_4").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED)))))) - .binding(Config.defaults.offReq, () -> Config.offReq, n -> Config.offReq = n) - .controller(opt -> EnumControllerBuilder.create(opt).enumClass(Config.HandRequirement.class) - .formatValue(v -> Text.translatable("config.sit."+v.name().toLowerCase()))) + .option(Option.createBuilder() + .name(lang("hand.requirement")) + .description(OptionDescription.of(lang("hand.requirement.description") + .append("\n\n").append(lang("hand.requirement.description.2",lang("hand.requirement.empty")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.AQUA)))) + .append("\n").append(lang("hand.requirement.description.3",lang("hand.requirement.restrictive")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))) + .append("\n").append(lang("hand.requirement.description.4",lang("hand.requirement.none")).styled(style -> style.withColor(TextColor.fromFormatting(Formatting.RED)))))) + .binding(config.defaults.offReq, () -> config.offReq, n -> config.offReq = n) + .controller(opt -> EnumControllerBuilder.create(opt).enumClass(config.HandRequirement.class) + .formatValue(v -> lang("hand.requirement."+v.toString()))) .build()) .group(OptionGroup.createBuilder() - .name(lang("hand.restrictions")) - .description(OptionDescription.of(lang("hand.restrictions.description"))) + .name(lang("hand.restriction")) + .description(OptionDescription.of(lang("hand.restriction.description"))) .option(Option.createBuilder() - .name(lang("hand.restrictions.blocks")) - .binding(Config.defaults.offBlock,()-> Config.offBlock, n -> Config.offBlock = n) + .name(lang("hand.restriction.blocks")) + .binding(config.defaults.offBlock,()-> config.offBlock,n -> config.offBlock = n) .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter()) .build()) .option(Option.createBuilder() - .name(lang("hand.restrictions.food")) - .binding(Config.defaults.offFood,()-> Config.offFood, n -> Config.offFood = n) + .name(lang("hand.restriction.food")) + .binding(config.defaults.offFood,()-> config.offFood,n -> config.offFood = n) .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter()) .build()) .option(Option.createBuilder() - .name(lang("hand.restrictions.usable")) - .description(OptionDescription.of(lang("hand.restrictions.usable.description"))) - .binding(Config.defaults.offUsable,()-> Config.offUsable, n -> Config.offUsable = n) + .name(lang("hand.restriction.usable")) + .description(OptionDescription.of(lang("hand.restriction.usable.description"))) + .binding(config.defaults.offUsable,()-> config.offUsable,n -> config.offUsable = n) .controller(opt -> BooleanControllerBuilder.create(opt).trueFalseFormatter()) .build()) .build()) .group(ListOption.createBuilder() - .name(lang("hand.whitelist")) - .description(OptionDescription.of(lang("hand.whitelist.description") - .append("\n\n").append(lang("hand.list.description")) - .append(lang("hand.list.description_2").styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY)))))) - .binding(Config.defaults.offWhitelist, () -> Config.offWhitelist, n -> Config.offWhitelist = n) + .name(lang("hand.restriction.whitelist")) + .description(OptionDescription.of(lang("hand.restriction.list.description") + .append("\n\n").append(lang("example", + Text.empty().append(Utl.Assets.LIST).styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY))))))) + .binding(config.defaults.offWhitelist, () -> config.offWhitelist, n -> config.offWhitelist = n) .controller(StringControllerBuilder::create) .initial("") .build()) .group(ListOption.createBuilder() - .name(lang("hand.blacklist")) - .description(OptionDescription.of(lang("hand.blacklist.description") - .append("\n\n").append(lang("hand.list.description")) - .append(lang("hand.list.description_2").styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY)))))) - .binding(Config.defaults.offBlacklist, () -> Config.offBlacklist, n -> Config.offBlacklist = n) + .name(lang("hand.restriction.blacklist")) + .description(OptionDescription.of(lang("hand.restriction.list.description") + .append("\n\n").append(lang("example", + Text.empty().append(Utl.Assets.LIST).styled(style -> style.withItalic(true).withColor(TextColor.fromFormatting(Formatting.GRAY))))))) + .binding(config.defaults.offBlacklist, () -> config.offBlacklist, n -> config.offBlacklist = n) .controller(StringControllerBuilder::create) .initial("") .build()) .build()) .build().generateScreen(parent); } - - /** - * check if YACL is installed by getting a class and seeing if it throws - * @return if YACL is installed - */ - public static boolean yaclCheck() { - try { - Class.forName("dev.isxander.yacl3.platform.Env"); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } } diff --git a/src/main/java/one/oth3r/sit/Sit.java b/src/main/java/one/oth3r/sit/Sit.java index 9874dad..bb837c5 100644 --- a/src/main/java/one/oth3r/sit/Sit.java +++ b/src/main/java/one/oth3r/sit/Sit.java @@ -5,15 +5,10 @@ import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.CommandManager; import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import one.oth3r.sit.file.Config; -import one.oth3r.sit.packet.CustomPayloads; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,20 +29,18 @@ public class Sit implements ModInitializer { //todo future: // make it so it updates the sitting height and pos based on the block so if it changed while offline it still works (or if stair changes shape) // inner stair offset & custom support for that ig - Config.load(); + config.load(); Events.register(); //PACKETS - PayloadTypeRegistry.playC2S().register(CustomPayloads.SettingsPayload.ID, CustomPayloads.SettingsPayload.CODEC); - ServerPlayNetworking.registerGlobalReceiver(CustomPayloads.SettingsPayload.ID,((payload, context) -> server.execute(() -> { - Type hashMapToken = new TypeToken>() {}.getType(); - Gson gson = new GsonBuilder().disableHtmlEscaping().create(); - LOGGER.info(String.format("Received custom sitting settings from %s.",context.player().getName().getString())); - playerSettings.put(context.player(),gson.fromJson(payload.value(),hashMapToken)); - }))); - } - - public static MutableText lang(String key, Object... args) { - if (isClient) return Text.translatable(key, args); - else return LangReader.of(key, args).getTxT(); + ServerPlayNetworking.registerGlobalReceiver(PacketBuilder.getIdentifier(), + (server, player, handler, buf, responseSender) -> { + // copy to not throw errors + PacketBuilder packet = new PacketBuilder(buf.copy()); + server.execute(() -> { + Type hashMapToken = new TypeToken>() {}.getType(); + Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + playerSettings.put(player,gson.fromJson(packet.getMessage(),hashMapToken)); + }); + }); } } \ No newline at end of file diff --git a/src/main/java/one/oth3r/sit/SitClient.java b/src/main/java/one/oth3r/sit/SitClient.java index 9db2f99..621c788 100644 --- a/src/main/java/one/oth3r/sit/SitClient.java +++ b/src/main/java/one/oth3r/sit/SitClient.java @@ -4,8 +4,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import one.oth3r.sit.packet.CustomPayloads; public class SitClient implements ClientModInitializer { public static boolean inGame = false; @@ -15,19 +13,13 @@ public class SitClient implements ClientModInitializer { ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { inGame = true; // send a data packet whenever joining a server - sendSettingsPackets(); + client.execute(SitClient::sendPackets); }); // reset inGame ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> inGame = false); } - - /** - * sends the settings packets to the server is the client is in game - */ - public static void sendSettingsPackets() { - if (inGame) { - Gson gson = new GsonBuilder().disableHtmlEscaping().create(); - ClientPlayNetworking.send(new CustomPayloads.SettingsPayload(gson.toJson(Utl.HandSettings.getHandSettings()))); - } + public static void sendPackets() { + Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + new PacketBuilder(gson.toJson(Utl.PlayerSettings.getHandSettings())).send(); } } diff --git a/src/main/java/one/oth3r/sit/SitCommand.java b/src/main/java/one/oth3r/sit/SitCommand.java index d641d30..b740d5d 100644 --- a/src/main/java/one/oth3r/sit/SitCommand.java +++ b/src/main/java/one/oth3r/sit/SitCommand.java @@ -7,13 +7,15 @@ import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.decoration.DisplayEntity; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.TextColor; import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; -import one.oth3r.sit.file.Config; +import net.minecraft.world.World; import java.util.concurrent.CompletableFuture; @@ -46,25 +48,32 @@ public class SitCommand { // if console if (player == null) { if (args[0].equalsIgnoreCase("reload")) { - Config.load(); - Sit.LOGGER.info(Sit.lang("key.sit.command.reloaded").getString()); + config.load(); + Sit.LOGGER.info(Utl.lang("msg.reloaded").getString()); } return 1; } if (args[0].equalsIgnoreCase("sit")) { BlockPos pos = player.getBlockPos(); - // get the block under the player if player on top of a solid - if (!(player.getY() - ((int) player.getY()) > 0.00)) { + if (!(player.getY() -((int) player.getY()) > 0.00)) { pos = pos.add(0,-1,0); } + World world = player.getWorld(); // if already sitting, ignore if (Events.entities.containsKey(player)) return 1; - // sit - Events.sit(player,pos); + // make entity first to check the blocks + DisplayEntity.TextDisplayEntity entity = new DisplayEntity.TextDisplayEntity(EntityType.TEXT_DISPLAY,player.getServerWorld()); + Events.setEntity(pos,world,entity); + if (Events.checkBlocks(pos,world,Events.isAboveBlockheight(entity))) { + player.getServerWorld().spawnEntity(entity); + player.startRiding(entity); + Events.entities.put(player,entity); + return 1; + } } if (args[0].equalsIgnoreCase("reload")) { - Config.load(); - player.sendMessage(Sit.lang("key.sit.command.reloaded").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))); + config.load(); + player.sendMessage(Utl.lang("msg.reloaded").styled(style -> style.withColor(TextColor.fromFormatting(Formatting.GREEN)))); } if (args[0].equalsIgnoreCase("purgeChairEntities")) { String cmd = "kill @e[type=minecraft:text_display,name=\""+Sit.ENTITY_NAME+"\"]"; @@ -72,9 +81,9 @@ public class SitCommand { ParseResults parse = Sit.commandManager.getDispatcher().parse(cmd, player.getCommandSource()); Sit.commandManager.getDispatcher().execute(parse); - player.sendMessage(Sit.lang("key.sit.command.purged")); + player.sendMessage(Utl.lang("msg.purged")); } catch (CommandSyntaxException e) { - player.sendMessage(Sit.lang("key.sit.command.purged")); + player.sendMessage(Utl.lang("msg.purged")); e.printStackTrace(); } } diff --git a/src/main/java/one/oth3r/sit/Utl.java b/src/main/java/one/oth3r/sit/Utl.java index ed69d96..b1bd1fd 100644 --- a/src/main/java/one/oth3r/sit/Utl.java +++ b/src/main/java/one/oth3r/sit/Utl.java @@ -4,7 +4,8 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import net.minecraft.server.network.ServerPlayerEntity; -import one.oth3r.sit.file.Config; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; import java.lang.reflect.Type; import java.util.ArrayList; @@ -12,59 +13,62 @@ import java.util.HashMap; import java.util.List; public class Utl { - public static class HandSettings { + public static MutableText lang(String key, Object... args) { + if (Sit.isClient) return Text.translatable(key, args); + else return LangReader.of(key, args).getTxT(); + } + public enum HandType { + main, + off + } + public static class PlayerSettings { + public enum Setting { + requirement, + block, + food, + usable, + whitelist, + blacklist + } + /** + * Gets a HashMap of all player configurable settings. + * @return a map with player hand settings. + */ public static HashMap getHandSettings() { Gson gson = new GsonBuilder().disableHtmlEscaping().create(); HashMap settings = new HashMap<>(); - settings.put("hand.main.requirement",String.valueOf(Config.mainReq)); - settings.put("hand.main.block",String.valueOf(Config.mainBlock)); - settings.put("hand.main.food",String.valueOf(Config.mainFood)); - settings.put("hand.main.usable",String.valueOf(Config.mainUsable)); - settings.put("hand.main.whitelist",gson.toJson(Config.mainWhitelist)); - settings.put("hand.main.blacklist",gson.toJson(Config.mainBlacklist)); - settings.put("hand.off.requirement",String.valueOf(Config.offReq)); - settings.put("hand.off.block",String.valueOf(Config.offBlock)); - settings.put("hand.off.food",String.valueOf(Config.offFood)); - settings.put("hand.off.usable",String.valueOf(Config.offUsable)); - settings.put("hand.off.whitelist",gson.toJson(Config.offWhitelist)); - settings.put("hand.off.blacklist",gson.toJson(Config.offBlacklist)); + // main hand + settings.put("hand.main."+Setting.requirement,String.valueOf(config.mainReq)); + settings.put("hand.main."+Setting.block,String.valueOf(config.mainBlock)); + settings.put("hand.main."+Setting.food,String.valueOf(config.mainFood)); + settings.put("hand.main."+Setting.usable,String.valueOf(config.mainUsable)); + settings.put("hand.main."+Setting.whitelist,gson.toJson(config.mainWhitelist)); + settings.put("hand.main."+Setting.blacklist,gson.toJson(config.mainBlacklist)); + // copy but offhand + settings.put("hand.off."+Setting.requirement,String.valueOf(config.offReq)); + settings.put("hand.off."+Setting.block,String.valueOf(config.offBlock)); + settings.put("hand.off."+Setting.food,String.valueOf(config.offFood)); + settings.put("hand.off."+Setting.usable,String.valueOf(config.offUsable)); + settings.put("hand.off."+Setting.whitelist,gson.toJson(config.offWhitelist)); + settings.put("hand.off."+Setting.blacklist,gson.toJson(config.offBlacklist)); return settings; } - - public static Config.HandRequirement getReq(ServerPlayerEntity player, HandType type) { - return Config.HandRequirement.get(Sit.playerSettings.get(player).get("hand."+type+".requirement")); + // returns specific items from the player config + public static config.HandRequirement getRequirement(ServerPlayerEntity player, HandType type) { + return config.HandRequirement.get(Sit.playerSettings.get(player).get("hand."+type+".requirement")); } - - public static List getList(ServerPlayerEntity player, HandType type, String setting) { + public static List getList(ServerPlayerEntity player, HandType type, Setting setting) { Type listType = new TypeToken>() {}.getType(); return new Gson().fromJson(Sit.playerSettings.get(player).get("hand."+type+"."+setting),listType); } - - public static boolean getBool(ServerPlayerEntity player, HandType type, String setting) { + public static boolean getToggle(ServerPlayerEntity player, HandType type, Setting setting) { return Boolean.parseBoolean(Sit.playerSettings.get(player).get("hand."+type+"."+setting)); } - - public enum HandType { - main, - off - } } - public static class Num { - public static boolean isInt(String string) { - try { - Integer.parseInt(string); - } catch (NumberFormatException nfe) { - return false; - } - return true; - } - public static boolean isFloat(String string) { - try { - Float.parseFloat(string); - } catch (NumberFormatException nfe) { - return false; - } - return true; - } + public static class Assets { + public static final String CUSTOM_BLOCKS = "\"minecraft:campfire|0.255|1|lit=false\""; + public static final String REQUIREMENT_OPTIONS = String.format("%s, %s, %s", + config.HandRequirement.empty,config.HandRequirement.restrictive,config.HandRequirement.none); + public static final String LIST = "\"minecraft:torch\""; } } diff --git a/src/main/java/one/oth3r/sit/file/Config.java b/src/main/java/one/oth3r/sit/file/Config.java index 5c5c802..a2c2290 100644 --- a/src/main/java/one/oth3r/sit/file/Config.java +++ b/src/main/java/one/oth3r/sit/file/Config.java @@ -165,7 +165,7 @@ public class Config { } } public static String lang(String key, Object... args) { - return LangReader.of("config.sit."+key, args).getTxT().getString(); + return Utl.lang("config."+key, args).getString(); } public static void save() { try (var file = Files.newBufferedWriter(configFile().toPath(), StandardCharsets.UTF_8)) { @@ -184,34 +184,45 @@ public class Config { file.write("\ncarpets=" + carpetsOn); file.write("\nfull-blocks=" + fullBlocksOn); file.write("\ncustom=" + customOn); - file.write("\n# "+Sit.lang("config.sit."+ + file.write("\n# "+ Utl.lang("config."+ "general.sittable_blocks.description") - .append("\n# ").append(lang("general.sittable_blocks.description_2", - "\"minecraft:campfire|0.255|1|lit=false\"")) - .append("\n# ").append(lang("general.sittable_blocks.description_4")) - .append("\n# ").append(lang("general.sittable_blocks.description_5")) - .append("\n# ").append(lang("general.sittable_blocks.description_6")) - .append("\n# ").append(lang("general.sittable_blocks.description_7")) - .append("\n# ").append(lang("general.sittable_blocks.description_8")).getString()); + .append("\n# ").append(lang("example",Utl.Assets.CUSTOM_BLOCKS)) + .append("\n# ").append(lang("general.sittable_blocks.description.2")) + .append("\n# ").append(lang("general.sittable_blocks.description.3")) + .append("\n# ").append(lang("general.sittable_blocks.description.4")) + .append("\n# ").append(lang("general.sittable_blocks.description.5")) + .append("\n# ").append(lang("general.sittable_blocks.description.6")).getString()); file.write("\ncustom-blocks="+gson.toJson(customBlocks)); file.write("\n\n# "+lang("hand")); - file.write("\n# "+Sit.lang("config.sit."+ - "hand.requirements.description") - .append("\n# ").append(lang("hand.requirements.description_2")) - .append("\n# ").append(lang("hand.requirements.description_3")) - .append("\n# ").append(lang("hand.requirements.description_4")).getString()); + file.write("\n# "+ Utl.lang("config."+ + "hand.requirement.description") + .append("\n# ").append(lang("hand.requirement.description.2",HandRequirement.empty)) + .append("\n# ").append(lang("hand.requirement.description.3",HandRequirement.restrictive)) + .append("\n# ").append(lang("hand.requirement.description.4",HandRequirement.none)).getString()); + file.write("\n# "+lang("hand.requirement.options",Utl.Assets.REQUIREMENT_OPTIONS)); file.write("\nhand.main.requirement=" + mainReq); + file.write("\n#"); + file.write("\nhand.off.requirement=" + offReq); + + file.write("\n\n# "+lang("hand.restriction")); + file.write("\n# "+lang("hand.restriction.description")); file.write("\nhand.main.block=" + mainBlock); file.write("\nhand.main.food=" + mainFood); file.write("\nhand.main.usable=" + mainUsable); - file.write("\nhand.main.whitelist="+gson.toJson(mainWhitelist)); - file.write("\nhand.main.blacklist="+gson.toJson(mainBlacklist)); - file.write("\nhand.off.requirement=" + offReq); + file.write("\n#"); file.write("\nhand.off.block=" + offBlock); file.write("\nhand.off.food=" + offFood); file.write("\nhand.off.usable=" + offUsable); + + file.write("\n\n# "+lang("hand.restriction.list")); + file.write("\n# "+lang("hand.restriction.list.description")); + file.write("\n# "+lang("example",Utl.Assets.LIST)); + file.write("\nhand.main.whitelist="+gson.toJson(mainWhitelist)); + file.write("\nhand.main.blacklist="+gson.toJson(mainBlacklist)); + file.write("\n#"); file.write("\nhand.off.whitelist="+gson.toJson(offWhitelist)); file.write("\nhand.off.blacklist="+gson.toJson(offBlacklist)); + // send packets to update the settings on the server SitClient.sendSettingsPackets(); } catch (Exception e) { diff --git a/src/main/resources/assets/sit/lang/en_us.json b/src/main/resources/assets/sit/lang/en_us.json index fe8916c..703f71c 100644 --- a/src/main/resources/assets/sit/lang/en_us.json +++ b/src/main/resources/assets/sit/lang/en_us.json @@ -1,51 +1,55 @@ { - "config.sit.empty": "Empty", - "config.sit.restrictive": "Restrictive", - "config.sit.none": "None", - "config.sit.category.general": "General", - "config.sit.category.general.tooltip": "General settings", - "config.sit.category.main_hand": "Main Hand", - "config.sit.category.main_hand.tooltip": "Main hand settings", - "config.sit.category.off_hand": "Off Hand", - "config.sit.category.off_hand.tooltip": "Off hand settings", - "config.sit.general.keep_active": "Keep Active", - "config.sit.general.keep_active.description": "Keeps the entities active even when logging off / shutting down", - "config.sit.general.sittable": "Sittable Blocks", - "config.sit.general.sittable.description": "Toggle the ability to sit on different block types.", - "config.sit.general.sit_while_seated": "Sit While Seated", - "config.sit.general.sit_while_seated.description": "Toggle the ability to sit on other blocks while already being seated on one.", - "config.sit.general.sittable.stairs": "Stairs", - "config.sit.general.sittable.slabs": "Slabs", - "config.sit.general.sittable.carpets": "Carpets", - "config.sit.general.sittable.full_blocks": "Full Blocks", - "config.sit.general.sittable.custom": "Custom", - "config.sit.general.sittable.custom.description": "Enables adding custom blocks to sit on.", - "config.sit.general.sittable_blocks": "Custom Sittable Blocks", - "config.sit.general.sittable_blocks.description": "Add custom sittable blocks!", - "config.sit.general.sittable_blocks.description_2": "Example: %s", - "config.sit.general.sittable_blocks.description_4": "First entry: custom block", - "config.sit.general.sittable_blocks.description_5": "Second entry: sitting height (number from 0-1 eg 0.52)", - "config.sit.general.sittable_blocks.description_6": "Third entry: hitbox size (where the player spawns above the entity when dismounting)", - "config.sit.general.sittable_blocks.description_7": "Fourth entry (optional): required blockstate to sit (Put a \"!\" to exclude blockstates)", - "config.sit.general.sittable_blocks.description_8": "Separate different entries with \"|\"!", - "config.sit.hand": "Hand Settings", - "config.sit.hand.requirements": "Requirements", - "config.sit.hand.requirements.description": "Hand requirements for sitting.", - "config.sit.hand.requirements.description_2": "Empty = hand has to be empty", - "config.sit.hand.requirements.description_3": "Restrictive = set restrictions for hand state", - "config.sit.hand.requirements.description_4": "None = can sit whenever", - "config.sit.hand.restrictions": "Restrictions", - "config.sit.hand.restrictions.description": "Toggle preset hand restrictions for sitting.", - "config.sit.hand.restrictions.blocks": "Blocks", - "config.sit.hand.restrictions.food": "Food", - "config.sit.hand.restrictions.usable": "Usable", - "config.sit.hand.restrictions.usable.description": "eg. bows, tridents, shield", - "config.sit.hand.whitelist": "Whitelist", - "config.sit.hand.whitelist.description": "Make a custom whitelist for items that the player can use to sit with.", - "config.sit.hand.blacklist": "Blacklist", - "config.sit.hand.blacklist.description": "Make a custom blacklist for items that the player can't use to sit with.", - "config.sit.hand.list.description": "Example: ", - "config.sit.hand.list.description_2": "\"minecraft:torch\"", - "key.sit.command.reloaded": "Reloaded the config!", - "key.sit.command.purged": "Purged all active chair entities!" + "category.sit": "Sit!", + "config.category.general": "General", + "config.category.main_hand": "Main Hand", + "config.category.off_hand": "Off Hand", + + "config.general.keep_active": "Keep Active", + "config.general.keep_active.description": "Keeps the entities active even when logging off / shutting down", + "config.general.sittable": "Sittable Blocks", + "config.general.sittable.description": "Toggle the ability to sit on different block types.", + "config.general.sit_while_seated": "Sit While Seated", + "config.general.sit_while_seated.description": "Toggle the ability to sit on other blocks while already being seated on one.", + "config.general.sittable.stairs": "Stairs", + "config.general.sittable.slabs": "Slabs", + "config.general.sittable.carpets": "Carpets", + "config.general.sittable.full_blocks": "Full Blocks", + "config.general.sittable.custom": "Custom", + "config.general.sittable.custom.description": "Enables adding custom blocks to sit on.", + "config.general.sittable_blocks": "Custom Sittable Blocks", + "config.general.sittable_blocks.description": "Add custom sittable blocks!", + "config.general.sittable_blocks.description.2": "First entry: custom block id", + "config.general.sittable_blocks.description.3": "Second entry: sitting height (number from 0-1 eg 0.52)", + "config.general.sittable_blocks.description.4": "Third entry: hitbox size (where the player spawns above the entity when dismounting)", + "config.general.sittable_blocks.description.5": "Fourth entry (optional): required blockstate to sit (Put a \"!\" to exclude blockstates)", + "config.general.sittable_blocks.description.6": "Separate different entries with \"|\"!", + "config.hand": "Hand Settings", + "config.hand.requirement": "Requirements", + "config.hand.requirement.empty": "Empty", + "config.hand.requirement.restrictive": "Restrictive", + "config.hand.requirement.none": "None", + "config.hand.requirement.description": "Hand requirements for sitting.", + "config.hand.requirement.description.2": "%s: hand has to be empty", + "config.hand.requirement.description.3": "%s: set restrictions for hand state", + "config.hand.requirement.description.4": "%s: can sit whenever", + "config.hand.requirement.options": "Options: %s", + "config.hand.restriction": "Restrictions", + "config.hand.restriction.description": "Toggle custom hand restrictions for sitting.", + "config.hand.restriction.blocks": "Blocks", + "config.hand.restriction.food": "Food", + "config.hand.restriction.usable": "Usable", + "config.hand.restriction.usable.description": "eg. bows, tridents, shield", + "config.hand.restriction.list": "Item Restrictions", + "config.hand.restriction.list.description": "Allow or block certain items when the hand requirement is restrictive.", + "config.hand.restriction.whitelist": "Whitelist", + "config.hand.restriction.blacklist": "Blacklist", + "config.example": "Example: %s", + + "msg.sit_toggle.on": "Enabled Sitting!", + "msg.sit_toggle.off": "Disabled Sitting!", + "msg.reloaded": "Reloaded the config!", + "msg.purged": "Purged all active chair entities!", + + "key.toggle": "Toggle Sitting", + "key.sit": "Sit" } \ No newline at end of file