From 00eb7672beda4c89dea913ae94390232b87436c7 Mon Sep 17 00:00:00 2001 From: wothers Date: Sat, 20 May 2023 21:50:02 +0100 Subject: [PATCH 01/12] Added optional properties for giving effects on consuming food --- src/main/java/wothers/hr/items/HyperFood.java | 17 +++++++++++++++++ src/main/java/wothers/ift/ItemsFromText.java | 10 +++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/wothers/hr/items/HyperFood.java b/src/main/java/wothers/hr/items/HyperFood.java index 4f4d168..4f9aa96 100644 --- a/src/main/java/wothers/hr/items/HyperFood.java +++ b/src/main/java/wothers/hr/items/HyperFood.java @@ -1,19 +1,34 @@ package wothers.hr.items; +import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.item.FoodComponent; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; public class HyperFood extends HyperItem { private final int hunger; private final float saturation; private final boolean isSnack; + private final String effect; + private final int effectDuration; + private final int effectAmplifier; + private final float effectChance; public HyperFood(int maxStackSize, int hunger, float saturation, boolean isSnack, boolean isFireproof) { + this(maxStackSize, hunger, saturation, isSnack, null, 0, 0, 0f, isFireproof); + } + + public HyperFood(int maxStackSize, int hunger, float saturation, boolean isSnack, String effect, int effectDuration, int effectAmplifier, float effectChance, boolean isFireproof) { super(maxStackSize, isFireproof); this.hunger = hunger; this.saturation = saturation; this.isSnack = isSnack; + this.effect = effect; + this.effectDuration = effectDuration; + this.effectAmplifier = effectAmplifier; + this.effectChance = effectChance; } @Override @@ -25,6 +40,8 @@ public Item getItem() { FoodComponent.Builder builder = new FoodComponent.Builder().hunger(hunger).saturationModifier(saturation); if (isSnack) builder = builder.snack(); + if (effect != null) + builder = builder.statusEffect(new StatusEffectInstance(Registry.STATUS_EFFECT.get(new Identifier(effect)), effectDuration, effectAmplifier), effectChance); item = new Item(settings.food(builder.build())); } return item; diff --git a/src/main/java/wothers/ift/ItemsFromText.java b/src/main/java/wothers/ift/ItemsFromText.java index 5559767..6482ac6 100644 --- a/src/main/java/wothers/ift/ItemsFromText.java +++ b/src/main/java/wothers/ift/ItemsFromText.java @@ -62,7 +62,15 @@ private void parseItem(String namespaceName, String itemName, Properties p) { int hunger = Integer.parseInt(p.getProperty("hunger")); float saturation = Float.parseFloat(p.getProperty("saturation")); boolean isSnack = Boolean.parseBoolean(p.getProperty("isSnack")); - item = new HyperFood(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, isFireproof); + String effect = p.getProperty("effect"); + if (effect != null) { + int effectDuration = Integer.parseInt(p.getProperty("effectDuration")); + int effectAmplifier = Integer.parseInt(p.getProperty("effectAmplifier")); + float effectChance = Float.parseFloat(p.getProperty("effectChance")); + item = new HyperFood(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, effect, effectDuration, effectAmplifier, effectChance, isFireproof); + } else { + item = new HyperFood(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, isFireproof); + } break; case "tool": float miningSpeed = Float.parseFloat(p.getProperty("miningSpeed")); From 595215d1a0619ac7ffc48c37374860d50ee3fc3d Mon Sep 17 00:00:00 2001 From: wothers Date: Sat, 20 May 2023 21:55:51 +0100 Subject: [PATCH 02/12] IntelliJ reformat --- src/main/java/wothers/hr/HyperRegistry.java | 24 ++++++-------- src/main/java/wothers/hr/items/HyperFood.java | 9 ++---- src/main/java/wothers/hr/items/HyperItem.java | 8 ++--- src/main/java/wothers/hr/items/HyperTool.java | 12 ++----- src/main/java/wothers/ift/ItemsFromText.java | 32 ++++++++----------- .../wothers/ift/mixins/FuelLoaderMixin.java | 6 ++-- .../ift/mixins/LanguageLoaderMixin.java | 4 +-- .../wothers/ift/mixins/ModelLoaderMixin.java | 9 +++--- .../wothers/ift/mixins/RecipeLoaderMixin.java | 10 +++--- .../ift/mixins/TextureLoaderMixin.java | 10 +++--- 10 files changed, 50 insertions(+), 74 deletions(-) diff --git a/src/main/java/wothers/hr/HyperRegistry.java b/src/main/java/wothers/hr/HyperRegistry.java index df53619..f52ab2f 100644 --- a/src/main/java/wothers/hr/HyperRegistry.java +++ b/src/main/java/wothers/hr/HyperRegistry.java @@ -1,8 +1,5 @@ package wothers.hr; -import java.io.File; -import java.util.HashMap; -import java.util.Map; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -11,6 +8,9 @@ import net.minecraft.util.registry.Registry; import wothers.hr.items.HyperItem; import wothers.ift.ItemsFromText; +import java.io.File; +import java.util.HashMap; +import java.util.Map; public final class HyperRegistry { public static final HyperRegistry INSTANCE = new HyperRegistry(); @@ -26,10 +26,8 @@ private HyperRegistry() { } public void register(String namespaceName, String itemName, HyperItem item, String displayName, Boolean isHandheld) { - if (registeredItems.containsKey(namespaceName + ":item/" + itemName)) - throw new RuntimeException("Duplicate item"); - if (displayName == null) - throw new RuntimeException("Missing item display name"); + if (registeredItems.containsKey(namespaceName + ":item/" + itemName)) throw new RuntimeException("Duplicate item"); + if (displayName == null) throw new RuntimeException("Missing item display name"); Registry.register(Registry.ITEM, new Identifier(namespaceName, itemName), item.getItem()); langMap.put("item." + namespaceName + "." + itemName, displayName); registeredItems.put(namespaceName + ":item/" + itemName, isHandheld ? "handheld" : "generated"); @@ -62,12 +60,9 @@ private Recipe() { public void add(String namespaceName, String itemName, String recipe) { try { - if (recipe.startsWith("shaped,")) - resolveShapedRecipe(namespaceName, itemName, recipe.replace("shaped,", "")); - else if (recipe.startsWith("shapeless,")) - resolveShapelessRecipe(namespaceName, itemName, recipe.replace("shapeless,", "")); - else - throw new RuntimeException(); + if (recipe.startsWith("shaped,")) resolveShapedRecipe(namespaceName, itemName, recipe.replace("shaped,", "")); + else if (recipe.startsWith("shapeless,")) resolveShapelessRecipe(namespaceName, itemName, recipe.replace("shapeless,", "")); + else throw new RuntimeException(); } catch (Exception e) { ItemsFromText.LOGGER.warn("Failed to resolve recipe for: " + namespaceName + ":" + itemName); } @@ -149,8 +144,7 @@ private Texture() { } public void add(String namespaceName, String itemName, File textureFile) { - if (textureFile.exists()) - map.put(namespaceName + ":textures/item/" + itemName + ".png", textureFile); + if (textureFile.exists()) map.put(namespaceName + ":textures/item/" + itemName + ".png", textureFile); } public Map getMap() { diff --git a/src/main/java/wothers/hr/items/HyperFood.java b/src/main/java/wothers/hr/items/HyperFood.java index 4f9aa96..48f4c54 100644 --- a/src/main/java/wothers/hr/items/HyperFood.java +++ b/src/main/java/wothers/hr/items/HyperFood.java @@ -35,13 +35,10 @@ public HyperFood(int maxStackSize, int hunger, float saturation, boolean isSnack public Item getItem() { if (item == null) { Item.Settings settings = new Item.Settings().group(ItemGroup.FOOD).maxCount(maxStackSize); - if (isFireproof) - settings = settings.fireproof(); + if (isFireproof) settings = settings.fireproof(); FoodComponent.Builder builder = new FoodComponent.Builder().hunger(hunger).saturationModifier(saturation); - if (isSnack) - builder = builder.snack(); - if (effect != null) - builder = builder.statusEffect(new StatusEffectInstance(Registry.STATUS_EFFECT.get(new Identifier(effect)), effectDuration, effectAmplifier), effectChance); + if (isSnack) builder = builder.snack(); + if (effect != null) builder = builder.statusEffect(new StatusEffectInstance(Registry.STATUS_EFFECT.get(new Identifier(effect)), effectDuration, effectAmplifier), effectChance); item = new Item(settings.food(builder.build())); } return item; diff --git a/src/main/java/wothers/hr/items/HyperItem.java b/src/main/java/wothers/hr/items/HyperItem.java index cc38242..da7f60c 100644 --- a/src/main/java/wothers/hr/items/HyperItem.java +++ b/src/main/java/wothers/hr/items/HyperItem.java @@ -4,13 +4,12 @@ import net.minecraft.item.ItemGroup; public class HyperItem { - Item item; final int maxStackSize; final boolean isFireproof; + Item item; public HyperItem(int maxStackSize, boolean isFireproof) { - if (maxStackSize < 1 || maxStackSize > 64) - throw new RuntimeException("Invalid item stack size - should be at least 1 and no more than 64"); + if (maxStackSize < 1 || maxStackSize > 64) throw new RuntimeException("Invalid item stack size - should be at least 1 and no more than 64"); this.maxStackSize = maxStackSize; this.isFireproof = isFireproof; } @@ -18,8 +17,7 @@ public HyperItem(int maxStackSize, boolean isFireproof) { public Item getItem() { if (item == null) { Item.Settings settings = new Item.Settings().group(ItemGroup.MISC).maxCount(maxStackSize); - if (isFireproof) - settings = settings.fireproof(); + if (isFireproof) settings = settings.fireproof(); item = new Item(settings); } return item; diff --git a/src/main/java/wothers/hr/items/HyperTool.java b/src/main/java/wothers/hr/items/HyperTool.java index 7ee133e..20a7e67 100644 --- a/src/main/java/wothers/hr/items/HyperTool.java +++ b/src/main/java/wothers/hr/items/HyperTool.java @@ -1,13 +1,6 @@ package wothers.hr.items; -import net.minecraft.item.AxeItem; -import net.minecraft.item.HoeItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.PickaxeItem; -import net.minecraft.item.ShovelItem; -import net.minecraft.item.SwordItem; -import net.minecraft.item.ToolMaterial; +import net.minecraft.item.*; import net.minecraft.recipe.Ingredient; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; @@ -62,8 +55,7 @@ public Ingredient getRepairIngredient() { public Item getItem() { if (item == null) { Item.Settings settings = new Item.Settings().group(ItemGroup.TOOLS); - if (isFireproof) - settings = settings.fireproof(); + if (isFireproof) settings = settings.fireproof(); switch (toolType) { case "pickaxe": item = new CustomPickaxeItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); diff --git a/src/main/java/wothers/ift/ItemsFromText.java b/src/main/java/wothers/ift/ItemsFromText.java index 6482ac6..2648bbe 100644 --- a/src/main/java/wothers/ift/ItemsFromText.java +++ b/src/main/java/wothers/ift/ItemsFromText.java @@ -1,17 +1,17 @@ package wothers.ift; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.Properties; +import net.fabricmc.api.ModInitializer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import net.fabricmc.api.ModInitializer; import wothers.hr.HyperRegistry; import wothers.hr.items.HyperFood; import wothers.hr.items.HyperItem; import wothers.hr.items.HyperTool; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Properties; public class ItemsFromText implements ModInitializer { public static final String MOD_ID = "itemsfromtext"; @@ -21,8 +21,7 @@ public class ItemsFromText implements ModInitializer { @Override public void onInitialize() { File[] subDirectories = {}; - if (MAIN_FOLDER.exists()) - subDirectories = MAIN_FOLDER.listFiles(File::isDirectory); + if (MAIN_FOLDER.exists()) subDirectories = MAIN_FOLDER.listFiles(File::isDirectory); parseItems(MAIN_FOLDER); for (File dir : subDirectories) { @@ -34,8 +33,7 @@ private void parseItems(File dir) { String namespaceName = dir.getName(); File[] txtFiles = {}; - if (dir.exists()) - txtFiles = dir.listFiles((file, string) -> string.endsWith(".txt")); + if (dir.exists()) txtFiles = dir.listFiles((file, string) -> string.endsWith(".txt")); for (File file : txtFiles) { String itemName = file.getName().replace(".txt", ""); @@ -88,14 +86,12 @@ private void parseItem(String namespaceName, String itemName, Properties p) { } HyperRegistry.INSTANCE.register(namespaceName, itemName, item, p.getProperty("name"), isHandheld); - if (p.getProperty("cookingTime") != null) - try { - HyperRegistry.INSTANCE.addFuel(item, Short.parseShort(p.getProperty("cookingTime"))); - } catch (NumberFormatException e) { - LOGGER.warn("Error parsing cooking time for item: " + namespaceName + ":" + itemName); - } - if (p.getProperty("recipe") != null) - HyperRegistry.Recipe.INSTANCE.add(namespaceName, itemName, p.getProperty("recipe")); + if (p.getProperty("cookingTime") != null) try { + HyperRegistry.INSTANCE.addFuel(item, Short.parseShort(p.getProperty("cookingTime"))); + } catch (NumberFormatException e) { + LOGGER.warn("Error parsing cooking time for item: " + namespaceName + ":" + itemName); + } + if (p.getProperty("recipe") != null) HyperRegistry.Recipe.INSTANCE.add(namespaceName, itemName, p.getProperty("recipe")); } catch (RuntimeException e) { LOGGER.error("Failed to load item: " + namespaceName + ":" + itemName + " - " + e); } diff --git a/src/main/java/wothers/ift/mixins/FuelLoaderMixin.java b/src/main/java/wothers/ift/mixins/FuelLoaderMixin.java index c43db6e..30c88a0 100644 --- a/src/main/java/wothers/ift/mixins/FuelLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/FuelLoaderMixin.java @@ -1,12 +1,12 @@ package wothers.ift.mixins; -import java.util.Map; +import net.minecraft.block.entity.AbstractFurnaceBlockEntity; +import net.minecraft.item.Item; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; -import net.minecraft.block.entity.AbstractFurnaceBlockEntity; -import net.minecraft.item.Item; import wothers.hr.HyperRegistry; +import java.util.Map; @Mixin(AbstractFurnaceBlockEntity.class) public class FuelLoaderMixin { diff --git a/src/main/java/wothers/ift/mixins/LanguageLoaderMixin.java b/src/main/java/wothers/ift/mixins/LanguageLoaderMixin.java index 1f99161..335ee93 100644 --- a/src/main/java/wothers/ift/mixins/LanguageLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/LanguageLoaderMixin.java @@ -1,12 +1,12 @@ package wothers.ift.mixins; -import java.util.Map; import com.google.gson.JsonObject; +import net.minecraft.util.Language; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; -import net.minecraft.util.Language; import wothers.hr.HyperRegistry; +import java.util.Map; @Mixin(Language.class) public class LanguageLoaderMixin { diff --git a/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java b/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java index b3a5727..3118543 100644 --- a/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java @@ -1,20 +1,19 @@ package wothers.ift.mixins; +import net.minecraft.client.render.model.ModelLoader; +import net.minecraft.client.render.model.json.JsonUnbakedModel; +import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.json.JsonUnbakedModel; -import net.minecraft.util.Identifier; import wothers.hr.HyperRegistry; @Mixin(ModelLoader.class) public class ModelLoaderMixin { @Inject(method = "loadModelFromJson", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;"), cancellable = true) private void loadModelFromJson(Identifier id, CallbackInfoReturnable cir) { - if (!HyperRegistry.INSTANCE.getRegisteredItems().containsKey(id.toString())) - return; + if (!HyperRegistry.INSTANCE.getRegisteredItems().containsKey(id.toString())) return; String modelJson = createItemModelJsonString(id.toString(), HyperRegistry.INSTANCE.getRegisteredItems().get(id.toString())); JsonUnbakedModel model = JsonUnbakedModel.deserialize(modelJson); model.id = id.toString(); diff --git a/src/main/java/wothers/ift/mixins/RecipeLoaderMixin.java b/src/main/java/wothers/ift/mixins/RecipeLoaderMixin.java index ff2cc46..74f4722 100644 --- a/src/main/java/wothers/ift/mixins/RecipeLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/RecipeLoaderMixin.java @@ -1,16 +1,16 @@ package wothers.ift.mixins; -import java.util.Map; import com.google.gson.JsonElement; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.recipe.RecipeManager; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Identifier; import net.minecraft.util.profiler.Profiler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import wothers.hr.HyperRegistry; +import java.util.Map; @Mixin(RecipeManager.class) public class RecipeLoaderMixin { diff --git a/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java b/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java index 623e204..6938c8a 100644 --- a/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java @@ -1,16 +1,16 @@ package wothers.ift.mixins; -import java.io.FileInputStream; -import java.io.IOException; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; import net.minecraft.client.texture.SpriteAtlasTexture; import net.minecraft.resource.Resource; import net.minecraft.resource.ResourceImpl; import net.minecraft.resource.ResourceManager; import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; import wothers.hr.HyperRegistry; +import java.io.FileInputStream; +import java.io.IOException; @Mixin(SpriteAtlasTexture.class) public class TextureLoaderMixin { From b76f34ab607829669b45d51b73dc669d3a4a7254 Mon Sep 17 00:00:00 2001 From: wothers Date: Sun, 21 May 2023 00:46:46 +0100 Subject: [PATCH 03/12] Improved, renamed and moved item and registry classes --- src/main/java/wothers/hr/items/HyperFood.java | 46 -------- src/main/java/wothers/hr/items/HyperTool.java | 100 ------------------ .../ItemRegistry.java} | 36 +++---- src/main/java/wothers/ift/ItemsFromText.java | 25 +++-- .../wothers/ift/items/FoodItemWrapper.java | 31 ++++++ .../java/wothers/ift/items/ItemProvider.java | 7 ++ .../items/ItemWrapper.java} | 16 ++- .../wothers/ift/items/ToolItemWrapper.java | 78 ++++++++++++++ .../wothers/ift/mixins/FuelLoaderMixin.java | 4 +- .../ift/mixins/LanguageLoaderMixin.java | 4 +- .../wothers/ift/mixins/ModelLoaderMixin.java | 6 +- .../wothers/ift/mixins/RecipeLoaderMixin.java | 4 +- .../ift/mixins/TextureLoaderMixin.java | 10 +- 13 files changed, 167 insertions(+), 200 deletions(-) delete mode 100644 src/main/java/wothers/hr/items/HyperFood.java delete mode 100644 src/main/java/wothers/hr/items/HyperTool.java rename src/main/java/wothers/{hr/HyperRegistry.java => ift/ItemRegistry.java} (85%) create mode 100644 src/main/java/wothers/ift/items/FoodItemWrapper.java create mode 100644 src/main/java/wothers/ift/items/ItemProvider.java rename src/main/java/wothers/{hr/items/HyperItem.java => ift/items/ItemWrapper.java} (53%) create mode 100644 src/main/java/wothers/ift/items/ToolItemWrapper.java diff --git a/src/main/java/wothers/hr/items/HyperFood.java b/src/main/java/wothers/hr/items/HyperFood.java deleted file mode 100644 index 48f4c54..0000000 --- a/src/main/java/wothers/hr/items/HyperFood.java +++ /dev/null @@ -1,46 +0,0 @@ -package wothers.hr.items; - -import net.minecraft.entity.effect.StatusEffectInstance; -import net.minecraft.item.FoodComponent; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - -public class HyperFood extends HyperItem { - private final int hunger; - private final float saturation; - private final boolean isSnack; - private final String effect; - private final int effectDuration; - private final int effectAmplifier; - private final float effectChance; - - public HyperFood(int maxStackSize, int hunger, float saturation, boolean isSnack, boolean isFireproof) { - this(maxStackSize, hunger, saturation, isSnack, null, 0, 0, 0f, isFireproof); - } - - public HyperFood(int maxStackSize, int hunger, float saturation, boolean isSnack, String effect, int effectDuration, int effectAmplifier, float effectChance, boolean isFireproof) { - super(maxStackSize, isFireproof); - this.hunger = hunger; - this.saturation = saturation; - this.isSnack = isSnack; - this.effect = effect; - this.effectDuration = effectDuration; - this.effectAmplifier = effectAmplifier; - this.effectChance = effectChance; - } - - @Override - public Item getItem() { - if (item == null) { - Item.Settings settings = new Item.Settings().group(ItemGroup.FOOD).maxCount(maxStackSize); - if (isFireproof) settings = settings.fireproof(); - FoodComponent.Builder builder = new FoodComponent.Builder().hunger(hunger).saturationModifier(saturation); - if (isSnack) builder = builder.snack(); - if (effect != null) builder = builder.statusEffect(new StatusEffectInstance(Registry.STATUS_EFFECT.get(new Identifier(effect)), effectDuration, effectAmplifier), effectChance); - item = new Item(settings.food(builder.build())); - } - return item; - } -} diff --git a/src/main/java/wothers/hr/items/HyperTool.java b/src/main/java/wothers/hr/items/HyperTool.java deleted file mode 100644 index 20a7e67..0000000 --- a/src/main/java/wothers/hr/items/HyperTool.java +++ /dev/null @@ -1,100 +0,0 @@ -package wothers.hr.items; - -import net.minecraft.item.*; -import net.minecraft.recipe.Ingredient; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - -public class HyperTool extends HyperItem { - private final String toolType; - private final int attackDamage; - private final float attackSpeed; - private final ToolMaterial customToolMaterial; - - public HyperTool(String toolType, float miningSpeed, int miningLevel, float attackSpeed, int attackDamage, int durability, int enchantability, String repairItem, boolean isFireproof) { - super(1, isFireproof); - this.toolType = toolType; - this.attackDamage = attackDamage; - attackSpeed -= 4; - this.attackSpeed = attackSpeed; - - customToolMaterial = new ToolMaterial() { - @Override - public int getDurability() { - return durability; - } - - @Override - public float getMiningSpeedMultiplier() { - return miningSpeed; - } - - @Override - public float getAttackDamage() { - return attackDamage % 2 == 0 ? (attackDamage / 2) - 1 : attackDamage / 2; - } - - @Override - public int getMiningLevel() { - return miningLevel; - } - - @Override - public int getEnchantability() { - return enchantability; - } - - @Override - public Ingredient getRepairIngredient() { - return repairItem != null ? Ingredient.ofItems(Registry.ITEM.get(new Identifier(repairItem))) : Ingredient.EMPTY; - } - }; - } - - @Override - public Item getItem() { - if (item == null) { - Item.Settings settings = new Item.Settings().group(ItemGroup.TOOLS); - if (isFireproof) settings = settings.fireproof(); - switch (toolType) { - case "pickaxe": - item = new CustomPickaxeItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); - break; - case "axe": - item = new CustomAxeItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); - break; - case "shovel": - item = new ShovelItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); - break; - case "hoe": - item = new CustomHoeItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); - break; - case "sword": - settings = settings.group(ItemGroup.COMBAT); - item = new SwordItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); - break; - default: - throw new RuntimeException("Invalid tool type - only pickaxe, axe, shovel, hoe or sword are permitted"); - } - } - return item; - } - - private class CustomPickaxeItem extends PickaxeItem { - private CustomPickaxeItem(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) { - super(material, attackDamage, attackSpeed, settings); - } - } - - private class CustomAxeItem extends AxeItem { - private CustomAxeItem(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) { - super(material, attackDamage, attackSpeed, settings); - } - } - - private class CustomHoeItem extends HoeItem { - private CustomHoeItem(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) { - super(material, attackDamage, attackSpeed, settings); - } - } -} diff --git a/src/main/java/wothers/hr/HyperRegistry.java b/src/main/java/wothers/ift/ItemRegistry.java similarity index 85% rename from src/main/java/wothers/hr/HyperRegistry.java rename to src/main/java/wothers/ift/ItemRegistry.java index f52ab2f..e648f82 100644 --- a/src/main/java/wothers/hr/HyperRegistry.java +++ b/src/main/java/wothers/ift/ItemRegistry.java @@ -1,4 +1,4 @@ -package wothers.hr; +package wothers.ift; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -6,26 +6,26 @@ import net.minecraft.item.Item; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; -import wothers.hr.items.HyperItem; -import wothers.ift.ItemsFromText; +import wothers.ift.items.ItemProvider; import java.io.File; +import java.util.Collections; import java.util.HashMap; import java.util.Map; -public final class HyperRegistry { - public static final HyperRegistry INSTANCE = new HyperRegistry(); +public final class ItemRegistry { + public static final ItemRegistry INSTANCE = new ItemRegistry(); - private Map langMap; - private Map registeredItems; - private Map fuelMap; + private final Map langMap; + private final Map registeredItems; + private final Map fuelMap; - private HyperRegistry() { + private ItemRegistry() { langMap = new HashMap<>(); registeredItems = new HashMap<>(); fuelMap = new HashMap<>(); } - public void register(String namespaceName, String itemName, HyperItem item, String displayName, Boolean isHandheld) { + public void register(String namespaceName, String itemName, ItemProvider item, String displayName, Boolean isHandheld) { if (registeredItems.containsKey(namespaceName + ":item/" + itemName)) throw new RuntimeException("Duplicate item"); if (displayName == null) throw new RuntimeException("Missing item display name"); Registry.register(Registry.ITEM, new Identifier(namespaceName, itemName), item.getItem()); @@ -33,26 +33,26 @@ public void register(String namespaceName, String itemName, HyperItem item, Stri registeredItems.put(namespaceName + ":item/" + itemName, isHandheld ? "handheld" : "generated"); } - public void addFuel(HyperItem item, short cookingTime) { + public void addFuel(ItemProvider item, short cookingTime) { fuelMap.put(item.getItem(), (int) cookingTime); } public Map getLangMap() { - return new HashMap<>(langMap); + return Collections.unmodifiableMap(langMap); } public Map getRegisteredItems() { - return new HashMap<>(registeredItems); + return Collections.unmodifiableMap(registeredItems); } public Map getFuelMap() { - return new HashMap<>(fuelMap); + return Collections.unmodifiableMap(fuelMap); } public static final class Recipe { public static final Recipe INSTANCE = new Recipe(); - private Map map; + private final Map map; private Recipe() { map = new HashMap<>(); @@ -130,14 +130,14 @@ private boolean isNumeric(String input) { } public Map getMap() { - return new HashMap<>(map); + return Collections.unmodifiableMap(map); } } public static final class Texture { public static final Texture INSTANCE = new Texture(); - private Map map; + private final Map map; private Texture() { map = new HashMap<>(); @@ -148,7 +148,7 @@ public void add(String namespaceName, String itemName, File textureFile) { } public Map getMap() { - return new HashMap<>(map); + return Collections.unmodifiableMap(map); } } } diff --git a/src/main/java/wothers/ift/ItemsFromText.java b/src/main/java/wothers/ift/ItemsFromText.java index 2648bbe..0f8469c 100644 --- a/src/main/java/wothers/ift/ItemsFromText.java +++ b/src/main/java/wothers/ift/ItemsFromText.java @@ -3,10 +3,9 @@ import net.fabricmc.api.ModInitializer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import wothers.hr.HyperRegistry; -import wothers.hr.items.HyperFood; -import wothers.hr.items.HyperItem; -import wothers.hr.items.HyperTool; +import wothers.ift.items.FoodItemWrapper; +import wothers.ift.items.ItemWrapper; +import wothers.ift.items.ToolItemWrapper; import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -42,7 +41,7 @@ private void parseItems(File dir) { Properties p = new Properties(); p.load(new FileReader(file)); parseItem(namespaceName, itemName, p); - HyperRegistry.Texture.INSTANCE.add(namespaceName, itemName, new File(dir.getAbsolutePath() + File.separator + itemName + ".png")); + ItemRegistry.Texture.INSTANCE.add(namespaceName, itemName, new File(dir.getAbsolutePath() + File.separator + itemName + ".png")); } catch (IOException e) { LOGGER.error("I/O error while reading from file: " + file.getAbsolutePath()); } @@ -51,7 +50,7 @@ private void parseItems(File dir) { private void parseItem(String namespaceName, String itemName, Properties p) { try { - HyperItem item = null; + ItemWrapper item = null; boolean isFireproof = Boolean.parseBoolean(p.getProperty("isFireproof")); boolean isHandheld = Boolean.parseBoolean(p.getProperty("isHandheld")); if (p.getProperty("type") != null) { @@ -65,9 +64,9 @@ private void parseItem(String namespaceName, String itemName, Properties p) { int effectDuration = Integer.parseInt(p.getProperty("effectDuration")); int effectAmplifier = Integer.parseInt(p.getProperty("effectAmplifier")); float effectChance = Float.parseFloat(p.getProperty("effectChance")); - item = new HyperFood(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, effect, effectDuration, effectAmplifier, effectChance, isFireproof); + item = new FoodItemWrapper(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, effect, effectDuration, effectAmplifier, effectChance, isFireproof); } else { - item = new HyperFood(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, isFireproof); + item = new FoodItemWrapper(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, isFireproof); } break; case "tool": @@ -77,21 +76,21 @@ private void parseItem(String namespaceName, String itemName, Properties p) { int attackDamage = Integer.parseInt(p.getProperty("attackDamage")); int durability = Integer.parseInt(p.getProperty("durability")); int enchantability = Integer.parseInt(p.getProperty("enchantability")); - item = new HyperTool(p.getProperty("toolType"), miningSpeed, miningLevel, attackSpeed, attackDamage, durability, enchantability, p.getProperty("repairItem"), isFireproof); + item = new ToolItemWrapper(p.getProperty("toolType"), miningSpeed, miningLevel, attackSpeed, attackDamage, durability, enchantability, p.getProperty("repairItem"), isFireproof); isHandheld = true; break; } } else { - item = new HyperItem(Integer.parseInt(p.getProperty("stack")), isFireproof); + item = new ItemWrapper(Integer.parseInt(p.getProperty("stack")), isFireproof); } - HyperRegistry.INSTANCE.register(namespaceName, itemName, item, p.getProperty("name"), isHandheld); + ItemRegistry.INSTANCE.register(namespaceName, itemName, item, p.getProperty("name"), isHandheld); if (p.getProperty("cookingTime") != null) try { - HyperRegistry.INSTANCE.addFuel(item, Short.parseShort(p.getProperty("cookingTime"))); + ItemRegistry.INSTANCE.addFuel(item, Short.parseShort(p.getProperty("cookingTime"))); } catch (NumberFormatException e) { LOGGER.warn("Error parsing cooking time for item: " + namespaceName + ":" + itemName); } - if (p.getProperty("recipe") != null) HyperRegistry.Recipe.INSTANCE.add(namespaceName, itemName, p.getProperty("recipe")); + if (p.getProperty("recipe") != null) ItemRegistry.Recipe.INSTANCE.add(namespaceName, itemName, p.getProperty("recipe")); } catch (RuntimeException e) { LOGGER.error("Failed to load item: " + namespaceName + ":" + itemName + " - " + e); } diff --git a/src/main/java/wothers/ift/items/FoodItemWrapper.java b/src/main/java/wothers/ift/items/FoodItemWrapper.java new file mode 100644 index 0000000..a6debce --- /dev/null +++ b/src/main/java/wothers/ift/items/FoodItemWrapper.java @@ -0,0 +1,31 @@ +package wothers.ift.items; + +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.item.FoodComponent; +import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +public class FoodItemWrapper extends ItemWrapper { + private final Item foodItem; + + public FoodItemWrapper(int maxStackSize, int hunger, float saturation, boolean isSnack, boolean isFireproof) { + this(maxStackSize, hunger, saturation, isSnack, null, 0, 0, 0f, isFireproof); + } + + public FoodItemWrapper(int maxStackSize, int hunger, float saturation, boolean isSnack, String effect, int effectDuration, int effectAmplifier, float effectChance, boolean isFireproof) { + super(maxStackSize, isFireproof); + Item.Settings settings = new Item.Settings().group(ItemGroup.FOOD).maxCount(maxStackSize); + if (isFireproof) settings = settings.fireproof(); + FoodComponent.Builder builder = new FoodComponent.Builder().hunger(hunger).saturationModifier(saturation); + if (isSnack) builder = builder.snack(); + if (effect != null) builder = builder.statusEffect(new StatusEffectInstance(Registry.STATUS_EFFECT.get(new Identifier(effect)), effectDuration, effectAmplifier), effectChance); + foodItem = new Item(settings.food(builder.build())); + } + + @Override + public Item getItem() { + return foodItem; + } +} diff --git a/src/main/java/wothers/ift/items/ItemProvider.java b/src/main/java/wothers/ift/items/ItemProvider.java new file mode 100644 index 0000000..2989062 --- /dev/null +++ b/src/main/java/wothers/ift/items/ItemProvider.java @@ -0,0 +1,7 @@ +package wothers.ift.items; + +import net.minecraft.item.Item; + +public interface ItemProvider { + Item getItem(); +} diff --git a/src/main/java/wothers/hr/items/HyperItem.java b/src/main/java/wothers/ift/items/ItemWrapper.java similarity index 53% rename from src/main/java/wothers/hr/items/HyperItem.java rename to src/main/java/wothers/ift/items/ItemWrapper.java index da7f60c..e0347c4 100644 --- a/src/main/java/wothers/hr/items/HyperItem.java +++ b/src/main/java/wothers/ift/items/ItemWrapper.java @@ -1,25 +1,23 @@ -package wothers.hr.items; +package wothers.ift.items; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; -public class HyperItem { +public class ItemWrapper implements ItemProvider { final int maxStackSize; final boolean isFireproof; - Item item; + private final Item item; - public HyperItem(int maxStackSize, boolean isFireproof) { + public ItemWrapper(int maxStackSize, boolean isFireproof) { if (maxStackSize < 1 || maxStackSize > 64) throw new RuntimeException("Invalid item stack size - should be at least 1 and no more than 64"); this.maxStackSize = maxStackSize; this.isFireproof = isFireproof; + Item.Settings settings = new Item.Settings().group(ItemGroup.MISC).maxCount(maxStackSize); + if (isFireproof) settings = settings.fireproof(); + item = new Item(settings); } public Item getItem() { - if (item == null) { - Item.Settings settings = new Item.Settings().group(ItemGroup.MISC).maxCount(maxStackSize); - if (isFireproof) settings = settings.fireproof(); - item = new Item(settings); - } return item; } } diff --git a/src/main/java/wothers/ift/items/ToolItemWrapper.java b/src/main/java/wothers/ift/items/ToolItemWrapper.java new file mode 100644 index 0000000..ecc6446 --- /dev/null +++ b/src/main/java/wothers/ift/items/ToolItemWrapper.java @@ -0,0 +1,78 @@ +package wothers.ift.items; + +import net.minecraft.item.*; +import net.minecraft.recipe.Ingredient; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +public class ToolItemWrapper extends ItemWrapper { + private final Item toolItem; + + public ToolItemWrapper(String toolType, float miningSpeed, int miningLevel, float attackSpeed, int attackDamage, int durability, int enchantability, String repairItem, boolean isFireproof) { + super(1, isFireproof); + attackSpeed -= 4; + + ToolMaterial customToolMaterial = new ToolMaterial() { + public int getDurability() { + return durability; + } + + public float getMiningSpeedMultiplier() { + return miningSpeed; + } + + public float getAttackDamage() { + return attackDamage % 2 == 0 ? (attackDamage / 2) - 1 : attackDamage / 2; + } + + public int getMiningLevel() { + return miningLevel; + } + + public int getEnchantability() { + return enchantability; + } + + public Ingredient getRepairIngredient() { + return repairItem != null ? Ingredient.ofItems(Registry.ITEM.get(new Identifier(repairItem))) : Ingredient.EMPTY; + } + }; + + Item.Settings settings = new Item.Settings().group(ItemGroup.TOOLS); + if (isFireproof) settings = settings.fireproof(); + switch (toolType) { + case "pickaxe" -> toolItem = new CustomPickaxeItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); + case "axe" -> toolItem = new CustomAxeItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); + case "shovel" -> toolItem = new ShovelItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); + case "hoe" -> toolItem = new CustomHoeItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); + case "sword" -> { + settings = settings.group(ItemGroup.COMBAT); + toolItem = new SwordItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); + } + default -> throw new RuntimeException("Invalid tool type - only pickaxe, axe, shovel, hoe or sword are permitted"); + } + } + + @Override + public Item getItem() { + return toolItem; + } + + private static class CustomPickaxeItem extends PickaxeItem { + private CustomPickaxeItem(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) { + super(material, attackDamage, attackSpeed, settings); + } + } + + private static class CustomAxeItem extends AxeItem { + private CustomAxeItem(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) { + super(material, attackDamage, attackSpeed, settings); + } + } + + private static class CustomHoeItem extends HoeItem { + private CustomHoeItem(ToolMaterial material, int attackDamage, float attackSpeed, Settings settings) { + super(material, attackDamage, attackSpeed, settings); + } + } +} diff --git a/src/main/java/wothers/ift/mixins/FuelLoaderMixin.java b/src/main/java/wothers/ift/mixins/FuelLoaderMixin.java index 30c88a0..cd78eed 100644 --- a/src/main/java/wothers/ift/mixins/FuelLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/FuelLoaderMixin.java @@ -5,14 +5,14 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; -import wothers.hr.HyperRegistry; +import wothers.ift.ItemRegistry; import java.util.Map; @Mixin(AbstractFurnaceBlockEntity.class) public class FuelLoaderMixin { @ModifyVariable(method = "createFuelTimeMap", at = @At(value = "TAIL"), ordinal = 0) private static Map appendMap(Map map) { - map.putAll(HyperRegistry.INSTANCE.getFuelMap()); + map.putAll(ItemRegistry.INSTANCE.getFuelMap()); return map; } } diff --git a/src/main/java/wothers/ift/mixins/LanguageLoaderMixin.java b/src/main/java/wothers/ift/mixins/LanguageLoaderMixin.java index 335ee93..9d30538 100644 --- a/src/main/java/wothers/ift/mixins/LanguageLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/LanguageLoaderMixin.java @@ -5,14 +5,14 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; -import wothers.hr.HyperRegistry; +import wothers.ift.ItemRegistry; import java.util.Map; @Mixin(Language.class) public class LanguageLoaderMixin { @ModifyVariable(method = "load", at = @At(value = "INVOKE_ASSIGN"), ordinal = 0) private static JsonObject appendJson(JsonObject jsonObject) { - for (Map.Entry entry : HyperRegistry.INSTANCE.getLangMap().entrySet()) { + for (Map.Entry entry : ItemRegistry.INSTANCE.getLangMap().entrySet()) { jsonObject.addProperty(entry.getKey(), entry.getValue()); } return jsonObject; diff --git a/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java b/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java index 3118543..ae9bd7b 100644 --- a/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java @@ -7,14 +7,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import wothers.hr.HyperRegistry; +import wothers.ift.ItemRegistry; @Mixin(ModelLoader.class) public class ModelLoaderMixin { @Inject(method = "loadModelFromJson", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;"), cancellable = true) private void loadModelFromJson(Identifier id, CallbackInfoReturnable cir) { - if (!HyperRegistry.INSTANCE.getRegisteredItems().containsKey(id.toString())) return; - String modelJson = createItemModelJsonString(id.toString(), HyperRegistry.INSTANCE.getRegisteredItems().get(id.toString())); + if (!ItemRegistry.INSTANCE.getRegisteredItems().containsKey(id.toString())) return; + String modelJson = createItemModelJsonString(id.toString(), ItemRegistry.INSTANCE.getRegisteredItems().get(id.toString())); JsonUnbakedModel model = JsonUnbakedModel.deserialize(modelJson); model.id = id.toString(); cir.setReturnValue(model); diff --git a/src/main/java/wothers/ift/mixins/RecipeLoaderMixin.java b/src/main/java/wothers/ift/mixins/RecipeLoaderMixin.java index 74f4722..deffc80 100644 --- a/src/main/java/wothers/ift/mixins/RecipeLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/RecipeLoaderMixin.java @@ -9,13 +9,13 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import wothers.hr.HyperRegistry; +import wothers.ift.ItemRegistry; import java.util.Map; @Mixin(RecipeManager.class) public class RecipeLoaderMixin { @Inject(method = "apply", at = @At(value = "HEAD")) private void appendMap(Map map, ResourceManager resourceManager, Profiler profiler, CallbackInfo info) { - map.putAll(HyperRegistry.Recipe.INSTANCE.getMap()); + map.putAll(ItemRegistry.Recipe.INSTANCE.getMap()); } } diff --git a/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java b/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java index 6938c8a..dc240c4 100644 --- a/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java @@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import wothers.hr.HyperRegistry; +import wothers.ift.ItemRegistry; import java.io.FileInputStream; import java.io.IOException; @@ -16,8 +16,8 @@ public class TextureLoaderMixin { @Redirect(method = "method_18160", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;")) private Resource loadExternalResource(ResourceManager resourceManager, Identifier id) throws IOException { - if (HyperRegistry.Texture.INSTANCE.getMap().containsKey(id.toString())) { - FileInputStream fileInputStream = new FileInputStream(HyperRegistry.Texture.INSTANCE.getMap().get(id.toString())); + if (ItemRegistry.Texture.INSTANCE.getMap().containsKey(id.toString())) { + FileInputStream fileInputStream = new FileInputStream(ItemRegistry.Texture.INSTANCE.getMap().get(id.toString())); return new ResourceImpl(null, id, fileInputStream, null); } return resourceManager.getResource(id); @@ -25,8 +25,8 @@ private Resource loadExternalResource(ResourceManager resourceManager, Identifie @Redirect(method = "loadSprite", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;")) private Resource loadExternalResource2(ResourceManager resourceManager, Identifier id) throws IOException { - if (HyperRegistry.Texture.INSTANCE.getMap().containsKey(id.toString())) { - FileInputStream fileInputStream = new FileInputStream(HyperRegistry.Texture.INSTANCE.getMap().get(id.toString())); + if (ItemRegistry.Texture.INSTANCE.getMap().containsKey(id.toString())) { + FileInputStream fileInputStream = new FileInputStream(ItemRegistry.Texture.INSTANCE.getMap().get(id.toString())); return new ResourceImpl(null, id, fileInputStream, null); } return resourceManager.getResource(id); From 739f40d7a3ae3bd32ced13f8caffd65700ed0b9a Mon Sep 17 00:00:00 2001 From: wothers Date: Mon, 22 May 2023 22:45:00 +0100 Subject: [PATCH 04/12] Separated item parsing and item registering code --- src/main/java/wothers/ift/ItemsFromText.java | 94 ++++++++++---------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/src/main/java/wothers/ift/ItemsFromText.java b/src/main/java/wothers/ift/ItemsFromText.java index 0f8469c..b1aa63b 100644 --- a/src/main/java/wothers/ift/ItemsFromText.java +++ b/src/main/java/wothers/ift/ItemsFromText.java @@ -4,6 +4,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import wothers.ift.items.FoodItemWrapper; +import wothers.ift.items.ItemProvider; import wothers.ift.items.ItemWrapper; import wothers.ift.items.ToolItemWrapper; import java.io.File; @@ -22,13 +23,13 @@ public void onInitialize() { File[] subDirectories = {}; if (MAIN_FOLDER.exists()) subDirectories = MAIN_FOLDER.listFiles(File::isDirectory); - parseItems(MAIN_FOLDER); + loadItems(MAIN_FOLDER); for (File dir : subDirectories) { - parseItems(dir); + loadItems(dir); } } - private void parseItems(File dir) { + private void loadItems(File dir) { String namespaceName = dir.getName(); File[] txtFiles = {}; @@ -40,59 +41,56 @@ private void parseItems(File dir) { try { Properties p = new Properties(); p.load(new FileReader(file)); - parseItem(namespaceName, itemName, p); - ItemRegistry.Texture.INSTANCE.add(namespaceName, itemName, new File(dir.getAbsolutePath() + File.separator + itemName + ".png")); + registerItem(parseItem(p), namespaceName, itemName, p, new File(dir.getAbsolutePath() + File.separator + itemName + ".png")); } catch (IOException e) { LOGGER.error("I/O error while reading from file: " + file.getAbsolutePath()); + } catch (RuntimeException e) { + LOGGER.error("Failed to load item: " + namespaceName + ":" + itemName + " - " + e); } } } - private void parseItem(String namespaceName, String itemName, Properties p) { - try { - ItemWrapper item = null; - boolean isFireproof = Boolean.parseBoolean(p.getProperty("isFireproof")); - boolean isHandheld = Boolean.parseBoolean(p.getProperty("isHandheld")); - if (p.getProperty("type") != null) { - switch (p.getProperty("type")) { - case "food": - int hunger = Integer.parseInt(p.getProperty("hunger")); - float saturation = Float.parseFloat(p.getProperty("saturation")); - boolean isSnack = Boolean.parseBoolean(p.getProperty("isSnack")); - String effect = p.getProperty("effect"); - if (effect != null) { - int effectDuration = Integer.parseInt(p.getProperty("effectDuration")); - int effectAmplifier = Integer.parseInt(p.getProperty("effectAmplifier")); - float effectChance = Float.parseFloat(p.getProperty("effectChance")); - item = new FoodItemWrapper(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, effect, effectDuration, effectAmplifier, effectChance, isFireproof); - } else { - item = new FoodItemWrapper(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, isFireproof); - } - break; - case "tool": - float miningSpeed = Float.parseFloat(p.getProperty("miningSpeed")); - int miningLevel = Integer.parseInt(p.getProperty("miningLevel")); - float attackSpeed = Float.parseFloat(p.getProperty("attackSpeed")); - int attackDamage = Integer.parseInt(p.getProperty("attackDamage")); - int durability = Integer.parseInt(p.getProperty("durability")); - int enchantability = Integer.parseInt(p.getProperty("enchantability")); - item = new ToolItemWrapper(p.getProperty("toolType"), miningSpeed, miningLevel, attackSpeed, attackDamage, durability, enchantability, p.getProperty("repairItem"), isFireproof); - isHandheld = true; - break; + private ItemProvider parseItem(Properties p) { + boolean isFireproof = Boolean.parseBoolean(p.getProperty("isFireproof")); + if (p.getProperty("type") != null) switch (p.getProperty("type")) { + case "food": + int hunger = Integer.parseInt(p.getProperty("hunger")); + float saturation = Float.parseFloat(p.getProperty("saturation")); + boolean isSnack = Boolean.parseBoolean(p.getProperty("isSnack")); + String effect = p.getProperty("effect"); + if (effect != null) { + int effectDuration = Integer.parseInt(p.getProperty("effectDuration")); + int effectAmplifier = Integer.parseInt(p.getProperty("effectAmplifier")); + float effectChance = Float.parseFloat(p.getProperty("effectChance")); + return new FoodItemWrapper(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, effect, effectDuration, effectAmplifier, effectChance, isFireproof); + } else { + return new FoodItemWrapper(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, isFireproof); } - } else { - item = new ItemWrapper(Integer.parseInt(p.getProperty("stack")), isFireproof); - } + case "tool": + float miningSpeed = Float.parseFloat(p.getProperty("miningSpeed")); + int miningLevel = Integer.parseInt(p.getProperty("miningLevel")); + float attackSpeed = Float.parseFloat(p.getProperty("attackSpeed")); + int attackDamage = Integer.parseInt(p.getProperty("attackDamage")); + int durability = Integer.parseInt(p.getProperty("durability")); + int enchantability = Integer.parseInt(p.getProperty("enchantability")); + return new ToolItemWrapper(p.getProperty("toolType"), miningSpeed, miningLevel, attackSpeed, attackDamage, durability, enchantability, p.getProperty("repairItem"), isFireproof); + } + return new ItemWrapper(Integer.parseInt(p.getProperty("stack")), isFireproof); + } - ItemRegistry.INSTANCE.register(namespaceName, itemName, item, p.getProperty("name"), isHandheld); - if (p.getProperty("cookingTime") != null) try { - ItemRegistry.INSTANCE.addFuel(item, Short.parseShort(p.getProperty("cookingTime"))); - } catch (NumberFormatException e) { - LOGGER.warn("Error parsing cooking time for item: " + namespaceName + ":" + itemName); - } - if (p.getProperty("recipe") != null) ItemRegistry.Recipe.INSTANCE.add(namespaceName, itemName, p.getProperty("recipe")); - } catch (RuntimeException e) { - LOGGER.error("Failed to load item: " + namespaceName + ":" + itemName + " - " + e); + private void registerItem(ItemProvider item, String namespaceName, String itemName, Properties p, File textureFile) { + boolean isHandheld = "tool".equals(p.getProperty("type")) || Boolean.parseBoolean(p.getProperty("isHandheld")); + + ItemRegistry.INSTANCE.register(namespaceName, itemName, item, p.getProperty("name"), isHandheld); + + if (p.getProperty("cookingTime") != null) try { + ItemRegistry.INSTANCE.addFuel(item, Short.parseShort(p.getProperty("cookingTime"))); + } catch (NumberFormatException e) { + LOGGER.warn("Error parsing cooking time for item: " + namespaceName + ":" + itemName); } + + if (p.getProperty("recipe") != null) ItemRegistry.Recipe.INSTANCE.add(namespaceName, itemName, p.getProperty("recipe")); + + ItemRegistry.Texture.INSTANCE.add(namespaceName, itemName, textureFile); } } From d18b28c6f3293c60d2e7fced290c9f961e4268e3 Mon Sep 17 00:00:00 2001 From: wothers Date: Sun, 4 Jun 2023 20:21:10 +0100 Subject: [PATCH 05/12] Created custom properties classes for handling and reporting misconfigured items --- .../java/wothers/ift/ItemLoadException.java | 16 ++++ src/main/java/wothers/ift/ItemRegistry.java | 22 ++---- src/main/java/wothers/ift/ItemsFromText.java | 75 +++++++------------ src/main/java/wothers/ift/NumberUtils.java | 22 ++++++ .../wothers/ift/items/FoodItemProperties.java | 61 +++++++++++++++ .../wothers/ift/items/ItemProperties.java | 72 ++++++++++++++++++ .../ift/items/ItemPropertiesFactory.java | 21 ++++++ .../java/wothers/ift/items/ItemWrapper.java | 12 +-- .../wothers/ift/items/ToolItemProperties.java | 73 ++++++++++++++++++ .../wothers/ift/items/ToolItemWrapper.java | 2 +- 10 files changed, 306 insertions(+), 70 deletions(-) create mode 100644 src/main/java/wothers/ift/ItemLoadException.java create mode 100644 src/main/java/wothers/ift/NumberUtils.java create mode 100644 src/main/java/wothers/ift/items/FoodItemProperties.java create mode 100644 src/main/java/wothers/ift/items/ItemProperties.java create mode 100644 src/main/java/wothers/ift/items/ItemPropertiesFactory.java create mode 100644 src/main/java/wothers/ift/items/ToolItemProperties.java diff --git a/src/main/java/wothers/ift/ItemLoadException.java b/src/main/java/wothers/ift/ItemLoadException.java new file mode 100644 index 0000000..e17b0d9 --- /dev/null +++ b/src/main/java/wothers/ift/ItemLoadException.java @@ -0,0 +1,16 @@ +package wothers.ift; + +public class ItemLoadException extends RuntimeException { + public ItemLoadException(String namespaceName, String itemName) { + super(getErrorMessage(namespaceName, itemName, null)); + } + + public ItemLoadException(String namespaceName, String itemName, String reason) { + super(getErrorMessage(namespaceName, itemName, reason)); + } + + public static String getErrorMessage(String namespaceName, String itemName, String reason) { + if (reason == null) return String.format("Failed to load item: %s:%s", namespaceName, itemName); + return String.format("Failed to load item: %s:%s - %s", namespaceName, itemName, reason); + } +} diff --git a/src/main/java/wothers/ift/ItemRegistry.java b/src/main/java/wothers/ift/ItemRegistry.java index e648f82..16ca73b 100644 --- a/src/main/java/wothers/ift/ItemRegistry.java +++ b/src/main/java/wothers/ift/ItemRegistry.java @@ -26,15 +26,14 @@ private ItemRegistry() { } public void register(String namespaceName, String itemName, ItemProvider item, String displayName, Boolean isHandheld) { - if (registeredItems.containsKey(namespaceName + ":item/" + itemName)) throw new RuntimeException("Duplicate item"); - if (displayName == null) throw new RuntimeException("Missing item display name"); + if (registeredItems.containsKey(namespaceName + ":item/" + itemName)) throw new ItemLoadException(namespaceName, itemName, "Duplicate item"); Registry.register(Registry.ITEM, new Identifier(namespaceName, itemName), item.getItem()); - langMap.put("item." + namespaceName + "." + itemName, displayName); + if (displayName != null) langMap.put("item." + namespaceName + "." + itemName, displayName); registeredItems.put(namespaceName + ":item/" + itemName, isHandheld ? "handheld" : "generated"); } - public void addFuel(ItemProvider item, short cookingTime) { - fuelMap.put(item.getItem(), (int) cookingTime); + public void addFuel(ItemProvider item, int cookingTime) { + fuelMap.put(item.getItem(), cookingTime); } public Map getLangMap() { @@ -62,7 +61,7 @@ public void add(String namespaceName, String itemName, String recipe) { try { if (recipe.startsWith("shaped,")) resolveShapedRecipe(namespaceName, itemName, recipe.replace("shaped,", "")); else if (recipe.startsWith("shapeless,")) resolveShapelessRecipe(namespaceName, itemName, recipe.replace("shapeless,", "")); - else throw new RuntimeException(); + else throw new IllegalArgumentException(); } catch (Exception e) { ItemsFromText.LOGGER.warn("Failed to resolve recipe for: " + namespaceName + ":" + itemName); } @@ -78,7 +77,7 @@ private void resolveShapedRecipe(String namespaceName, String itemName, String r resultObject.addProperty("item", namespaceName + ":" + itemName); for (int i = 0; i < subStrings.length; i++) { - if (isNumeric(subStrings[i])) { + if (NumberUtils.isNumeric(subStrings[i])) { resultObject.addProperty("count", Integer.parseInt(subStrings[i])); for (int j = i + 1; j < subStrings.length; j++) { JsonObject keyObject = new JsonObject(); @@ -120,15 +119,6 @@ private void resolveShapelessRecipe(String namespaceName, String itemName, Strin map.put(new Identifier(namespaceName, itemName), mainObject); } - private boolean isNumeric(String input) { - try { - Integer.parseInt(input); - } catch (NumberFormatException e) { - return false; - } - return true; - } - public Map getMap() { return Collections.unmodifiableMap(map); } diff --git a/src/main/java/wothers/ift/ItemsFromText.java b/src/main/java/wothers/ift/ItemsFromText.java index b1aa63b..edfee35 100644 --- a/src/main/java/wothers/ift/ItemsFromText.java +++ b/src/main/java/wothers/ift/ItemsFromText.java @@ -3,27 +3,23 @@ import net.fabricmc.api.ModInitializer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import wothers.ift.items.FoodItemWrapper; -import wothers.ift.items.ItemProvider; -import wothers.ift.items.ItemWrapper; -import wothers.ift.items.ToolItemWrapper; +import wothers.ift.items.*; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.nio.file.Paths; import java.util.Properties; public class ItemsFromText implements ModInitializer { public static final String MOD_ID = "itemsfromtext"; - public static final File MAIN_FOLDER = Paths.get(MOD_ID).toFile(); + public static final File MAIN_DIR = new File(MOD_ID); public static final Logger LOGGER = LogManager.getLogger(); @Override public void onInitialize() { File[] subDirectories = {}; - if (MAIN_FOLDER.exists()) subDirectories = MAIN_FOLDER.listFiles(File::isDirectory); + if (MAIN_DIR.exists()) subDirectories = MAIN_DIR.listFiles(File::isDirectory); - loadItems(MAIN_FOLDER); + loadItems(MAIN_DIR); for (File dir : subDirectories) { loadItems(dir); } @@ -39,57 +35,40 @@ private void loadItems(File dir) { String itemName = file.getName().replace(".txt", ""); try { - Properties p = new Properties(); - p.load(new FileReader(file)); - registerItem(parseItem(p), namespaceName, itemName, p, new File(dir.getAbsolutePath() + File.separator + itemName + ".png")); + ItemProperties ip = ItemPropertiesFactory.create(newProperties(file), namespaceName, itemName, LOGGER); + ItemProvider item = parseItem(ip); + registerItem(item, ip, namespaceName, itemName, new File(dir.getAbsolutePath() + File.separator + itemName + ".png")); } catch (IOException e) { LOGGER.error("I/O error while reading from file: " + file.getAbsolutePath()); - } catch (RuntimeException e) { - LOGGER.error("Failed to load item: " + namespaceName + ":" + itemName + " - " + e); + } catch (ItemLoadException e) { + LOGGER.error(e.getMessage()); + } catch (IllegalArgumentException e) { + LOGGER.error(ItemLoadException.getErrorMessage(namespaceName, itemName, e.getMessage())); } } } - private ItemProvider parseItem(Properties p) { - boolean isFireproof = Boolean.parseBoolean(p.getProperty("isFireproof")); - if (p.getProperty("type") != null) switch (p.getProperty("type")) { - case "food": - int hunger = Integer.parseInt(p.getProperty("hunger")); - float saturation = Float.parseFloat(p.getProperty("saturation")); - boolean isSnack = Boolean.parseBoolean(p.getProperty("isSnack")); - String effect = p.getProperty("effect"); - if (effect != null) { - int effectDuration = Integer.parseInt(p.getProperty("effectDuration")); - int effectAmplifier = Integer.parseInt(p.getProperty("effectAmplifier")); - float effectChance = Float.parseFloat(p.getProperty("effectChance")); - return new FoodItemWrapper(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, effect, effectDuration, effectAmplifier, effectChance, isFireproof); - } else { - return new FoodItemWrapper(Integer.parseInt(p.getProperty("stack")), hunger, saturation, isSnack, isFireproof); - } - case "tool": - float miningSpeed = Float.parseFloat(p.getProperty("miningSpeed")); - int miningLevel = Integer.parseInt(p.getProperty("miningLevel")); - float attackSpeed = Float.parseFloat(p.getProperty("attackSpeed")); - int attackDamage = Integer.parseInt(p.getProperty("attackDamage")); - int durability = Integer.parseInt(p.getProperty("durability")); - int enchantability = Integer.parseInt(p.getProperty("enchantability")); - return new ToolItemWrapper(p.getProperty("toolType"), miningSpeed, miningLevel, attackSpeed, attackDamage, durability, enchantability, p.getProperty("repairItem"), isFireproof); - } - return new ItemWrapper(Integer.parseInt(p.getProperty("stack")), isFireproof); + private Properties newProperties(File file) throws IOException { + Properties properties = new Properties(); + properties.load(new FileReader(file)); + return properties; } - private void registerItem(ItemProvider item, String namespaceName, String itemName, Properties p, File textureFile) { - boolean isHandheld = "tool".equals(p.getProperty("type")) || Boolean.parseBoolean(p.getProperty("isHandheld")); + private ItemProvider parseItem(ItemProperties ip) { + if (ip instanceof FoodItemProperties fip) { + if (fip.effect() != null) return new FoodItemWrapper(fip.maxStackSize(), fip.hunger(), fip.saturation(), fip.isSnack(), fip.effect(), fip.effectDuration(), fip.effectAmplifier(), fip.effectChance(), fip.isFireproof()); + return new FoodItemWrapper(fip.maxStackSize(), fip.hunger(), fip.saturation(), fip.isSnack(), fip.isFireproof()); + } + if (ip instanceof ToolItemProperties tip) return new ToolItemWrapper(tip.toolType(), tip.miningSpeed(), tip.miningLevel(), tip.attackSpeed(), tip.attackDamage(), tip.durability(), tip.enchantability(), tip.repairItem(), tip.isFireproof()); + return new ItemWrapper(ip.maxStackSize(), ip.isFireproof()); + } - ItemRegistry.INSTANCE.register(namespaceName, itemName, item, p.getProperty("name"), isHandheld); + private void registerItem(ItemProvider item, ItemProperties ip, String namespaceName, String itemName, File textureFile) { + ItemRegistry.INSTANCE.register(namespaceName, itemName, item, ip.displayName(), ip.isHandheld()); - if (p.getProperty("cookingTime") != null) try { - ItemRegistry.INSTANCE.addFuel(item, Short.parseShort(p.getProperty("cookingTime"))); - } catch (NumberFormatException e) { - LOGGER.warn("Error parsing cooking time for item: " + namespaceName + ":" + itemName); - } + if (ip.cookingTime() != null) ItemRegistry.INSTANCE.addFuel(item, ip.cookingTime()); - if (p.getProperty("recipe") != null) ItemRegistry.Recipe.INSTANCE.add(namespaceName, itemName, p.getProperty("recipe")); + if (ip.recipe() != null) ItemRegistry.Recipe.INSTANCE.add(namespaceName, itemName, ip.recipe()); ItemRegistry.Texture.INSTANCE.add(namespaceName, itemName, textureFile); } diff --git a/src/main/java/wothers/ift/NumberUtils.java b/src/main/java/wothers/ift/NumberUtils.java new file mode 100644 index 0000000..4a166ac --- /dev/null +++ b/src/main/java/wothers/ift/NumberUtils.java @@ -0,0 +1,22 @@ +package wothers.ift; + +public final class NumberUtils { + private NumberUtils() {} + + public static boolean isNumeric(String s) { + try { + Double.parseDouble(s); + } catch (NullPointerException | NumberFormatException e) { + return false; + } + return true; + } + + public static Integer tryParse(String s, Integer defaultValue) { + try { + return Integer.valueOf(s); + } catch (NumberFormatException e) { + return defaultValue; + } + } +} diff --git a/src/main/java/wothers/ift/items/FoodItemProperties.java b/src/main/java/wothers/ift/items/FoodItemProperties.java new file mode 100644 index 0000000..9da8a1a --- /dev/null +++ b/src/main/java/wothers/ift/items/FoodItemProperties.java @@ -0,0 +1,61 @@ +package wothers.ift.items; + +import org.apache.logging.log4j.Logger; +import wothers.ift.ItemLoadException; +import wothers.ift.NumberUtils; +import java.util.List; +import java.util.Properties; + +public class FoodItemProperties extends ItemProperties { + public FoodItemProperties(Properties p, String namespaceName, String itemName, Logger logger) { + super(p, namespaceName, itemName, logger); + } + + @Override + public boolean validateRequired() { + boolean error = super.validateRequired(); + + List keys = List.of("hunger", "saturation"); + for (String key : keys) { + if (checkProperty(key, NumberUtils::isNumeric)) error = true; + } + + if (effect() != null) { + List effectKeys = List.of("effectDuration", "effectAmplifier", "effectChance"); + for (String effectKey : effectKeys) { + if (checkProperty(effectKey, NumberUtils::isNumeric)) error = true; + } + } + + if (error) throw new ItemLoadException(namespaceName, itemName); + return false; + } + + public int hunger() { + return Integer.parseInt(p.getProperty("hunger")); + } + + public float saturation() { + return Float.parseFloat(p.getProperty("saturation")); + } + + public boolean isSnack() { + return Boolean.parseBoolean(p.getProperty("isSnack")); + } + + public String effect() { + return p.getProperty("effect"); + } + + public int effectDuration() { + return Integer.parseInt(p.getProperty("effectDuration")); + } + + public int effectAmplifier() { + return Integer.parseInt(p.getProperty("effectAmplifier")); + } + + public float effectChance() { + return Float.parseFloat(p.getProperty("effectChance")); + } +} diff --git a/src/main/java/wothers/ift/items/ItemProperties.java b/src/main/java/wothers/ift/items/ItemProperties.java new file mode 100644 index 0000000..f022728 --- /dev/null +++ b/src/main/java/wothers/ift/items/ItemProperties.java @@ -0,0 +1,72 @@ +package wothers.ift.items; + +import org.apache.logging.log4j.Logger; +import wothers.ift.NumberUtils; +import java.util.Properties; +import java.util.function.Function; + +public class ItemProperties { + final Properties p; + final String namespaceName, itemName; + final Logger logger; + + public ItemProperties(Properties p, String namespaceName, String itemName, Logger logger) { + this.p = p; + this.namespaceName = namespaceName; + this.itemName = itemName; + this.logger = logger; + + validateOptional(); + validateRequired(); + } + + public void validateOptional() { + if (displayName() == null) logger.warn(String.format("Missing display name - %s:%s", namespaceName, itemName)); + + if (!"tool".equals(p.getProperty("type"))) { + String stack = p.getProperty("stack"); + if (stack != null && !NumberUtils.isNumeric(stack)) logger.warn(String.format("Non-numeric stack specified - %s:%s", namespaceName, itemName)); + } + + String cookingTime = p.getProperty("cookingTime"); + if (cookingTime != null && !NumberUtils.isNumeric(cookingTime)) logger.warn(String.format("Non-numeric cooking time specified - %s:%s", namespaceName, itemName)); + } + + public boolean validateRequired() { + if (maxStackSize() < 1 || maxStackSize() > 64) { + logger.error(String.format("Stack not in range 1-64 - %s:%s", namespaceName, itemName)); + return true; + } + return false; + } + + boolean checkProperty(String key, Function isValid) { + boolean error = !isValid.apply(p.getProperty(key)); + if (error) logger.error(String.format("Missing or invalid %s value - %s:%s", key, namespaceName, itemName)); + return error; + } + + public String displayName() { + return p.getProperty("name"); + } + + public int maxStackSize() { + return NumberUtils.tryParse(p.getProperty("stack"), 64); + } + + public boolean isHandheld() { + return Boolean.parseBoolean(p.getProperty("isHandheld")); + } + + public boolean isFireproof() { + return Boolean.parseBoolean(p.getProperty("isFireproof")); + } + + public Integer cookingTime() { + return NumberUtils.tryParse(p.getProperty("cookingTime"), null); + } + + public String recipe() { + return p.getProperty("recipe"); + } +} diff --git a/src/main/java/wothers/ift/items/ItemPropertiesFactory.java b/src/main/java/wothers/ift/items/ItemPropertiesFactory.java new file mode 100644 index 0000000..093a132 --- /dev/null +++ b/src/main/java/wothers/ift/items/ItemPropertiesFactory.java @@ -0,0 +1,21 @@ +package wothers.ift.items; + +import org.apache.logging.log4j.Logger; +import java.util.Properties; + +public final class ItemPropertiesFactory { + private ItemPropertiesFactory() {} + + public static ItemProperties create(Properties p, String namespaceName, String itemName, Logger logger) { + String type = p.getProperty("type"); + if (type != null) switch (type) { + case "food": + return new FoodItemProperties(p, namespaceName, itemName, logger); + case "tool": + return new ToolItemProperties(p, namespaceName, itemName, logger); + default: + logger.warn(String.format("Invalid type \"%s\" - %s:%s", type, namespaceName, itemName)); + } + return new ItemProperties(p, namespaceName, itemName, logger); + } +} diff --git a/src/main/java/wothers/ift/items/ItemWrapper.java b/src/main/java/wothers/ift/items/ItemWrapper.java index e0347c4..ceed7b9 100644 --- a/src/main/java/wothers/ift/items/ItemWrapper.java +++ b/src/main/java/wothers/ift/items/ItemWrapper.java @@ -6,15 +6,17 @@ public class ItemWrapper implements ItemProvider { final int maxStackSize; final boolean isFireproof; - private final Item item; + private Item item; public ItemWrapper(int maxStackSize, boolean isFireproof) { - if (maxStackSize < 1 || maxStackSize > 64) throw new RuntimeException("Invalid item stack size - should be at least 1 and no more than 64"); this.maxStackSize = maxStackSize; this.isFireproof = isFireproof; - Item.Settings settings = new Item.Settings().group(ItemGroup.MISC).maxCount(maxStackSize); - if (isFireproof) settings = settings.fireproof(); - item = new Item(settings); + + if (this.getClass() == ItemWrapper.class) { + Item.Settings settings = new Item.Settings().group(ItemGroup.MISC).maxCount(maxStackSize); + if (isFireproof) settings = settings.fireproof(); + item = new Item(settings); + } } public Item getItem() { diff --git a/src/main/java/wothers/ift/items/ToolItemProperties.java b/src/main/java/wothers/ift/items/ToolItemProperties.java new file mode 100644 index 0000000..4eac3ac --- /dev/null +++ b/src/main/java/wothers/ift/items/ToolItemProperties.java @@ -0,0 +1,73 @@ +package wothers.ift.items; + +import org.apache.logging.log4j.Logger; +import wothers.ift.ItemLoadException; +import wothers.ift.NumberUtils; +import java.util.List; +import java.util.Properties; + +public class ToolItemProperties extends ItemProperties { + public ToolItemProperties(Properties p, String namespaceName, String itemName, Logger logger) { + super(p, namespaceName, itemName, logger); + } + + @Override + public boolean validateRequired() { + boolean error = super.validateRequired(); + + if (toolType() == null) { + logger.error(String.format("Missing tool type - %s:%s", namespaceName, itemName)); + error = true; + } + + List keys = List.of("miningSpeed", "miningLevel", "attackSpeed", "attackDamage", "durability", "enchantability"); + for (String key : keys) { + if (checkProperty(key, NumberUtils::isNumeric)) error = true; + } + + if (error) throw new ItemLoadException(namespaceName, itemName); + return false; + } + + @Override + public int maxStackSize() { + return 1; + } + + @Override + public boolean isHandheld() { + return true; + } + + public String toolType() { + return p.getProperty("toolType"); + } + + public float miningSpeed() { + return Float.parseFloat(p.getProperty("miningSpeed")); + } + + public int miningLevel() { + return Integer.parseInt(p.getProperty("miningLevel")); + } + + public float attackSpeed() { + return Float.parseFloat(p.getProperty("attackSpeed")); + } + + public int attackDamage() { + return Integer.parseInt(p.getProperty("attackDamage")); + } + + public int durability() { + return Integer.parseInt(p.getProperty("durability")); + } + + public int enchantability() { + return Integer.parseInt(p.getProperty("enchantability")); + } + + public String repairItem() { + return p.getProperty("repairItem"); + } +} diff --git a/src/main/java/wothers/ift/items/ToolItemWrapper.java b/src/main/java/wothers/ift/items/ToolItemWrapper.java index ecc6446..512ac10 100644 --- a/src/main/java/wothers/ift/items/ToolItemWrapper.java +++ b/src/main/java/wothers/ift/items/ToolItemWrapper.java @@ -49,7 +49,7 @@ public Ingredient getRepairIngredient() { settings = settings.group(ItemGroup.COMBAT); toolItem = new SwordItem(customToolMaterial, attackDamage / 2, attackSpeed, settings); } - default -> throw new RuntimeException("Invalid tool type - only pickaxe, axe, shovel, hoe or sword are permitted"); + default -> throw new IllegalArgumentException("Invalid tool type - only pickaxe, axe, shovel, hoe or sword are permitted"); } } From 7ca95cb830aff7a41cdda1e5c0f984cb75a21c77 Mon Sep 17 00:00:00 2001 From: wothers Date: Sun, 18 Jun 2023 17:29:58 +0100 Subject: [PATCH 06/12] Rewrote texture loading mixin to allow for resource pack overriding --- src/main/java/wothers/ift/ItemRegistry.java | 21 ++++--- src/main/java/wothers/ift/ItemsFromText.java | 2 +- .../ift/mixins/TextureLoaderMixin.java | 56 ++++++++++++------- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/src/main/java/wothers/ift/ItemRegistry.java b/src/main/java/wothers/ift/ItemRegistry.java index 16ca73b..e1ea908 100644 --- a/src/main/java/wothers/ift/ItemRegistry.java +++ b/src/main/java/wothers/ift/ItemRegistry.java @@ -8,42 +8,47 @@ import net.minecraft.util.registry.Registry; import wothers.ift.items.ItemProvider; import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; public final class ItemRegistry { public static final ItemRegistry INSTANCE = new ItemRegistry(); - private final Map langMap; + private final Set namespaces; private final Map registeredItems; + private final Map langMap; private final Map fuelMap; private ItemRegistry() { - langMap = new HashMap<>(); + namespaces = new HashSet<>(); registeredItems = new HashMap<>(); + langMap = new HashMap<>(); fuelMap = new HashMap<>(); } public void register(String namespaceName, String itemName, ItemProvider item, String displayName, Boolean isHandheld) { if (registeredItems.containsKey(namespaceName + ":item/" + itemName)) throw new ItemLoadException(namespaceName, itemName, "Duplicate item"); Registry.register(Registry.ITEM, new Identifier(namespaceName, itemName), item.getItem()); - if (displayName != null) langMap.put("item." + namespaceName + "." + itemName, displayName); + namespaces.add(namespaceName); registeredItems.put(namespaceName + ":item/" + itemName, isHandheld ? "handheld" : "generated"); + if (displayName != null) langMap.put("item." + namespaceName + "." + itemName, displayName); } public void addFuel(ItemProvider item, int cookingTime) { fuelMap.put(item.getItem(), cookingTime); } - public Map getLangMap() { - return Collections.unmodifiableMap(langMap); + public Set getNamespaces() { + return Collections.unmodifiableSet(namespaces); } public Map getRegisteredItems() { return Collections.unmodifiableMap(registeredItems); } + public Map getLangMap() { + return Collections.unmodifiableMap(langMap); + } + public Map getFuelMap() { return Collections.unmodifiableMap(fuelMap); } diff --git a/src/main/java/wothers/ift/ItemsFromText.java b/src/main/java/wothers/ift/ItemsFromText.java index edfee35..68c266c 100644 --- a/src/main/java/wothers/ift/ItemsFromText.java +++ b/src/main/java/wothers/ift/ItemsFromText.java @@ -37,7 +37,7 @@ private void loadItems(File dir) { try { ItemProperties ip = ItemPropertiesFactory.create(newProperties(file), namespaceName, itemName, LOGGER); ItemProvider item = parseItem(ip); - registerItem(item, ip, namespaceName, itemName, new File(dir.getAbsolutePath() + File.separator + itemName + ".png")); + registerItem(item, ip, namespaceName, itemName, new File(dir, itemName + ".png").getAbsoluteFile()); } catch (IOException e) { LOGGER.error("I/O error while reading from file: " + file.getAbsolutePath()); } catch (ItemLoadException e) { diff --git a/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java b/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java index dc240c4..2fdc5de 100644 --- a/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/TextureLoaderMixin.java @@ -1,34 +1,50 @@ package wothers.ift.mixins; -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.resource.Resource; -import net.minecraft.resource.ResourceImpl; -import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.DefaultResourcePack; +import net.minecraft.resource.ResourceType; import net.minecraft.util.Identifier; +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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import wothers.ift.ItemRegistry; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; -@Mixin(SpriteAtlasTexture.class) +@Mixin(DefaultResourcePack.class) public class TextureLoaderMixin { - @Redirect(method = "method_18160", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;")) - private Resource loadExternalResource(ResourceManager resourceManager, Identifier id) throws IOException { - if (ItemRegistry.Texture.INSTANCE.getMap().containsKey(id.toString())) { - FileInputStream fileInputStream = new FileInputStream(ItemRegistry.Texture.INSTANCE.getMap().get(id.toString())); - return new ResourceImpl(null, id, fileInputStream, null); - } - return resourceManager.getResource(id); + @Final + @Shadow + public Set namespaces; + + @Inject(method = "getNamespaces", at = @At(value = "HEAD"), cancellable = true) + private void getAppendedNamespaces(ResourceType type, CallbackInfoReturnable> cir) { + Set namespaces = new HashSet<>(this.namespaces); + namespaces.addAll(ItemRegistry.INSTANCE.getNamespaces()); + cir.setReturnValue(Collections.unmodifiableSet(namespaces)); + cir.cancel(); + } + + @Inject(method = "contains", at = @At(value = "HEAD"), cancellable = true) + private void overrideContains(ResourceType type, Identifier id, CallbackInfoReturnable cir) { + if (!ItemRegistry.Texture.INSTANCE.getMap().containsKey(id.toString())) return; + cir.setReturnValue(true); + cir.cancel(); } - @Redirect(method = "loadSprite", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;")) - private Resource loadExternalResource2(ResourceManager resourceManager, Identifier id) throws IOException { - if (ItemRegistry.Texture.INSTANCE.getMap().containsKey(id.toString())) { - FileInputStream fileInputStream = new FileInputStream(ItemRegistry.Texture.INSTANCE.getMap().get(id.toString())); - return new ResourceImpl(null, id, fileInputStream, null); - } - return resourceManager.getResource(id); + @Inject(method = "open", at = @At(value = "HEAD"), cancellable = true) + private void openExternal(ResourceType type, Identifier id, CallbackInfoReturnable cir) throws IOException { + Map textureMap = ItemRegistry.Texture.INSTANCE.getMap(); + if (!textureMap.containsKey(id.toString())) return; + cir.setReturnValue(new FileInputStream(textureMap.get(id.toString()))); + cir.cancel(); } } From dbb2aee32dda1b8f3a68c0b571fd737018ec46b9 Mon Sep 17 00:00:00 2001 From: wothers Date: Sat, 24 Jun 2023 20:00:51 +0100 Subject: [PATCH 07/12] Added mixin for internally validating identifier type property values --- .../wothers/ift/mixins/RegistryMixin.java | 56 +++++++++++++++++++ src/main/resources/mixins.json | 1 + 2 files changed, 57 insertions(+) create mode 100644 src/main/java/wothers/ift/mixins/RegistryMixin.java diff --git a/src/main/java/wothers/ift/mixins/RegistryMixin.java b/src/main/java/wothers/ift/mixins/RegistryMixin.java new file mode 100644 index 0000000..5f0bb41 --- /dev/null +++ b/src/main/java/wothers/ift/mixins/RegistryMixin.java @@ -0,0 +1,56 @@ +package wothers.ift.mixins; + +import com.mojang.datafixers.util.Pair; +import com.mojang.logging.LogUtils; +import com.mojang.serialization.Lifecycle; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.item.FoodComponent; +import net.minecraft.item.Item; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.util.registry.SimpleRegistry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +@Mixin(SimpleRegistry.class) +public abstract class RegistryMixin { + private final Map, FoodComponent> foodComponentMap = new HashMap<>(); + + @Inject(method = "add", at = @At(value = "HEAD")) + private void interceptAddItem(RegistryKey key, Object entry, Lifecycle lifecycle, CallbackInfoReturnable> cir) { + if (!this.equals(Registry.ITEM)) return; + addFoodContainingEffects(key, (Item) entry); + } + + private void addFoodContainingEffects(RegistryKey key, Item item) { + if (!item.isFood()) return; + FoodComponent foodComponent = item.getFoodComponent(); + if (foodComponent.getStatusEffects().isEmpty()) return; + foodComponentMap.put(key, foodComponent); + } + + @Inject(method = "freeze", at = @At(value = "HEAD")) + private void validateOnFreeze(CallbackInfoReturnable> cir) { + if (!this.equals(Registry.ITEM)) return; + validateFoodEffects(); + } + + private void validateFoodEffects() { + for (Map.Entry, FoodComponent> entry : foodComponentMap.entrySet()) { + Iterator> iterator = entry.getValue().getStatusEffects().iterator(); + while (iterator.hasNext()) { + Pair pair = iterator.next(); + if (pair.getFirst().getEffectType() == null) { + iterator.remove(); + LogUtils.getLogger().error("Food item {} has invalid status effect(s)", entry.getKey().getValue()); + } + } + } + } +} diff --git a/src/main/resources/mixins.json b/src/main/resources/mixins.json index f1a66f7..aa115b0 100644 --- a/src/main/resources/mixins.json +++ b/src/main/resources/mixins.json @@ -8,6 +8,7 @@ "LanguageLoaderMixin", "ModelLoaderMixin", "RecipeLoaderMixin", + "RegistryMixin", "TextureLoaderMixin" ], "injectors": { From ebfa6ab7f54b26216a407fa3689067bbb605c76d Mon Sep 17 00:00:00 2001 From: wothers Date: Thu, 29 Jun 2023 23:45:41 +0100 Subject: [PATCH 08/12] Prevented creating item instances of existing identifiers by checking for duplicates internally --- src/main/java/wothers/ift/ItemRegistry.java | 5 ++++- src/main/java/wothers/ift/ItemsFromText.java | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/wothers/ift/ItemRegistry.java b/src/main/java/wothers/ift/ItemRegistry.java index e1ea908..3a2056f 100644 --- a/src/main/java/wothers/ift/ItemRegistry.java +++ b/src/main/java/wothers/ift/ItemRegistry.java @@ -25,8 +25,11 @@ private ItemRegistry() { fuelMap = new HashMap<>(); } + public static boolean internalContains(String namespaceName, String itemName) { + return Registry.ITEM.containsId(new Identifier(namespaceName, itemName)); + } + public void register(String namespaceName, String itemName, ItemProvider item, String displayName, Boolean isHandheld) { - if (registeredItems.containsKey(namespaceName + ":item/" + itemName)) throw new ItemLoadException(namespaceName, itemName, "Duplicate item"); Registry.register(Registry.ITEM, new Identifier(namespaceName, itemName), item.getItem()); namespaces.add(namespaceName); registeredItems.put(namespaceName + ":item/" + itemName, isHandheld ? "handheld" : "generated"); diff --git a/src/main/java/wothers/ift/ItemsFromText.java b/src/main/java/wothers/ift/ItemsFromText.java index 68c266c..0c97933 100644 --- a/src/main/java/wothers/ift/ItemsFromText.java +++ b/src/main/java/wothers/ift/ItemsFromText.java @@ -35,6 +35,7 @@ private void loadItems(File dir) { String itemName = file.getName().replace(".txt", ""); try { + if (ItemRegistry.internalContains(namespaceName, itemName)) throw new ItemLoadException(namespaceName, itemName, "Duplicate item"); ItemProperties ip = ItemPropertiesFactory.create(newProperties(file), namespaceName, itemName, LOGGER); ItemProvider item = parseItem(ip); registerItem(item, ip, namespaceName, itemName, new File(dir, itemName + ".png").getAbsoluteFile()); From 1085b1db84dff5f322f5790078f908bff87252b8 Mon Sep 17 00:00:00 2001 From: wothers Date: Sun, 2 Jul 2023 21:01:00 +0100 Subject: [PATCH 09/12] Added simple validation of crafting recipe formats --- src/main/java/wothers/ift/ItemRegistry.java | 39 ++++++++----------- src/main/java/wothers/ift/NumberUtils.java | 9 +++++ .../wothers/ift/items/ItemProperties.java | 28 +++++++++++++ 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/main/java/wothers/ift/ItemRegistry.java b/src/main/java/wothers/ift/ItemRegistry.java index 3a2056f..3e3de69 100644 --- a/src/main/java/wothers/ift/ItemRegistry.java +++ b/src/main/java/wothers/ift/ItemRegistry.java @@ -66,35 +66,30 @@ private Recipe() { } public void add(String namespaceName, String itemName, String recipe) { - try { - if (recipe.startsWith("shaped,")) resolveShapedRecipe(namespaceName, itemName, recipe.replace("shaped,", "")); - else if (recipe.startsWith("shapeless,")) resolveShapelessRecipe(namespaceName, itemName, recipe.replace("shapeless,", "")); - else throw new IllegalArgumentException(); - } catch (Exception e) { - ItemsFromText.LOGGER.warn("Failed to resolve recipe for: " + namespaceName + ":" + itemName); - } + String[] strings = recipe.split(","); + strings = Arrays.copyOfRange(strings, 1, strings.length); + if (recipe.startsWith("shaped,")) addShaped(namespaceName, itemName, strings); + if (recipe.startsWith("shapeless,")) addShapeless(namespaceName, itemName, strings); } - private void resolveShapedRecipe(String namespaceName, String itemName, String recipe) { + private void addShaped(String namespaceName, String itemName, String[] strings) { JsonObject mainObject = new JsonObject(); JsonArray patternArray = new JsonArray(); JsonObject keysObject = new JsonObject(); JsonObject resultObject = new JsonObject(); - String[] subStrings = recipe.split(","); - resultObject.addProperty("item", namespaceName + ":" + itemName); - for (int i = 0; i < subStrings.length; i++) { - if (NumberUtils.isNumeric(subStrings[i])) { - resultObject.addProperty("count", Integer.parseInt(subStrings[i])); - for (int j = i + 1; j < subStrings.length; j++) { + for (int i = 0; i < strings.length; i++) { + if (NumberUtils.isInteger(strings[i])) { + resultObject.addProperty("count", Integer.parseInt(strings[i])); + for (int j = i + 1; j < strings.length; j++) { JsonObject keyObject = new JsonObject(); - keyObject.addProperty("item", subStrings[j].substring(2)); - keysObject.add(Character.toString(subStrings[j].charAt(0)), keyObject); + keyObject.addProperty("item", strings[j].substring(2)); + keysObject.add(Character.toString(strings[j].charAt(0)), keyObject); } break; } - patternArray.add(subStrings[i]); + patternArray.add(strings[i]); } mainObject.addProperty("type", "minecraft:crafting_shaped"); @@ -105,18 +100,16 @@ private void resolveShapedRecipe(String namespaceName, String itemName, String r map.put(new Identifier(namespaceName, itemName), mainObject); } - private void resolveShapelessRecipe(String namespaceName, String itemName, String recipe) { + private void addShapeless(String namespaceName, String itemName, String[] strings) { JsonObject mainObject = new JsonObject(); JsonArray ingredientArray = new JsonArray(); JsonObject resultObject = new JsonObject(); - String[] subStrings = recipe.split(","); - resultObject.addProperty("item", namespaceName + ":" + itemName); - resultObject.addProperty("count", Integer.parseInt(subStrings[0])); - for (int i = 1; i < subStrings.length; i++) { + resultObject.addProperty("count", Integer.parseInt(strings[0])); + for (int i = 1; i < strings.length; i++) { JsonObject ingredientObject = new JsonObject(); - ingredientObject.addProperty("item", subStrings[i]); + ingredientObject.addProperty("item", strings[i]); ingredientArray.add(ingredientObject); } diff --git a/src/main/java/wothers/ift/NumberUtils.java b/src/main/java/wothers/ift/NumberUtils.java index 4a166ac..c74e0cc 100644 --- a/src/main/java/wothers/ift/NumberUtils.java +++ b/src/main/java/wothers/ift/NumberUtils.java @@ -12,6 +12,15 @@ public static boolean isNumeric(String s) { return true; } + public static boolean isInteger(String s) { + try { + Integer.parseInt(s); + } catch (NumberFormatException e) { + return false; + } + return true; + } + public static Integer tryParse(String s, Integer defaultValue) { try { return Integer.valueOf(s); diff --git a/src/main/java/wothers/ift/items/ItemProperties.java b/src/main/java/wothers/ift/items/ItemProperties.java index f022728..2f72765 100644 --- a/src/main/java/wothers/ift/items/ItemProperties.java +++ b/src/main/java/wothers/ift/items/ItemProperties.java @@ -30,6 +30,11 @@ public void validateOptional() { String cookingTime = p.getProperty("cookingTime"); if (cookingTime != null && !NumberUtils.isNumeric(cookingTime)) logger.warn(String.format("Non-numeric cooking time specified - %s:%s", namespaceName, itemName)); + + if (initialRecipeCheck()) { + p.remove("recipe"); + logger.warn(String.format("Invalid recipe structure - %s:%s", namespaceName, itemName)); + } } public boolean validateRequired() { @@ -40,6 +45,29 @@ public boolean validateRequired() { return false; } + private boolean initialRecipeCheck() { + if (recipe() == null) return false; + String[] strings = recipe().split(","); + if (strings.length < 3) return true; + if (recipe().startsWith("shaped")) return initialShapedRecipeCheck(strings); + if (recipe().startsWith("shapeless")) return initialShapelessRecipeCheck(strings); + return true; + } + + private boolean initialShapedRecipeCheck(String[] strings) { + if (NumberUtils.isInteger(strings[1])) return true; + if (strings[1].length() < 1 || strings[1].length() > 3) return true; + for (int i = 2; i < 4; i++) { + if (NumberUtils.isInteger(strings[i])) return false; + if (strings[i].length() != strings[1].length()) return true; + } + return !NumberUtils.isInteger(strings[4]); + } + + private boolean initialShapelessRecipeCheck(String[] strings) { + return !NumberUtils.isInteger(strings[1]); + } + boolean checkProperty(String key, Function isValid) { boolean error = !isValid.apply(p.getProperty(key)); if (error) logger.error(String.format("Missing or invalid %s value - %s:%s", key, namespaceName, itemName)); From 225d193f526000608301f82c23123b5ba4040693 Mon Sep 17 00:00:00 2001 From: wothers Date: Fri, 17 Nov 2023 15:42:15 +0000 Subject: [PATCH 10/12] Updated gradle version --- build.gradle | 15 ++++++++------- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 10 +++++----- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 6263d0f..c1e099d 100644 --- a/build.gradle +++ b/build.gradle @@ -3,13 +3,13 @@ plugins { id 'maven-publish' } -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 - -archivesBaseName = project.archives_base_name version = project.mod_version group = project.maven_group +base { + archivesName = project.archives_base_name +} + dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" @@ -43,13 +43,14 @@ tasks.withType(JavaCompile).configureEach { java { withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } jar { from("LICENSE") { - rename { - "${it}_${project.archivesBaseName}" - } + rename { "${it}_${project.base.archivesName.get()}"} } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 84d1f85..e411586 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c787..c53aefa 100644 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,10 +32,10 @@ # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # From 7eebbdd057be715a7057634f88264275c9f583d4 Mon Sep 17 00:00:00 2001 From: Erik Steiner Date: Wed, 3 Jan 2024 00:05:34 +0100 Subject: [PATCH 11/12] Update to 1.19.2 --- build.gradle | 6 ++++-- gradle.properties | 10 +++++----- .../wothers/ift/items/ItemProperties.java | 2 +- .../wothers/ift/mixins/ModelLoaderMixin.java | 8 +++++--- .../wothers/ift/mixins/RegistryMixin.java | 19 ++++++++++++------- src/main/resources/fabric.mod.json | 6 ++++-- src/main/resources/mixins.json | 2 +- 7 files changed, 32 insertions(+), 21 deletions(-) diff --git a/build.gradle b/build.gradle index c1e099d..d4758b0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '0.11-SNAPSHOT' + id 'fabric-loom' version '1.4-SNAPSHOT' id 'maven-publish' } @@ -14,11 +14,13 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" Set apiModules = [ "fabric-api-base", - "fabric-command-api-v1", + "fabric-command-api-v2", "fabric-lifecycle-events-v1", "fabric-networking-api-v1", "fabric-registry-sync-v0" diff --git a/gradle.properties b/gradle.properties index 03c03fd..5a51458 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,14 +2,14 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties - minecraft_version=1.18.2 - yarn_mappings=1.18.2+build.1 - loader_version=0.13.3 + minecraft_version=1.19.2 + yarn_mappings=1.19.2+build.28 + loader_version=0.15.3 # Mod Properties - mod_version = 1.6.3-1.18.2 + mod_version = 2.0.0-1.19.2 maven_group = wothers.ift archives_base_name = items-from-text # Dependencies - fabric_version=0.47.8+1.18.2 + fabric_version=0.77.0+1.19.2 diff --git a/src/main/java/wothers/ift/items/ItemProperties.java b/src/main/java/wothers/ift/items/ItemProperties.java index 2f72765..fbc0c2c 100644 --- a/src/main/java/wothers/ift/items/ItemProperties.java +++ b/src/main/java/wothers/ift/items/ItemProperties.java @@ -56,7 +56,7 @@ private boolean initialRecipeCheck() { private boolean initialShapedRecipeCheck(String[] strings) { if (NumberUtils.isInteger(strings[1])) return true; - if (strings[1].length() < 1 || strings[1].length() > 3) return true; + if (strings[1].isEmpty() || strings[1].length() > 3) return true; for (int i = 2; i < 4; i++) { if (NumberUtils.isInteger(strings[i])) return false; if (strings[i].length() != strings[1].length()) return true; diff --git a/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java b/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java index ae9bd7b..1dfc335 100644 --- a/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java @@ -4,6 +4,7 @@ import net.minecraft.client.render.model.json.JsonUnbakedModel; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -11,17 +12,18 @@ @Mixin(ModelLoader.class) public class ModelLoaderMixin { - @Inject(method = "loadModelFromJson", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;"), cancellable = true) + @Inject(method = "loadModelFromJson", at = @At(value = "INVOKE", target="Lnet/minecraft/resource/ResourceManager;openAsReader(Lnet/minecraft/util/Identifier;)Ljava/io/BufferedReader;"), cancellable = true) private void loadModelFromJson(Identifier id, CallbackInfoReturnable cir) { if (!ItemRegistry.INSTANCE.getRegisteredItems().containsKey(id.toString())) return; - String modelJson = createItemModelJsonString(id.toString(), ItemRegistry.INSTANCE.getRegisteredItems().get(id.toString())); + String modelJson = ift$createItemModelJsonString(id.toString(), ItemRegistry.INSTANCE.getRegisteredItems().get(id.toString())); JsonUnbakedModel model = JsonUnbakedModel.deserialize(modelJson); model.id = id.toString(); cir.setReturnValue(model); cir.cancel(); } - private String createItemModelJsonString(String id, String modelType) { + @Unique + private String ift$createItemModelJsonString(String id, String modelType) { return "{\n" + " \"parent\": \"item/" + modelType + "\",\n" + " \"textures\": {\n" + " \"layer0\": \"" + id + "\"\n" + " }\n" + "}"; } } diff --git a/src/main/java/wothers/ift/mixins/RegistryMixin.java b/src/main/java/wothers/ift/mixins/RegistryMixin.java index 5f0bb41..0d6603c 100644 --- a/src/main/java/wothers/ift/mixins/RegistryMixin.java +++ b/src/main/java/wothers/ift/mixins/RegistryMixin.java @@ -11,6 +11,7 @@ import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -20,29 +21,33 @@ @Mixin(SimpleRegistry.class) public abstract class RegistryMixin { - private final Map, FoodComponent> foodComponentMap = new HashMap<>(); + + @Unique + private final Map, FoodComponent> itemsfromtext$foodComponentMap = new HashMap<>(); @Inject(method = "add", at = @At(value = "HEAD")) private void interceptAddItem(RegistryKey key, Object entry, Lifecycle lifecycle, CallbackInfoReturnable> cir) { if (!this.equals(Registry.ITEM)) return; - addFoodContainingEffects(key, (Item) entry); + itemsfromtext$addFoodContainingEffects(key, (Item) entry); } - private void addFoodContainingEffects(RegistryKey key, Item item) { + @Unique + private void itemsfromtext$addFoodContainingEffects(RegistryKey key, Item item) { if (!item.isFood()) return; FoodComponent foodComponent = item.getFoodComponent(); if (foodComponent.getStatusEffects().isEmpty()) return; - foodComponentMap.put(key, foodComponent); + itemsfromtext$foodComponentMap.put(key, foodComponent); } @Inject(method = "freeze", at = @At(value = "HEAD")) private void validateOnFreeze(CallbackInfoReturnable> cir) { if (!this.equals(Registry.ITEM)) return; - validateFoodEffects(); + itemsfromtext$validateFoodEffects(); } - private void validateFoodEffects() { - for (Map.Entry, FoodComponent> entry : foodComponentMap.entrySet()) { + @Unique + private void itemsfromtext$validateFoodEffects() { + for (Map.Entry, FoodComponent> entry : itemsfromtext$foodComponentMap.entrySet()) { Iterator> iterator = entry.getValue().getStatusEffects().iterator(); while (iterator.hasNext()) { Pair pair = iterator.next(); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index fae4db6..9c49627 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -23,8 +23,10 @@ "mixins.json" ], "depends": { - "fabricloader": ">=0.12.5", - "minecraft": "1.18.x" + "fabricloader": ">=0.15.3", + "minecraft": "~1.19.2", + "java": ">=17", + "fabric-api": "*" }, "suggests": { "another-mod": "*" diff --git a/src/main/resources/mixins.json b/src/main/resources/mixins.json index aa115b0..c02143b 100644 --- a/src/main/resources/mixins.json +++ b/src/main/resources/mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "wothers.ift.mixins", - "compatibilityLevel": "JAVA_8", + "compatibilityLevel": "JAVA_17", "mixins": [ "FuelLoaderMixin", "LanguageLoaderMixin", From c109e08e46a095acec2f1b822ed88fdf7261d1e1 Mon Sep 17 00:00:00 2001 From: Erik Steiner Date: Wed, 3 Jan 2024 00:05:34 +0100 Subject: [PATCH 12/12] Update to 1.19.2 Signed-off-by: Erik Steiner --- build.gradle | 6 ++++-- gradle.properties | 10 +++++----- .../wothers/ift/items/ItemProperties.java | 2 +- .../wothers/ift/mixins/ModelLoaderMixin.java | 8 +++++--- .../wothers/ift/mixins/RegistryMixin.java | 19 ++++++++++++------- src/main/resources/fabric.mod.json | 6 ++++-- src/main/resources/mixins.json | 2 +- 7 files changed, 32 insertions(+), 21 deletions(-) diff --git a/build.gradle b/build.gradle index c1e099d..d4758b0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '0.11-SNAPSHOT' + id 'fabric-loom' version '1.4-SNAPSHOT' id 'maven-publish' } @@ -14,11 +14,13 @@ dependencies { minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" Set apiModules = [ "fabric-api-base", - "fabric-command-api-v1", + "fabric-command-api-v2", "fabric-lifecycle-events-v1", "fabric-networking-api-v1", "fabric-registry-sync-v0" diff --git a/gradle.properties b/gradle.properties index 03c03fd..5a51458 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,14 +2,14 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties - minecraft_version=1.18.2 - yarn_mappings=1.18.2+build.1 - loader_version=0.13.3 + minecraft_version=1.19.2 + yarn_mappings=1.19.2+build.28 + loader_version=0.15.3 # Mod Properties - mod_version = 1.6.3-1.18.2 + mod_version = 2.0.0-1.19.2 maven_group = wothers.ift archives_base_name = items-from-text # Dependencies - fabric_version=0.47.8+1.18.2 + fabric_version=0.77.0+1.19.2 diff --git a/src/main/java/wothers/ift/items/ItemProperties.java b/src/main/java/wothers/ift/items/ItemProperties.java index 2f72765..fbc0c2c 100644 --- a/src/main/java/wothers/ift/items/ItemProperties.java +++ b/src/main/java/wothers/ift/items/ItemProperties.java @@ -56,7 +56,7 @@ private boolean initialRecipeCheck() { private boolean initialShapedRecipeCheck(String[] strings) { if (NumberUtils.isInteger(strings[1])) return true; - if (strings[1].length() < 1 || strings[1].length() > 3) return true; + if (strings[1].isEmpty() || strings[1].length() > 3) return true; for (int i = 2; i < 4; i++) { if (NumberUtils.isInteger(strings[i])) return false; if (strings[i].length() != strings[1].length()) return true; diff --git a/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java b/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java index ae9bd7b..1dfc335 100644 --- a/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java +++ b/src/main/java/wothers/ift/mixins/ModelLoaderMixin.java @@ -4,6 +4,7 @@ import net.minecraft.client.render.model.json.JsonUnbakedModel; import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -11,17 +12,18 @@ @Mixin(ModelLoader.class) public class ModelLoaderMixin { - @Inject(method = "loadModelFromJson", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourceManager;getResource(Lnet/minecraft/util/Identifier;)Lnet/minecraft/resource/Resource;"), cancellable = true) + @Inject(method = "loadModelFromJson", at = @At(value = "INVOKE", target="Lnet/minecraft/resource/ResourceManager;openAsReader(Lnet/minecraft/util/Identifier;)Ljava/io/BufferedReader;"), cancellable = true) private void loadModelFromJson(Identifier id, CallbackInfoReturnable cir) { if (!ItemRegistry.INSTANCE.getRegisteredItems().containsKey(id.toString())) return; - String modelJson = createItemModelJsonString(id.toString(), ItemRegistry.INSTANCE.getRegisteredItems().get(id.toString())); + String modelJson = ift$createItemModelJsonString(id.toString(), ItemRegistry.INSTANCE.getRegisteredItems().get(id.toString())); JsonUnbakedModel model = JsonUnbakedModel.deserialize(modelJson); model.id = id.toString(); cir.setReturnValue(model); cir.cancel(); } - private String createItemModelJsonString(String id, String modelType) { + @Unique + private String ift$createItemModelJsonString(String id, String modelType) { return "{\n" + " \"parent\": \"item/" + modelType + "\",\n" + " \"textures\": {\n" + " \"layer0\": \"" + id + "\"\n" + " }\n" + "}"; } } diff --git a/src/main/java/wothers/ift/mixins/RegistryMixin.java b/src/main/java/wothers/ift/mixins/RegistryMixin.java index 5f0bb41..0d6603c 100644 --- a/src/main/java/wothers/ift/mixins/RegistryMixin.java +++ b/src/main/java/wothers/ift/mixins/RegistryMixin.java @@ -11,6 +11,7 @@ import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -20,29 +21,33 @@ @Mixin(SimpleRegistry.class) public abstract class RegistryMixin { - private final Map, FoodComponent> foodComponentMap = new HashMap<>(); + + @Unique + private final Map, FoodComponent> itemsfromtext$foodComponentMap = new HashMap<>(); @Inject(method = "add", at = @At(value = "HEAD")) private void interceptAddItem(RegistryKey key, Object entry, Lifecycle lifecycle, CallbackInfoReturnable> cir) { if (!this.equals(Registry.ITEM)) return; - addFoodContainingEffects(key, (Item) entry); + itemsfromtext$addFoodContainingEffects(key, (Item) entry); } - private void addFoodContainingEffects(RegistryKey key, Item item) { + @Unique + private void itemsfromtext$addFoodContainingEffects(RegistryKey key, Item item) { if (!item.isFood()) return; FoodComponent foodComponent = item.getFoodComponent(); if (foodComponent.getStatusEffects().isEmpty()) return; - foodComponentMap.put(key, foodComponent); + itemsfromtext$foodComponentMap.put(key, foodComponent); } @Inject(method = "freeze", at = @At(value = "HEAD")) private void validateOnFreeze(CallbackInfoReturnable> cir) { if (!this.equals(Registry.ITEM)) return; - validateFoodEffects(); + itemsfromtext$validateFoodEffects(); } - private void validateFoodEffects() { - for (Map.Entry, FoodComponent> entry : foodComponentMap.entrySet()) { + @Unique + private void itemsfromtext$validateFoodEffects() { + for (Map.Entry, FoodComponent> entry : itemsfromtext$foodComponentMap.entrySet()) { Iterator> iterator = entry.getValue().getStatusEffects().iterator(); while (iterator.hasNext()) { Pair pair = iterator.next(); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index fae4db6..9c49627 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -23,8 +23,10 @@ "mixins.json" ], "depends": { - "fabricloader": ">=0.12.5", - "minecraft": "1.18.x" + "fabricloader": ">=0.15.3", + "minecraft": "~1.19.2", + "java": ">=17", + "fabric-api": "*" }, "suggests": { "another-mod": "*" diff --git a/src/main/resources/mixins.json b/src/main/resources/mixins.json index aa115b0..c02143b 100644 --- a/src/main/resources/mixins.json +++ b/src/main/resources/mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "wothers.ift.mixins", - "compatibilityLevel": "JAVA_8", + "compatibilityLevel": "JAVA_17", "mixins": [ "FuelLoaderMixin", "LanguageLoaderMixin",