diff --git a/MineTweaker3-API/src/main/java/minetweaker/expand/ExpandString.java b/MineTweaker3-API/src/main/java/minetweaker/expand/ExpandString.java index e1fad89..3fd2f7b 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/expand/ExpandString.java +++ b/MineTweaker3-API/src/main/java/minetweaker/expand/ExpandString.java @@ -14,10 +14,12 @@ import minetweaker.api.chat.IChatMessage; import minetweaker.api.data.DataString; import minetweaker.api.data.IData; import minetweaker.api.formatting.IFormattedText; +import stanhebben.zenscript.annotations.OperatorType; import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.ZenCaster; import stanhebben.zenscript.annotations.ZenExpansion; import stanhebben.zenscript.annotations.ZenMethod; +import stanhebben.zenscript.annotations.ZenOperator; /** * @@ -25,6 +27,16 @@ import stanhebben.zenscript.annotations.ZenMethod; */ @ZenExpansion("string") public class ExpandString { + @ZenOperator(OperatorType.ADD) + public static IFormattedText add(String str, IFormattedText formattedText) { + return MineTweakerAPI.format.string(str).add(formattedText); + } + + @ZenOperator(OperatorType.CAT) + public static IFormattedText cat(String str, IFormattedText formattedText) { + return add(str, formattedText); + } + @ZenCaster public static IData asData(String value) { return new DataString(value); diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java index 37b355a..c58cf01 100644 --- a/MineTweaker3-MC164-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java @@ -414,4 +414,22 @@ public class MineTweakerMC { } return result; } + + /** + * Converts a Minecraft ingredient to a MineTweaker ingredient. + * + * @param ingredient minecraft ingredient + * @return minetweaker ingredient + */ + public static IIngredient getIIngredient(Object ingredient) { + if (ingredient instanceof String) { + return MineTweakerAPI.oreDict.get((String) ingredient); + } else if (ingredient instanceof Item) { + return getIItemStack(new ItemStack((Item) ingredient, 1, 0)); + } else if (ingredient instanceof ItemStack) { + return getIItemStack((ItemStack) ingredient); + } else { + throw new IllegalArgumentException("Not a valid ingredient: " + ingredient); + } + } } diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java index 019d969..0d09262 100644 --- a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java @@ -67,13 +67,15 @@ public class MineTweakerMod { "minetweaker.mods.ic2.ClassRegistry", "minetweaker.mods.nei.ClassRegistry", "minetweaker.mods.mfr.ClassRegistry", - "minetweaker.mods.gregtech.ClassRegistry" + "minetweaker.mods.gregtech.ClassRegistry", + "minetweaker.mods.buildcraft.ClassRegistry" }; private static final String[] REGISTRY_DESCRIPTIONS = { "IC2 mod support", "NEI mod support", "MFR mod support", - "GregTech mod support" + "GregTech mod support", + "Buildcraft mod support" }; @Mod.Instance(MODID) diff --git a/MineTweaker3-MC164-Mod-Buildcraft/build.gradle b/MineTweaker3-MC164-Mod-Buildcraft/build.gradle new file mode 100644 index 0000000..57baf32 --- /dev/null +++ b/MineTweaker3-MC164-Mod-Buildcraft/build.gradle @@ -0,0 +1,42 @@ +import minetweaker.tasks.RegisterZenClassesTask; + +buildscript { + repositories { + mavenCentral() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:1.0-SNAPSHOT' + } +} + +apply plugin: 'forge' + +minecraft { + version = forgeVersion164 +} + +version = "1.0" +archivesBaseName = project.projectDir.name + +dependencies { + compile project(':ZenScript') + compile project(':MineTweaker3-API') + compile project(':MineTweaker3-MC164-Main') + compile files('libs/buildcraft-A-1.6.4-4.2.1.jar') +} + +task makeRegistry(type: RegisterZenClassesTask) { + inputDir = file('build/classes/main') + outputDir = file('build/classes/main') + className = 'minetweaker.mods.buildcraft.ClassRegistry' +} + +tasks.jar.dependsOn(makeRegistry) diff --git a/MineTweaker3-MC164-Mod-Buildcraft/libs/buildcraft-A-1.6.4-4.2.1.jar b/MineTweaker3-MC164-Mod-Buildcraft/libs/buildcraft-A-1.6.4-4.2.1.jar new file mode 100644 index 0000000..c31d77f Binary files /dev/null and b/MineTweaker3-MC164-Mod-Buildcraft/libs/buildcraft-A-1.6.4-4.2.1.jar differ diff --git a/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/AssemblyTable.java b/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/AssemblyTable.java new file mode 100644 index 0000000..3921f36 --- /dev/null +++ b/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/AssemblyTable.java @@ -0,0 +1,184 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mods.buildcraft; + +import buildcraft.api.recipes.AssemblyRecipe; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.buildcraft.AssemblyTable") +@ModOnly("BuildCraft|Core") +public class AssemblyTable { + @ZenMethod + public static void addRecipe(IItemStack output, double energy, IIngredient[] ingredients) { + MineTweakerAPI.apply(new AddRecipeAction(output, energy, ingredients)); + } + + @ZenMethod + public static void remove(IIngredient output) { + removeRecipe(output, null, false); + } + + @ZenMethod + public static void removeRecipe(IIngredient output, @Optional IIngredient[] ingredients, @Optional boolean wildcard) { + List toRemove = new ArrayList(); + + outer: for (AssemblyRecipe recipe : AssemblyRecipe.assemblyRecipes) { + if (output.matches(MineTweakerMC.getIItemStack(recipe.output)) + && ingredientsMatch(recipe, ingredients, wildcard)) { + toRemove.add(recipe); + } + } + + for (AssemblyRecipe recipe : toRemove) { + MineTweakerAPI.apply(new RemoveRecipeAction(recipe)); + } + } + + /** + * Checks if ingredients from the recipe match with the given ingredients. + * + * @param recipe recipe to check + * @param ingredients required ingredients + * @param wildcard true if there can be more ingredients in the recipe than given, false otherwise + * @return matching result + */ + private static boolean ingredientsMatch(AssemblyRecipe recipe, IIngredient[] ingredients, boolean wildcard) { + if (ingredients == null) + return true; + + System.out.println("Assembly Table Recipe " + Arrays.deepToString(recipe.input)); + + int matchedIngredients = 0; + boolean[] matched = new boolean[ingredients.length]; + checkIngredient: for (int i = 0; i < recipe.input.length; i++) { + Object ingredientObject = recipe.input[i]; + if (ingredientObject instanceof Number) + continue; + + IIngredient recipeIngredient = MineTweakerMC.getIIngredient(recipe.input[i]); + + for (int j = 0; j < ingredients.length; j++) { + if (!matched[j] && ingredients[j].contains(recipeIngredient)) { + matched[j] = true; + matchedIngredients++; + continue checkIngredient; + } + } + + if (!wildcard) + return false; + } + + return matchedIngredients == ingredients.length; + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddRecipeAction implements IUndoableAction { + private final IItemStack output; + private final AssemblyRecipe recipe; + + public AddRecipeAction(IItemStack output, double energy, IIngredient[] ingredients) { + this.output = output; + + Object[] mcIngredients = new Object[ingredients.length]; + for (int i = 0; i < ingredients.length; i++) { + mcIngredients[i] = ingredients[i].getInternal(); + if (mcIngredients[i] == null) { + throw new IllegalArgumentException("Not a valid assembly table ingredient"); + } + } + + recipe = new AssemblyRecipe((int) energy, MineTweakerMC.getItemStack(output), mcIngredients); + } + + @Override + public void apply() { + AssemblyRecipe.assemblyRecipes.add(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + AssemblyRecipe.assemblyRecipes.remove(recipe); + } + + @Override + public String describe() { + return "Adding assembly table recipe for " + output; + } + + @Override + public String describeUndo() { + return "Removing assembly table recipe for " + output; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveRecipeAction implements IUndoableAction { + private final AssemblyRecipe recipe; + + public RemoveRecipeAction(AssemblyRecipe recipe) { + this.recipe = recipe; + } + + @Override + public void apply() { + AssemblyRecipe.assemblyRecipes.remove(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + AssemblyRecipe.assemblyRecipes.add(recipe); + } + + @Override + public String describe() { + return "Removing assembly table recipe for " + MineTweakerMC.getIItemStack(recipe.output); + } + + @Override + public String describeUndo() { + return "Restoring assembly table recipe for " + MineTweakerMC.getIItemStack(recipe.output); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Fuels.java b/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Fuels.java new file mode 100644 index 0000000..994e14c --- /dev/null +++ b/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Fuels.java @@ -0,0 +1,375 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mods.buildcraft; + +import buildcraft.api.core.StackWrapper; +import buildcraft.api.fuels.IronEngineCoolant; +import buildcraft.api.fuels.IronEngineFuel; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; +import java.util.logging.Logger; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.buildcraft.Fuels") +@ModOnly("BuildCraft|Core") +public class Fuels { + private static final Constructor CONSTRUCT_FUEL; + + static { + Constructor newFuel = null; + try { + newFuel = IronEngineFuel.Fuel.class.getDeclaredConstructor(Fluid.class, float.class, int.class); + newFuel.setAccessible(true); + } catch (NoSuchMethodException ex) { + MineTweakerAPI.logError("Could not load combustion engine fuel constructor", ex); + } catch (SecurityException ex) { + MineTweakerAPI.logError("Could not load combustion engine fuel constructor", ex); + } + + CONSTRUCT_FUEL = newFuel; + } + + @ZenMethod + public static void addCombustionEngineFuel(ILiquidStack fuel, double powerPerCycle, int totalBurningTime) { + MineTweakerAPI.apply(new AddFuelAction(fuel, powerPerCycle, totalBurningTime)); + } + + @ZenMethod + public static void removeCombustionEngineFuel(ILiquidStack fuel) { + Fluid fluid = MineTweakerMC.getLiquidStack(fuel).getFluid(); + if (IronEngineFuel.fuels.containsKey(fluid.getName())) { + MineTweakerAPI.apply(new RemoveFuelAction(fluid.getName(), IronEngineFuel.fuels.get(fluid.getName()))); + } else { + MineTweakerAPI.logWarning("No such iron engine fuel: " + fluid.getName()); + } + } + + @ZenMethod + public static void addCombustionEngineCoolant(ILiquidStack coolant, float coolingPerMB) { + MineTweakerAPI.apply(new AddLiquidCoolantAction(coolant.getName(), new MTCoolant(coolingPerMB))); + } + + @ZenMethod + public static void addCoolantItem(IItemStack coolantItem, ILiquidStack coolantLiquid) { + MineTweakerAPI.apply(new AddCoolantItemAction(new StackWrapper(MineTweakerMC.getItemStack(coolantItem)), MineTweakerMC.getLiquidStack(coolantLiquid))); + } + + @ZenMethod + public static void removeCombustionEngineCoolant(ILiquidStack coolant) { + FluidStack fluid = MineTweakerMC.getLiquidStack(coolant); + + if (IronEngineCoolant.isCoolant(fluid.getFluid())) { + MineTweakerAPI.apply(new RemoveLiquidCoolantAction(fluid.getFluid().getName(), IronEngineCoolant.getCoolant(fluid))); + } else { + MineTweakerAPI.logWarning("No such iron engine coolant: " + fluid.getFluid().getName()); + } + } + + @ZenMethod + public static void removeCoolantItem(IIngredient item) { + int numRemoved = 0; + for (IItemStack itemStack : item.getItems()) { + StackWrapper key = new StackWrapper(MineTweakerMC.getItemStack(itemStack)); + if (IronEngineCoolant.solidCoolants.containsKey(key)) { + MineTweakerAPI.apply(new RemoveCoolantItemAction(key, IronEngineCoolant.solidCoolants.get(key))); + numRemoved++; + } + } + + if (numRemoved == 0) { + MineTweakerAPI.logWarning("No such iron engine coolant: " + item); + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddFuelAction implements IUndoableAction { + private final String fuelName; + private final IronEngineFuel.Fuel fuel; + + public AddFuelAction(ILiquidStack fuel, double powerPerCycle, int totalBurningTime) { + fuelName = fuel.getName(); + IronEngineFuel.Fuel ieFuel = null; + try { + if (CONSTRUCT_FUEL == null) + System.out.println("No constructor for fuel"); + + ieFuel = (IronEngineFuel.Fuel) CONSTRUCT_FUEL.newInstance(MineTweakerMC.getLiquidStack(fuel).getFluid(), (float) powerPerCycle, totalBurningTime); + } catch (InstantiationException ex) { + Logger.getLogger(Fuels.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + Logger.getLogger(Fuels.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalArgumentException ex) { + Logger.getLogger(Fuels.class.getName()).log(Level.SEVERE, null, ex); + } catch (InvocationTargetException ex) { + Logger.getLogger(Fuels.class.getName()).log(Level.SEVERE, null, ex); + } + + this.fuel = ieFuel; + } + + @Override + public void apply() { + IronEngineFuel.fuels.put(fuelName, fuel); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineFuel.fuels.remove(fuelName); + } + + @Override + public String describe() { + return "Adding iron engine fuel " + fuelName; + } + + @Override + public String describeUndo() { + return "Removing iron engine fuel " + fuelName; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveFuelAction implements IUndoableAction { + private final String fuelName; + private final IronEngineFuel.Fuel fuel; + + public RemoveFuelAction(String fuelName, IronEngineFuel.Fuel fuel) { + this.fuelName = fuelName; + this.fuel = fuel; + } + + @Override + public void apply() { + IronEngineFuel.fuels.remove(fuelName); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineFuel.fuels.put(fuelName, fuel); + } + + @Override + public String describe() { + return "Removing iron engine fuel " + fuelName; + } + + @Override + public String describeUndo() { + return "Restoring iron engine fuel " + fuelName; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AddLiquidCoolantAction implements IUndoableAction { + private final String liquid; + private final IronEngineCoolant.Coolant coolant; + + public AddLiquidCoolantAction(String liquid, IronEngineCoolant.Coolant coolant) { + this.liquid = liquid; + this.coolant = coolant; + } + + @Override + public void apply() { + IronEngineCoolant.liquidCoolants.put(liquid, coolant); + } + + @Override + public boolean canUndo() { + return false; + } + + @Override + public void undo() { + IronEngineCoolant.liquidCoolants.remove(liquid); + } + + @Override + public String describe() { + return "Adding iron engine coolant " + liquid; + } + + @Override + public String describeUndo() { + return "Removing iron engine coolant " + liquid; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AddCoolantItemAction implements IUndoableAction { + private final StackWrapper item; + private final FluidStack liquid; + + public AddCoolantItemAction(StackWrapper item, FluidStack liquid) { + this.item = item; + this.liquid = liquid; + } + + @Override + public void apply() { + IronEngineCoolant.solidCoolants.put(item, liquid); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineCoolant.solidCoolants.remove(item); + } + + @Override + public String describe() { + return "Adding iron engine coolant item " + MineTweakerMC.getIItemStack(item.stack); + } + + @Override + public String describeUndo() { + return "Removing iron engine coolant item " + MineTweakerMC.getIItemStack(item.stack); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveLiquidCoolantAction implements IUndoableAction { + private final String liquid; + private final IronEngineCoolant.Coolant coolant; + + public RemoveLiquidCoolantAction(String liquid, IronEngineCoolant.Coolant coolant) { + this.liquid = liquid; + this.coolant = coolant; + } + + @Override + public void apply() { + IronEngineCoolant.liquidCoolants.remove(liquid); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineCoolant.liquidCoolants.put(liquid, coolant); + } + + @Override + public String describe() { + return "Removing iron engine coolant " + liquid; + } + + @Override + public String describeUndo() { + return "Restoring iron engine coolant " + liquid; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveCoolantItemAction implements IUndoableAction { + private final StackWrapper item; + private final FluidStack liquid; + + public RemoveCoolantItemAction(StackWrapper item, FluidStack liquid) { + this.item = item; + this.liquid = liquid; + } + + @Override + public void apply() { + IronEngineCoolant.solidCoolants.remove(item); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineCoolant.solidCoolants.put(item, liquid); + } + + @Override + public String describe() { + return "Removing iron engine coolant item " + item.stack.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Restoring iron engine coolant item " + item.stack.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class MTCoolant implements IronEngineCoolant.Coolant { + private final float coolingPerMB; + + public MTCoolant(float coolingPerMB) { + this.coolingPerMB = coolingPerMB; + } + + @Override + public float getDegreesCoolingPerMB(float f) { + return coolingPerMB; + } + } +} diff --git a/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Refinery.java b/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Refinery.java new file mode 100644 index 0000000..3ed5ec6 --- /dev/null +++ b/MineTweaker3-MC164-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Refinery.java @@ -0,0 +1,200 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mods.buildcraft; + +import buildcraft.api.recipes.RefineryRecipes; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.SortedSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.buildcraft.Refinery") +@ModOnly("BuildCraft|Core") +public class Refinery { + private static final Constructor CONSTRUCT_REFINERYRECIPE; + private static final Field REFINERYRECIPEMANAGER_RECIPES; + + static { + Constructor constructor = null; + try { + constructor = RefineryRecipes.Recipe.class.getDeclaredConstructor(FluidStack.class, FluidStack.class, FluidStack.class, int.class, int.class); + constructor.setAccessible(true); + } catch (NoSuchMethodException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } + + Field recipes = null; + try { + recipes = RefineryRecipes.class.getDeclaredField("recipes"); + recipes.setAccessible(true); + } catch (NoSuchFieldException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } + + CONSTRUCT_REFINERYRECIPE = constructor; + REFINERYRECIPEMANAGER_RECIPES = recipes; + } + + + @ZenMethod + public static void addRecipe(ILiquidStack output, int energyPerMB, int ticksPerMB, ILiquidStack input1, @Optional ILiquidStack input2) { + MineTweakerAPI.apply(new AddRecipeAction(output, energyPerMB, ticksPerMB, input1, input2)); + } + + @ZenMethod + public static void remove(ILiquidStack output) { + Fluid fluid = MineTweakerMC.getLiquidStack(output).getFluid(); + + List toRemove = new ArrayList(); + for (RefineryRecipes.Recipe recipe : RefineryRecipes.getRecipes()) { + if (recipe.result.getFluid() == fluid) { + toRemove.add(recipe); + } + } + + for (RefineryRecipes.Recipe recipe : toRemove) { + MineTweakerAPI.apply(new RemoveRecipeAction(recipe)); + } + } + + private static SortedSet getRecipes() { + try { + return (SortedSet) REFINERYRECIPEMANAGER_RECIPES.get(null); + } catch (IllegalArgumentException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } + + throw new RuntimeException("Refinery recipes unavailable"); + } + + // ###################### + // ### Action Classes ### + // ###################### + + private static class AddRecipeAction implements IUndoableAction { + private final ILiquidStack output; + private final RefineryRecipes.Recipe recipe; + + public AddRecipeAction(ILiquidStack output, int energyPerMB, int ticksPerMB, ILiquidStack input1, ILiquidStack input2) { + this.output = output; + + RefineryRecipes.Recipe rrecipe = null; + try { + rrecipe = (RefineryRecipes.Recipe) CONSTRUCT_REFINERYRECIPE.newInstance( + MineTweakerMC.getLiquidStack(input1), + MineTweakerMC.getLiquidStack(input2), + MineTweakerMC.getLiquidStack(output), + energyPerMB, + ticksPerMB); + } catch (InstantiationException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalArgumentException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (InvocationTargetException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } + + recipe = rrecipe; + } + + @Override + public void apply() { + getRecipes().add(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + getRecipes().add(recipe); + } + + @Override + public String describe() { + return "Adding refinery recipe for " + output; + } + + @Override + public String describeUndo() { + return "Removing refinery recipe for " + output; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveRecipeAction implements IUndoableAction { + private final RefineryRecipes.Recipe recipe; + + public RemoveRecipeAction(RefineryRecipes.Recipe recipe) { + this.recipe = recipe; + } + + @Override + public void apply() { + getRecipes().remove(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + getRecipes().add(recipe); + } + + @Override + public String describe() { + return "Removing refinery recipe for " + + recipe.result.getFluid().getLocalizedName(); + } + + @Override + public String describeUndo() { + return "Restoring refinery recipe for " + + recipe.result.getFluid().getLocalizedName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java index 5d57633..83ac691 100644 --- a/MineTweaker3-MC172-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java @@ -397,4 +397,31 @@ public class MineTweakerMC { return (FluidStack) stack.getInternal(); } + + /** + * Converts a Minecraft ingredient to a MineTweaker ingredient. + * + * @param ingredient minecraft ingredient + * @return minetweaker ingredient + */ + public static IIngredient getIIngredient(Object ingredient) { + if (ingredient instanceof String) { + return MineTweakerAPI.oreDict.get((String) ingredient); + } else if (ingredient instanceof Item) { + return getIItemStack(new ItemStack((Item) ingredient, 1, 0)); + } else if (ingredient instanceof ItemStack) { + return getIItemStack((ItemStack) ingredient); + } else { + throw new IllegalArgumentException("Not a valid ingredient: " + ingredient); + } + } + + public static ItemStack[] getExamples(IIngredient ingredient) { + List examples = ingredient.getItems(); + ItemStack[] result = new ItemStack[examples.size()]; + for (int i = 0; i < examples.size(); i++) { + result[i] = MineTweakerMC.getItemStack(examples.get(i)); + } + return result; + } } diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java index d885116..a10a3b6 100644 --- a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/MineTweakerMod.java @@ -49,7 +49,7 @@ import net.minecraftforge.common.MinecraftForge; * * @author Stan Hebben */ -@Mod(modid = MineTweakerMod.MODID, version = "${version}") +@Mod(modid = MineTweakerMod.MODID, version = "3.0.9") public class MineTweakerMod { public static final String MODID = "MineTweaker3"; public static final String MCVERSION = "1.7.2"; @@ -59,12 +59,14 @@ public class MineTweakerMod { private static final String[] REGISTRIES = { "minetweaker.mods.ic2.ClassRegistry", "minetweaker.mods.nei.ClassRegistry", - "minetweaker.mods.gregtech.ClassRegistry" + "minetweaker.mods.gregtech.ClassRegistry", + "minetweaker.mods.buildcraft.ClassRegistry" }; private static final String[] REGISTRY_DESCRIPTIONS = { "IC2 mod support", "NEI mod support", - "GregTech mod support" + "GregTech mod support", + "Buildcraft mod support" }; static { diff --git a/MineTweaker3-MC172-Mod-Buildcraft/build.gradle b/MineTweaker3-MC172-Mod-Buildcraft/build.gradle new file mode 100644 index 0000000..9939c31 --- /dev/null +++ b/MineTweaker3-MC172-Mod-Buildcraft/build.gradle @@ -0,0 +1,42 @@ +import minetweaker.tasks.RegisterZenClassesTask; + +buildscript { + repositories { + mavenCentral() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' + } +} + +apply plugin: 'forge' + +minecraft { + version = forgeVersion172 +} + +version = "1.0" +archivesBaseName = project.projectDir.name + +dependencies { + compile project(':ZenScript') + compile project(':MineTweaker3-API') + compile project(':MineTweaker3-MC172-Main') + compile files('libs/buildcraft-6.0.16-dev.jar') +} + +task makeRegistry(type: RegisterZenClassesTask) { + inputDir = file('build/classes/main') + outputDir = file('build/classes/main') + className = 'minetweaker.mods.buildcraft.ClassRegistry' +} + +tasks.jar.dependsOn(makeRegistry) diff --git a/MineTweaker3-MC172-Mod-Buildcraft/libs/buildcraft-6.0.16-dev.jar b/MineTweaker3-MC172-Mod-Buildcraft/libs/buildcraft-6.0.16-dev.jar new file mode 100644 index 0000000..71b9c5c Binary files /dev/null and b/MineTweaker3-MC172-Mod-Buildcraft/libs/buildcraft-6.0.16-dev.jar differ diff --git a/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/AssemblyTable.java b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/AssemblyTable.java new file mode 100644 index 0000000..e20cb57 --- /dev/null +++ b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/AssemblyTable.java @@ -0,0 +1,184 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mods.buildcraft; + +import buildcraft.api.recipes.BuildcraftRecipes; +import buildcraft.core.recipes.AssemblyRecipeManager; +import buildcraft.core.recipes.AssemblyRecipeManager.AssemblyRecipe; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.buildcraft.AssemblyTable") +@ModOnly("BuildCraft|Core") +public class AssemblyTable { + @ZenMethod + public static void addRecipe(IItemStack output, double energy, IIngredient[] ingredients) { + MineTweakerAPI.apply(new AddRecipeAction(output, energy, ingredients)); + } + + @ZenMethod + public static void remove(IIngredient output) { + removeRecipe(output, null, false); + } + + @ZenMethod + public static void removeRecipe(IIngredient output, @Optional IIngredient[] ingredients, @Optional boolean wildcard) { + List toRemove = new ArrayList(); + + outer: for (AssemblyRecipe recipe : ((AssemblyRecipeManager) BuildcraftRecipes.assemblyTable).getRecipes()) { + if (output.matches(MineTweakerMC.getIItemStack(recipe.getOutput())) + && ingredientsMatch(recipe, ingredients, wildcard)) { + toRemove.add(recipe); + } + } + + for (AssemblyRecipe recipe : toRemove) { + MineTweakerAPI.apply(new RemoveRecipeAction(recipe)); + } + } + + /** + * Checks if ingredients from the recipe match with the given ingredients. + * + * @param recipe recipe to check + * @param ingredients required ingredients + * @param wildcard true if there can be more ingredients in the recipe than given, false otherwise + * @return matching result + */ + private static boolean ingredientsMatch(AssemblyRecipe recipe, IIngredient[] ingredients, boolean wildcard) { + if (ingredients == null) + return true; + + int matchedIngredients = 0; + boolean[] matched = new boolean[ingredients.length]; + checkIngredient: for (int i = 0; i < recipe.getInputs().length; i++) { + Object ingredientObject = recipe.getInputs()[i]; + if (ingredientObject instanceof Number) + continue; + + IIngredient recipeIngredient = MineTweakerMC.getIIngredient(recipe.getInputs()[i]); + + for (int j = 0; j < ingredients.length; j++) { + if (!matched[j] && ingredients[j].contains(recipeIngredient)) { + matched[j] = true; + matchedIngredients++; + continue checkIngredient; + } + } + + if (!wildcard) + return false; + } + + return matchedIngredients == ingredients.length; + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddRecipeAction implements IUndoableAction { + private final IItemStack output; + private final AssemblyRecipe recipe; + + public AddRecipeAction(IItemStack output, double energy, IIngredient[] ingredients) { + this.output = output; + + Object[] mcIngredients = new Object[ingredients.length]; + for (int i = 0; i < ingredients.length; i++) { + mcIngredients[i] = ingredients[i].getInternal(); + if (mcIngredients[i] == null) { + throw new IllegalArgumentException("Not a valid assembly table ingredient"); + } + } + + recipe = new AssemblyRecipe(MineTweakerMC.getItemStack(output), energy, mcIngredients); + } + + @Override + public void apply() { + ((AssemblyRecipeManager) BuildcraftRecipes.assemblyTable).getRecipes().add(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + BuildcraftRecipes.assemblyTable.getRecipes().remove(recipe); + } + + @Override + public String describe() { + return "Adding assembly table recipe for " + output; + } + + @Override + public String describeUndo() { + return "Removing assembly table recipe for " + output; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveRecipeAction implements IUndoableAction { + private final AssemblyRecipe recipe; + + public RemoveRecipeAction(AssemblyRecipe recipe) { + this.recipe = recipe; + } + + @Override + public void apply() { + BuildcraftRecipes.assemblyTable.getRecipes().remove(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + ((AssemblyRecipeManager) BuildcraftRecipes.assemblyTable).getRecipes().add(recipe); + } + + @Override + public String describe() { + return "Removing assembly table recipe for " + MineTweakerMC.getIItemStack(recipe.getOutput()); + } + + @Override + public String describeUndo() { + return "Restoring assembly table recipe for " + MineTweakerMC.getIItemStack(recipe.getOutput()); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Fuels.java b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Fuels.java new file mode 100644 index 0000000..5053306 --- /dev/null +++ b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Fuels.java @@ -0,0 +1,375 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mods.buildcraft; + +import buildcraft.api.core.StackKey; +import buildcraft.api.fuels.IronEngineCoolant; +import buildcraft.api.fuels.IronEngineFuel; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; +import java.util.logging.Logger; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.buildcraft.Fuels") +@ModOnly("BuildCraft|Core") +public class Fuels { + private static final Constructor CONSTRUCT_FUEL; + + static { + Constructor newFuel = null; + try { + newFuel = IronEngineFuel.Fuel.class.getDeclaredConstructor(Fluid.class, float.class, int.class); + newFuel.setAccessible(true); + } catch (NoSuchMethodException ex) { + MineTweakerAPI.logError("Could not load combustion engine fuel constructor", ex); + } catch (SecurityException ex) { + MineTweakerAPI.logError("Could not load combustion engine fuel constructor", ex); + } + + CONSTRUCT_FUEL = newFuel; + } + + @ZenMethod + public static void addCombustionEngineFuel(ILiquidStack fuel, double powerPerCycle, int totalBurningTime) { + MineTweakerAPI.apply(new AddFuelAction(fuel, powerPerCycle, totalBurningTime)); + } + + @ZenMethod + public static void removeCombustionEngineFuel(ILiquidStack fuel) { + Fluid fluid = MineTweakerMC.getLiquidStack(fuel).getFluid(); + if (IronEngineFuel.fuels.containsKey(fluid.getName())) { + MineTweakerAPI.apply(new RemoveFuelAction(fluid.getName(), IronEngineFuel.fuels.get(fluid.getName()))); + } else { + MineTweakerAPI.logWarning("No such iron engine fuel: " + fluid.getName()); + } + } + + @ZenMethod + public static void addCombustionEngineCoolant(ILiquidStack coolant, float coolingPerMB) { + MineTweakerAPI.apply(new AddLiquidCoolantAction(coolant.getName(), new MTCoolant(coolingPerMB))); + } + + @ZenMethod + public static void addCoolantItem(IItemStack coolantItem, ILiquidStack coolantLiquid) { + MineTweakerAPI.apply(new AddCoolantItemAction(new StackKey(MineTweakerMC.getItemStack(coolantItem)), MineTweakerMC.getLiquidStack(coolantLiquid))); + } + + @ZenMethod + public static void removeCombustionEngineCoolant(ILiquidStack coolant) { + FluidStack fluid = MineTweakerMC.getLiquidStack(coolant); + + if (IronEngineCoolant.isCoolant(fluid.getFluid())) { + MineTweakerAPI.apply(new RemoveLiquidCoolantAction(fluid.getFluid().getName(), IronEngineCoolant.getCoolant(fluid))); + } else { + MineTweakerAPI.logWarning("No such iron engine coolant: " + fluid.getFluid().getName()); + } + } + + @ZenMethod + public static void removeCoolantItem(IIngredient item) { + int numRemoved = 0; + for (IItemStack itemStack : item.getItems()) { + StackKey key = new StackKey(MineTweakerMC.getItemStack(itemStack)); + if (IronEngineCoolant.solidCoolants.containsKey(key)) { + MineTweakerAPI.apply(new RemoveCoolantItemAction(key, IronEngineCoolant.solidCoolants.get(key))); + numRemoved++; + } + } + + if (numRemoved == 0) { + MineTweakerAPI.logWarning("No such iron engine coolant: " + item); + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddFuelAction implements IUndoableAction { + private final String fuelName; + private final IronEngineFuel.Fuel fuel; + + public AddFuelAction(ILiquidStack fuel, double powerPerCycle, int totalBurningTime) { + fuelName = fuel.getName(); + IronEngineFuel.Fuel ieFuel = null; + try { + if (CONSTRUCT_FUEL == null) + System.out.println("No constructor for fuel"); + + ieFuel = (IronEngineFuel.Fuel) CONSTRUCT_FUEL.newInstance(MineTweakerMC.getLiquidStack(fuel).getFluid(), (float) powerPerCycle, totalBurningTime); + } catch (InstantiationException ex) { + Logger.getLogger(Fuels.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + Logger.getLogger(Fuels.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalArgumentException ex) { + Logger.getLogger(Fuels.class.getName()).log(Level.SEVERE, null, ex); + } catch (InvocationTargetException ex) { + Logger.getLogger(Fuels.class.getName()).log(Level.SEVERE, null, ex); + } + + this.fuel = ieFuel; + } + + @Override + public void apply() { + IronEngineFuel.fuels.put(fuelName, fuel); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineFuel.fuels.remove(fuelName); + } + + @Override + public String describe() { + return "Adding iron engine fuel " + fuelName; + } + + @Override + public String describeUndo() { + return "Removing iron engine fuel " + fuelName; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveFuelAction implements IUndoableAction { + private final String fuelName; + private final IronEngineFuel.Fuel fuel; + + public RemoveFuelAction(String fuelName, IronEngineFuel.Fuel fuel) { + this.fuelName = fuelName; + this.fuel = fuel; + } + + @Override + public void apply() { + IronEngineFuel.fuels.remove(fuelName); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineFuel.fuels.put(fuelName, fuel); + } + + @Override + public String describe() { + return "Removing iron engine fuel " + fuelName; + } + + @Override + public String describeUndo() { + return "Restoring iron engine fuel " + fuelName; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AddLiquidCoolantAction implements IUndoableAction { + private final String liquid; + private final IronEngineCoolant.Coolant coolant; + + public AddLiquidCoolantAction(String liquid, IronEngineCoolant.Coolant coolant) { + this.liquid = liquid; + this.coolant = coolant; + } + + @Override + public void apply() { + IronEngineCoolant.liquidCoolants.put(liquid, coolant); + } + + @Override + public boolean canUndo() { + return false; + } + + @Override + public void undo() { + IronEngineCoolant.liquidCoolants.remove(liquid); + } + + @Override + public String describe() { + return "Adding iron engine coolant " + liquid; + } + + @Override + public String describeUndo() { + return "Removing iron engine coolant " + liquid; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AddCoolantItemAction implements IUndoableAction { + private final StackKey item; + private final FluidStack liquid; + + public AddCoolantItemAction(StackKey item, FluidStack liquid) { + this.item = item; + this.liquid = liquid; + } + + @Override + public void apply() { + IronEngineCoolant.solidCoolants.put(item, liquid); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineCoolant.solidCoolants.remove(item); + } + + @Override + public String describe() { + return "Adding iron engine coolant item " + MineTweakerMC.getIItemStack(item.stack); + } + + @Override + public String describeUndo() { + return "Removing iron engine coolant item " + MineTweakerMC.getIItemStack(item.stack); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveLiquidCoolantAction implements IUndoableAction { + private final String liquid; + private final IronEngineCoolant.Coolant coolant; + + public RemoveLiquidCoolantAction(String liquid, IronEngineCoolant.Coolant coolant) { + this.liquid = liquid; + this.coolant = coolant; + } + + @Override + public void apply() { + IronEngineCoolant.liquidCoolants.remove(liquid); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineCoolant.liquidCoolants.put(liquid, coolant); + } + + @Override + public String describe() { + return "Removing iron engine coolant " + liquid; + } + + @Override + public String describeUndo() { + return "Restoring iron engine coolant " + liquid; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveCoolantItemAction implements IUndoableAction { + private final StackKey item; + private final FluidStack liquid; + + public RemoveCoolantItemAction(StackKey item, FluidStack liquid) { + this.item = item; + this.liquid = liquid; + } + + @Override + public void apply() { + IronEngineCoolant.solidCoolants.remove(item); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + IronEngineCoolant.solidCoolants.put(item, liquid); + } + + @Override + public String describe() { + return "Removing iron engine coolant item " + item.stack.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Restoring iron engine coolant item " + item.stack.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class MTCoolant implements IronEngineCoolant.Coolant { + private final float coolingPerMB; + + public MTCoolant(float coolingPerMB) { + this.coolingPerMB = coolingPerMB; + } + + @Override + public float getDegreesCoolingPerMB(float f) { + return coolingPerMB; + } + } +} diff --git a/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/IIntegrationRecipeFunction.java b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/IIntegrationRecipeFunction.java new file mode 100644 index 0000000..f372d7d --- /dev/null +++ b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/IIntegrationRecipeFunction.java @@ -0,0 +1,17 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mods.buildcraft; + +import minetweaker.api.item.IItemStack; + +/** + * + * @author Stan + */ +public interface IIntegrationRecipeFunction { + public IItemStack recipe(IItemStack output, IItemStack inputA, IItemStack inputB); +} diff --git a/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/IntegrationTable.java b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/IntegrationTable.java new file mode 100644 index 0000000..f55ee76 --- /dev/null +++ b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/IntegrationTable.java @@ -0,0 +1,217 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mods.buildcraft; + +import buildcraft.api.recipes.BuildcraftRecipes; +import buildcraft.api.recipes.IIntegrationRecipeManager.IIntegrationRecipe; +import java.util.ArrayList; +import java.util.List; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.item.ItemStack; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.buildcraft.IntegrationTable") +@ModOnly("BuildCraft|Core") +public class IntegrationTable { + @ZenMethod + public static void addRecipe(IItemStack output, double energy, IIngredient inputA, IIngredient inputB, @Optional IIntegrationRecipeFunction function) { + MineTweakerAPI.apply(new AddRecipeAction(output, energy, inputA, inputB, function)); + } + + @ZenMethod + public static void remove(IIngredient output) { + removeRecipe(output, null, null); + } + + @ZenMethod + public static void removeRecipe(IIngredient output, @Optional IIngredient inputA, @Optional IIngredient inputB) { + List toRemove = new ArrayList(); + + outer: for (IIntegrationRecipe recipe : BuildcraftRecipes.integrationTable.getRecipes()) { + for (ItemStack component : recipe.getComponents()) { + if (!output.matches(MineTweakerMC.getIItemStack(component))) + continue outer; + + if (inputA != null) { + for (ItemStack example1 : recipe.getExampleInputsA()) { + if (!inputA.matches(MineTweakerMC.getIItemStack(example1))) { + continue outer; + } + } + } + + if (inputB != null) { + for (ItemStack example2 : recipe.getExampleInputsB()) { + if (!inputB.matches(MineTweakerMC.getIItemStack(example2))) { + continue outer; + } + } + } + + toRemove.add(recipe); + } + } + + for (IIntegrationRecipe recipe : toRemove) { + MineTweakerAPI.apply(new RemoveRecipeAction(recipe)); + } + } + + // ###################### + // ### Action Classes ### + // ###################### + + private static class AddRecipeAction implements IUndoableAction { + private final MTIntegrationRecipe recipe; + + public AddRecipeAction(IItemStack output, double energy, IIngredient inputA, IIngredient inputB, IIntegrationRecipeFunction function) { + recipe = new MTIntegrationRecipe(output, energy, inputA, inputB, function); + } + + @Override + public void apply() { + BuildcraftRecipes.integrationTable.addRecipe(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + BuildcraftRecipes.integrationTable.getRecipes().remove(recipe); + } + + @Override + public String describe() { + return "Adding integration table recipe for " + recipe.output; + } + + @Override + public String describeUndo() { + return "Removing integration table recipe for " + recipe.output; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveRecipeAction implements IUndoableAction { + private final IIntegrationRecipe recipe; + + public RemoveRecipeAction(IIntegrationRecipe recipe) { + this.recipe = recipe; + } + + @Override + public void apply() { + BuildcraftRecipes.integrationTable.getRecipes().remove(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + BuildcraftRecipes.integrationTable.addRecipe(recipe); + } + + @Override + public String describe() { + return "Removing integration table recipe for " + MineTweakerMC.getIItemStack(recipe.getComponents()[0]); + } + + @Override + public String describeUndo() { + return "Restoring integration table recipe for " + MineTweakerMC.getIItemStack(recipe.getComponents()[0]); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class MTIntegrationRecipe implements IIntegrationRecipe { + private final IItemStack output; + private final ItemStack[] components; + private final double energy; + private final IIngredient inputA; + private final ItemStack[] inputAExamples; + private final IIngredient inputB; + private final ItemStack[] inputBExamples; + private final IIntegrationRecipeFunction function; + + private MTIntegrationRecipe(IItemStack output, double energy, IIngredient inputA, IIngredient inputB, IIntegrationRecipeFunction function) { + this.output = output; + this.components = new ItemStack[] { MineTweakerMC.getItemStack(output) }; + this.energy = energy; + this.inputA = inputA; + this.inputAExamples = MineTweakerMC.getExamples(inputA); + this.inputB = inputB; + this.inputBExamples = MineTweakerMC.getExamples(inputB); + this.function = function; + } + + @Override + public double getEnergyCost() { + return energy; + } + + @Override + public boolean isValidInputA(ItemStack is) { + return inputA.matches(MineTweakerMC.getIItemStack(is)); + } + + @Override + public boolean isValidInputB(ItemStack is) { + return inputB.matches(MineTweakerMC.getIItemStack(is)); + } + + @Override + public ItemStack getOutputForInputs(ItemStack is, ItemStack is1, ItemStack[] iss) { + if (function != null) { + IItemStack actualInputA = MineTweakerMC.getIItemStack(is); + IItemStack actualInputB = MineTweakerMC.getIItemStack(is1); + return MineTweakerMC.getItemStack(function.recipe(output, actualInputA, actualInputB)); + } else { + return MineTweakerMC.getItemStack(output); + } + } + + @Override + public ItemStack[] getComponents() { + return components; + } + + @Override + public ItemStack[] getExampleInputsA() { + return inputAExamples; + } + + @Override + public ItemStack[] getExampleInputsB() { + return inputBExamples; + } + } +} diff --git a/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Refinery.java b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Refinery.java new file mode 100644 index 0000000..9092371 --- /dev/null +++ b/MineTweaker3-MC172-Mod-Buildcraft/src/main/java/minetweaker/mods/buildcraft/Refinery.java @@ -0,0 +1,202 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mods.buildcraft; + +import buildcraft.api.recipes.BuildcraftRecipes; +import buildcraft.core.recipes.RefineryRecipeManager; +import buildcraft.core.recipes.RefineryRecipeManager.RefineryRecipe; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.SortedSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.buildcraft.Refinery") +@ModOnly("BuildCraft|Core") +public class Refinery { + private static final Constructor CONSTRUCT_REFINERYRECIPE; + private static final Field REFINERYRECIPEMANAGER_RECIPES; + + static { + Constructor constructor = null; + try { + constructor = RefineryRecipe.class.getDeclaredConstructor(FluidStack.class, FluidStack.class, FluidStack.class, int.class, int.class); + constructor.setAccessible(true); + } catch (NoSuchMethodException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } + + Field recipes = null; + try { + recipes = RefineryRecipeManager.class.getDeclaredField("recipes"); + recipes.setAccessible(true); + } catch (NoSuchFieldException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } + + CONSTRUCT_REFINERYRECIPE = constructor; + REFINERYRECIPEMANAGER_RECIPES = recipes; + } + + + @ZenMethod + public static void addRecipe(ILiquidStack output, int energyPerMB, int ticksPerMB, ILiquidStack input1, @Optional ILiquidStack input2) { + MineTweakerAPI.apply(new AddRecipeAction(output, energyPerMB, ticksPerMB, input1, input2)); + } + + @ZenMethod + public static void remove(ILiquidStack output) { + Fluid fluid = MineTweakerMC.getLiquidStack(output).getFluid(); + + List toRemove = new ArrayList(); + for (RefineryRecipe recipe : ((RefineryRecipeManager) BuildcraftRecipes.refinery).getRecipes()) { + if (recipe.getResult().getFluid() == fluid) { + toRemove.add(recipe); + } + } + + for (RefineryRecipe recipe : toRemove) { + MineTweakerAPI.apply(new RemoveRecipeAction(recipe)); + } + } + + private static SortedSet getRecipes() { + try { + return (SortedSet) REFINERYRECIPEMANAGER_RECIPES.get((RefineryRecipeManager) BuildcraftRecipes.refinery); + } catch (IllegalArgumentException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } + + throw new RuntimeException("Refinery recipes unavailable"); + } + + // ###################### + // ### Action Classes ### + // ###################### + + private static class AddRecipeAction implements IUndoableAction { + private final ILiquidStack output; + private final RefineryRecipe recipe; + + public AddRecipeAction(ILiquidStack output, int energyPerMB, int ticksPerMB, ILiquidStack input1, ILiquidStack input2) { + this.output = output; + + RefineryRecipe rrecipe = null; + try { + rrecipe = (RefineryRecipe) CONSTRUCT_REFINERYRECIPE.newInstance( + MineTweakerMC.getLiquidStack(input1), + MineTweakerMC.getLiquidStack(input2), + MineTweakerMC.getLiquidStack(output), + energyPerMB, + ticksPerMB); + } catch (InstantiationException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalAccessException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (IllegalArgumentException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } catch (InvocationTargetException ex) { + Logger.getLogger(Refinery.class.getName()).log(Level.SEVERE, null, ex); + } + + recipe = rrecipe; + } + + @Override + public void apply() { + getRecipes().add(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + getRecipes().add(recipe); + } + + @Override + public String describe() { + return "Adding refinery recipe for " + output; + } + + @Override + public String describeUndo() { + return "Removing refinery recipe for " + output; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveRecipeAction implements IUndoableAction { + private final RefineryRecipe recipe; + + public RemoveRecipeAction(RefineryRecipe recipe) { + this.recipe = recipe; + } + + @Override + public void apply() { + getRecipes().remove(recipe); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + getRecipes().add(recipe); + } + + @Override + public String describe() { + return "Removing refinery recipe for " + + recipe.getResult().getFluid().getLocalizedName(); + } + + @Override + public String describeUndo() { + return "Restoring refinery recipe for " + + recipe.getResult().getFluid().getLocalizedName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/ZenScript/src/main/java/stanhebben/zenscript/TypeExpansion.java b/ZenScript/src/main/java/stanhebben/zenscript/TypeExpansion.java index 22108a5..28a4e80 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/TypeExpansion.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/TypeExpansion.java @@ -107,7 +107,7 @@ public class TypeExpansion { switch (operatorAnnotation.value()) { case NEG: case NOT: - if (method.getParameterTypes().length != 0) { + if (method.getParameterTypes().length != 1) { // TODO: error } else { unaryOperators.add(new ZenNativeOperator( @@ -128,8 +128,12 @@ public class TypeExpansion { case RANGE: case CONTAINS: case COMPARE: - if (method.getParameterTypes().length != 1) { - // TODO: error + if (method.getParameterTypes().length != 2) { + throw new RuntimeException( + "Binary operator expansion needs a static method with 2 arguments - " + + cls.getName() + + "." + + method.getName()); } else { binaryOperators.add(new ZenNativeOperator( operatorAnnotation.value(), @@ -137,7 +141,7 @@ public class TypeExpansion { } break; case INDEXSET: - if (method.getParameterTypes().length != 2) { + if (method.getParameterTypes().length != 3) { // TODO: error } else { trinaryOperators.add(new ZenNativeOperator( diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeString.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeString.java index 8597b21..f2ed3fa 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeString.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeString.java @@ -207,10 +207,20 @@ public class ZenTypeString extends ZenType { ((ExpressionStringConcat) left).add(right.cast(position, environment, this)); return left; } else { - List values = new ArrayList(); - values.add(left); - values.add(right.cast(position, environment, this)); - return new ExpressionStringConcat(position, values); + if (right.getType().canCastImplicit(STRING, environment)) { + List values = new ArrayList(); + values.add(left); + values.add(right.cast(position, environment, this)); + return new ExpressionStringConcat(position, values); + } else { + Expression expanded = this.binaryExpansion(position, environment, left, right, operator); + if (expanded == null) { + environment.error(position, "cannot add " + right.getType().getName() + " to a string"); + return new ExpressionInvalid(position, this); + } else { + return expanded; + } + } } } else if (operator == OperatorType.INDEXGET) { return new ExpressionStringIndex(position, left, right.cast(position, environment, INT)); diff --git a/configuration.gradle b/configuration.gradle index 7b4459e..c90a78f 100644 --- a/configuration.gradle +++ b/configuration.gradle @@ -16,7 +16,8 @@ ext.projects164 = [ 'MineTweaker3-MC164-Mod-IC2', 'MineTweaker3-MC164-Mod-NEI', 'MineTweaker3-MC164-Mod-MFR', - 'MineTweaker3-MC164-Mod-GregTech' + 'MineTweaker3-MC164-Mod-GregTech', + 'MineTweaker3-MC164-Mod-Buildcraft' ] // ###################### @@ -28,7 +29,8 @@ ext.projects172 = [ 'MineTweaker3-MC172-Main', 'MineTweaker3-MC172-Mod-IC2', 'MineTweaker3-MC172-Mod-NEI', - 'MineTweaker3-MC172-Mod-GregTech' + 'MineTweaker3-MC172-Mod-GregTech', + 'MineTweaker3-MC172-Mod-Buildcraft' ] // #######################