diff --git a/MineTweaker3-API/src/main/java/minetweaker/MineTweakerImplementationAPI.java b/MineTweaker3-API/src/main/java/minetweaker/MineTweakerImplementationAPI.java index a442b9d..fb77b4c 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/MineTweakerImplementationAPI.java +++ b/MineTweaker3-API/src/main/java/minetweaker/MineTweakerImplementationAPI.java @@ -5,12 +5,19 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import static minetweaker.MineTweakerAPI.server; +import minetweaker.api.block.IBlock; +import minetweaker.api.data.IData; +import minetweaker.api.event.IEventHandle; +import minetweaker.api.event.IPlayerInteractEventHandler; import minetweaker.api.event.IPlayerLoggedInEventHandler; import minetweaker.api.event.IPlayerLoggedOutEventHandler; import minetweaker.api.event.MTEventManager; +import minetweaker.api.event.PlayerInteractEvent; import minetweaker.api.event.PlayerLoggedInEvent; import minetweaker.api.event.PlayerLoggedOutEvent; import minetweaker.api.game.IGame; @@ -36,11 +43,16 @@ import minetweaker.runtime.IScriptProvider; * @author Stan Hebben */ public class MineTweakerImplementationAPI { + private static Set blockInfoPlayers = new HashSet(); + private static IEventHandle blockEventHandler = null; + private static final Map minetweakerCommands; + private static final Comparator ITEM_COMPARATOR = new ItemComparator(); private static final Comparator LIQUID_COMPARATOR = new LiquidComparator(); private static final ListenPlayerLoggedIn LISTEN_LOGIN = new ListenPlayerLoggedIn(); private static final ListenPlayerLoggedOut LISTEN_LOGOUT = new ListenPlayerLoggedOut(); + private static final ListenBlockInfo LISTEN_BLOCK_INFO = new ListenBlockInfo(); static { minetweakerCommands = new HashMap(); @@ -261,6 +273,32 @@ public class MineTweakerImplementationAPI { } })); + minetweakerCommands.put("blockinfo", new MineTweakerCommand( + "blockinfo", + new String[] { + "/minetweaker blockinfo", + " Activates or deactivates block reader. In block info mode,", + " right-click a block to see ID, meta and tile entity data" + }, new ICommandFunction() { + @Override + public void execute(String[] arguments, IPlayer player) { + if (blockInfoPlayers.isEmpty()) { + blockEventHandler = events.onPlayerInteract(LISTEN_BLOCK_INFO); + } + + if (blockInfoPlayers.contains(player)) { + blockInfoPlayers.remove(player); + player.sendChat(platform.getMessage("Block info mode deactivated.")); + } else { + blockInfoPlayers.add(player); + player.sendChat(platform.getMessage("Block info mode activated. Right-click a block to see its data.")); + } + + if (blockInfoPlayers.isEmpty()) { + blockEventHandler.close(); + } + } + })); } /** @@ -331,6 +369,8 @@ public class MineTweakerImplementationAPI { * provider in order to reload scripts. */ public static void reload() { + blockInfoPlayers.clear(); + logger.clear(); events.clear(); @@ -477,4 +517,19 @@ public class MineTweakerImplementationAPI { logger.removePlayer(event.getPlayer()); } } + + private static class ListenBlockInfo implements IPlayerInteractEventHandler { + @Override + public void handle(PlayerInteractEvent event) { + if (blockInfoPlayers.contains(event.getPlayer())) { + IBlock block = event.getBlock(); + event.getPlayer().sendChat(platform.getMessage("Block ID: " + block.getDefinition().getId())); + event.getPlayer().sendChat(platform.getMessage("Meta value: " + block.getMeta())); + IData data = block.getTileData(); + if (data != null) { + event.getPlayer().sendChat(platform.getMessage("Tile entity data: " + data.asString())); + } + } + } + } } diff --git a/MineTweaker3-API/src/main/java/minetweaker/annotations/OnRegister.java b/MineTweaker3-API/src/main/java/minetweaker/annotations/OnRegister.java new file mode 100644 index 0000000..cbb9795 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/annotations/OnRegister.java @@ -0,0 +1,22 @@ +/* + * 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.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + * @author Stan + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface OnRegister { + +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/block/BlockPatternOr.java b/MineTweaker3-API/src/main/java/minetweaker/api/block/BlockPatternOr.java new file mode 100644 index 0000000..e50f187 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/api/block/BlockPatternOr.java @@ -0,0 +1,68 @@ +/* + * 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.api.block; + +import java.util.ArrayList; +import java.util.List; +import minetweaker.util.ArrayUtil; + +/** + * + * @author Stan + */ +public class BlockPatternOr implements IBlockPattern { + private final IBlockPattern[] elements; + + public BlockPatternOr(IBlockPattern[] elements) { + this.elements = elements; + } + + public BlockPatternOr(IBlockPattern a, IBlockPattern b) { + this.elements = new IBlockPattern[] {a, b}; + } + + @Override + public List getBlocks() { + List blocks = new ArrayList(); + for (IBlockPattern pattern : elements) { + blocks.addAll(pattern.getBlocks()); + } + return blocks; + } + + @Override + public boolean matches(IBlock block) { + for (IBlockPattern pattern : elements) { + if (pattern.matches(block)) + return true; + } + + return false; + } + + @Override + public String getDisplayName() { + StringBuilder result = new StringBuilder(); + boolean first = true; + for (IBlockPattern pattern : elements) { + if (first) { + first = false; + } else { + result.append(" | "); + } + + result.append(pattern.getDisplayName()); + } + + return result.toString(); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(ArrayUtil.append(elements, pattern)); + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlock.java b/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlock.java index 1447026..938277f 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlock.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlock.java @@ -1,5 +1,6 @@ package minetweaker.api.block; +import minetweaker.api.data.IData; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenGetter; @@ -9,7 +10,7 @@ import stanhebben.zenscript.annotations.ZenGetter; * @author Stan Hebben */ @ZenClass("minetweaker.block.IBlock") -public interface IBlock { +public interface IBlock extends IBlockPattern { /** * Gets the block definition. * @@ -17,4 +18,10 @@ public interface IBlock { */ @ZenGetter("definition") public IBlockDefinition getDefinition(); + + @ZenGetter("meta") + public int getMeta(); + + @ZenGetter("data") + public IData getTileData(); } diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlockDefinition.java b/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlockDefinition.java index 61afe7a..6a76b01 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlockDefinition.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlockDefinition.java @@ -1,6 +1,7 @@ package minetweaker.api.block; import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenGetter; /** * Blocks definitions provide additional information about blocks. @@ -9,5 +10,6 @@ import stanhebben.zenscript.annotations.ZenClass; */ @ZenClass("minetweaker.block.IBlockDefinition") public interface IBlockDefinition { - + @ZenGetter("id") + public String getId(); } diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlockPattern.java b/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlockPattern.java new file mode 100644 index 0000000..41af7b1 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/api/block/IBlockPattern.java @@ -0,0 +1,34 @@ +/* + * 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.api.block; + +import java.util.List; +import stanhebben.zenscript.annotations.OperatorType; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenGetter; +import stanhebben.zenscript.annotations.ZenMethod; +import stanhebben.zenscript.annotations.ZenOperator; + +/** + * + * @author Stan + */ +@ZenClass("minetweaker.block.IBlockPattern") +public interface IBlockPattern { + @ZenMethod("blocks") + public List getBlocks(); + + @ZenOperator(OperatorType.CONTAINS) + public boolean matches(IBlock block); + + @ZenOperator(OperatorType.OR) + public IBlockPattern or(IBlockPattern pattern); + + @ZenGetter("displayName") + public String getDisplayName(); + +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/data/DataMap.java b/MineTweaker3-API/src/main/java/minetweaker/api/data/DataMap.java index 14c5e14..ea74800 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/data/DataMap.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/data/DataMap.java @@ -137,7 +137,13 @@ public class DataMap implements IData { } else { result.append(", "); } - result.append(entry.getKey()); + + if (isValidIdentifier(entry.getKey())) { + result.append(entry.getKey()); + } else { + result.append("\"").append(entry.getKey()).append("\""); + } + result.append(": "); result.append(entry.getValue().toString()); } @@ -275,4 +281,16 @@ public class DataMap implements IData { public String toString() { return asString(); } + + private boolean isValidIdentifier(String str) { + if (!Character.isJavaIdentifierStart(str.charAt(0))) + return false; + + for (int i = 1; i < str.length(); i++) { + if (!Character.isJavaIdentifierPart(str.charAt(i))) + return false; + } + + return true; + } } diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/event/PlayerInteractEvent.java b/MineTweaker3-API/src/main/java/minetweaker/api/event/PlayerInteractEvent.java index 6e706ae..9dcd682 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/event/PlayerInteractEvent.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/event/PlayerInteractEvent.java @@ -7,7 +7,6 @@ package minetweaker.api.event; import minetweaker.api.block.IBlock; -import minetweaker.api.entity.IEntity; import minetweaker.api.player.IPlayer; import minetweaker.api.world.IBlockGroup; import minetweaker.api.world.IDimension; @@ -22,7 +21,6 @@ import stanhebben.zenscript.annotations.ZenMethod; @ZenClass("minetweaker.event.PlayerInteractEvent") public class PlayerInteractEvent { private final IPlayer player; - private final IEntity entity; private final IBlockGroup blocks; private final int x; private final int y; @@ -32,9 +30,8 @@ public class PlayerInteractEvent { private boolean useBlock; private boolean useItem; - public PlayerInteractEvent(IPlayer player, IEntity entity, IBlockGroup blocks, int x, int y, int z) { + public PlayerInteractEvent(IPlayer player, IBlockGroup blocks, int x, int y, int z) { this.player = player; - this.entity = entity; this.blocks = blocks; this.x = x; this.y = y; diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/item/IIngredient.java b/MineTweaker3-API/src/main/java/minetweaker/api/item/IIngredient.java index df888bd..48f5b5b 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/item/IIngredient.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/item/IIngredient.java @@ -60,6 +60,17 @@ public interface IIngredient { @ZenMethod public IIngredient amount(int amount); + /** + * Combines multiple ingredients into a single one. Note that ore dictionary + * entries are preferred to or statements. + * + * @param ingredient ingredient to combine with + * @return or-ed ingredient + */ + @ZenOperator(OperatorType.OR) + @ZenMethod + public IIngredient or(IIngredient ingredient); + /** * Returns a new ingredient with the given transform added to it. * diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/item/IItemStack.java b/MineTweaker3-API/src/main/java/minetweaker/api/item/IItemStack.java index a4d55c7..2a51b0c 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/item/IItemStack.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/item/IItemStack.java @@ -1,8 +1,10 @@ package minetweaker.api.item; +import minetweaker.api.block.IBlock; import minetweaker.api.data.IData; import minetweaker.api.liquid.ILiquidStack; import stanhebben.zenscript.annotations.OperatorType; +import stanhebben.zenscript.annotations.ZenCaster; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenGetter; import stanhebben.zenscript.annotations.ZenMethod; @@ -170,4 +172,12 @@ public interface IItemStack extends IIngredient { */ @ZenMethod public IItemStack updateTag(IData tagUpdate); + + /** + * Converts this item stack into a block. + * + * @return block, or null if this item is not a block + */ + @ZenCaster + public IBlock asBlock(); } diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientAny.java b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientAny.java index 05d869b..f92a6e8 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientAny.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientAny.java @@ -50,6 +50,11 @@ public class IngredientAny implements IIngredient { return new IngredientAnyAdvanced(mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); } + @Override + public IIngredient or(IIngredient ingredient) { + return this; + } + @Override public boolean matches(IItemStack item) { return true; diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientAnyAdvanced.java b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientAnyAdvanced.java index 1adf326..860979f 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientAnyAdvanced.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientAnyAdvanced.java @@ -55,6 +55,11 @@ public class IngredientAnyAdvanced implements IIngredient { return new IngredientAnyAdvanced(mark, conditions, transformers); } + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } + @Override public boolean matches(IItemStack item) { if (!item.matches(item)) return false; diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientItem.java b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientItem.java index 39f3cee..dd75a1a 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientItem.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientItem.java @@ -60,6 +60,11 @@ public class IngredientItem implements IIngredient { return new IngredientItem(item, mark, conditions, transformers); } + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } + @Override public boolean matches(IItemStack item) { if (!this.item.matches(item)) return false; diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientOr.java b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientOr.java new file mode 100644 index 0000000..5b8be93 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientOr.java @@ -0,0 +1,128 @@ +/* + * 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.api.item; + +import java.util.ArrayList; +import java.util.List; +import minetweaker.util.ArrayUtil; + +/** + * + * @author Stan + */ +public class IngredientOr implements IIngredient { + private final IIngredient[] elements; + private final String mark; + private final IItemCondition[] conditions; + private final IItemTransformer[] transformers; + + public IngredientOr(IIngredient[] elements) { + this.elements = elements; + mark = null; + conditions = ArrayUtil.EMPTY_CONDITIONS; + transformers = ArrayUtil.EMPTY_TRANSFORMERS; + } + + public IngredientOr(IIngredient a, IIngredient b) { + this(new IIngredient[] {a, b}); + } + + private IngredientOr(IIngredient[] elements, String mark, IItemCondition[] conditions, IItemTransformer[] transformers) { + this.elements = elements; + this.mark = mark; + this.conditions = conditions; + this.transformers = transformers; + } + + @Override + public String getMark() { + return mark; + } + + @Override + public int getAmount() { + return elements[0].getAmount(); + } + + @Override + public List getItems() { + List result = new ArrayList(); + for (IIngredient element : elements) { + result.addAll(element.getItems()); + } + return result; + } + + @Override + public IIngredient amount(int amount) { + IIngredient[] result = new IIngredient[elements.length]; + for (int i = 0; i < elements.length; i++) { + result[i] = elements[i].amount(amount); + } + return new IngredientOr(result); + } + + @Override + public IIngredient transform(IItemTransformer transformer) { + return new IngredientOr(elements, mark, conditions, ArrayUtil.append(transformers, transformer)); + } + + @Override + public IIngredient only(IItemCondition condition) { + return new IngredientOr(elements, mark, ArrayUtil.append(conditions, condition), transformers); + } + + @Override + public IIngredient marked(String mark) { + return new IngredientOr(elements, mark, conditions, transformers); + } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(ArrayUtil.append(elements, ingredient)); + } + + @Override + public boolean matches(IItemStack item) { + for (IIngredient ingredient : item.getItems()) { + if (ingredient.matches(item)) + return true; + } + + return false; + } + + @Override + public boolean contains(IIngredient ingredient) { + List items = ingredient.getItems(); + for (IItemStack item : items) { + if (!matches(item)) + return false; + } + + return true; + } + + @Override + public IItemStack applyTransform(IItemStack item) { + for (IItemTransformer transformer : transformers) { + item = transformer.transform(item); + } + + return item; + } + + @Override + public boolean hasTransformers() { + return transformers.length > 0; + } + + @Override + public Object getInternal() { + return null; + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientStack.java b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientStack.java index 3e74ae1..92d4d78 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientStack.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/item/IngredientStack.java @@ -52,6 +52,11 @@ public class IngredientStack implements IIngredient { return new IngredientStack(ingredient.marked(mark), amount); } + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } + @Override public boolean matches(IItemStack item) { return item.getAmount() == amount && ingredient.matches(item); diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/item/WeightedItemStack.java b/MineTweaker3-API/src/main/java/minetweaker/api/item/WeightedItemStack.java index cfadac4..a5e6f0a 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/item/WeightedItemStack.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/item/WeightedItemStack.java @@ -1,5 +1,8 @@ package minetweaker.api.item; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenGetter; @@ -11,6 +14,18 @@ import stanhebben.zenscript.annotations.ZenGetter; */ @ZenClass("minetweaker.item.WeightedItemStack") public final class WeightedItemStack { + public static List pickRandomDrops(Random random, WeightedItemStack[] items) { + ArrayList result = new ArrayList(); + + for (WeightedItemStack item : items) { + if (random.nextFloat() <= item.getChance()) { + result.add(item.getStack()); + } + } + + return result; + } + private final IItemStack stack; private final float p; @@ -37,6 +52,7 @@ public final class WeightedItemStack { // ############################# // ### Object implementation ### // ############################# + @Override public int hashCode() { int hash = 7; diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/liquid/WeightedLiquidStack.java b/MineTweaker3-API/src/main/java/minetweaker/api/liquid/WeightedLiquidStack.java new file mode 100644 index 0000000..871c9f5 --- /dev/null +++ b/MineTweaker3-API/src/main/java/minetweaker/api/liquid/WeightedLiquidStack.java @@ -0,0 +1,81 @@ +package minetweaker.api.liquid; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenGetter; + +/** + * Contains a weighted item stack. Weighted item stacks simply contain a stack + * and a weight. + * + * @author Stan Hebben + */ +@ZenClass("minetweaker.item.WeightedItemStack") +public final class WeightedLiquidStack { + public static List pickRandomDrops(Random random, WeightedLiquidStack[] items) { + ArrayList result = new ArrayList(); + + for (WeightedLiquidStack item : items) { + if (random.nextFloat() <= item.getChance()) { + result.add(item.getStack()); + } + } + + return result; + } + + private final ILiquidStack stack; + private final float p; + + public WeightedLiquidStack(ILiquidStack stack, float p) { + this.stack = stack; + this.p = p; + } + + @ZenGetter("stack") + public ILiquidStack getStack() { + return stack; + } + + @ZenGetter("chance") + public float getChance() { + return p; + } + + @ZenGetter("percent") + public float getPercent() { + return p * 100; + } + + // ############################# + // ### Object implementation ### + // ############################# + + @Override + public int hashCode() { + int hash = 17; + hash = 29 * hash + (this.stack != null ? this.stack.hashCode() : 0); + hash = 29 * hash + Float.floatToIntBits(this.p); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final WeightedLiquidStack other = (WeightedLiquidStack) obj; + if (this.stack != other.stack && (this.stack == null || !this.stack.equals(other.stack))) { + return false; + } + if (Float.floatToIntBits(this.p) != Float.floatToIntBits(other.p)) { + return false; + } + return true; + } +} diff --git a/MineTweaker3-API/src/main/java/minetweaker/api/oredict/IngredientOreDict.java b/MineTweaker3-API/src/main/java/minetweaker/api/oredict/IngredientOreDict.java index 243b408..093b2bc 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/api/oredict/IngredientOreDict.java +++ b/MineTweaker3-API/src/main/java/minetweaker/api/oredict/IngredientOreDict.java @@ -11,6 +11,7 @@ import minetweaker.api.item.IIngredient; import minetweaker.api.item.IItemCondition; import minetweaker.api.item.IItemStack; import minetweaker.api.item.IItemTransformer; +import minetweaker.api.item.IngredientOr; import minetweaker.api.item.IngredientStack; import minetweaker.util.ArrayUtil; @@ -70,6 +71,11 @@ public class IngredientOreDict implements IIngredient { return new IngredientOreDict(entry, mark, conditions, transformers); } + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } + @Override public boolean matches(IItemStack item) { if (!entry.matches(item)) return false; diff --git a/MineTweaker3-API/src/main/java/minetweaker/util/ArrayUtil.java b/MineTweaker3-API/src/main/java/minetweaker/util/ArrayUtil.java index 41c0b4f..ea2f742 100644 --- a/MineTweaker3-API/src/main/java/minetweaker/util/ArrayUtil.java +++ b/MineTweaker3-API/src/main/java/minetweaker/util/ArrayUtil.java @@ -7,6 +7,8 @@ package minetweaker.util; import java.util.Arrays; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.item.IIngredient; import minetweaker.api.item.IItemCondition; import minetweaker.api.item.IItemTransformer; @@ -29,4 +31,16 @@ public class ArrayUtil { result[values.length] = value; return result; } + + public static IIngredient[] append(IIngredient[] values, IIngredient value) { + IIngredient[] result = Arrays.copyOf(values, values.length + 1); + result[values.length] = value; + return result; + } + + public static IBlockPattern[] append(IBlockPattern[] values, IBlockPattern value) { + IBlockPattern[] result = Arrays.copyOf(values, values.length + 1); + result[values.length] = value; + return result; + } } 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 5dfd261..ae174c0 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 @@ -1,21 +1,35 @@ package minetweaker.api.minecraft; +import java.util.HashMap; import java.util.List; +import java.util.Map; import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; import minetweaker.api.data.IData; import minetweaker.api.item.IIngredient; import minetweaker.api.item.IItemStack; +import minetweaker.api.liquid.ILiquidStack; import minetweaker.api.oredict.IOreDictEntry; import minetweaker.api.player.IPlayer; +import minetweaker.api.world.IDimension; +import minetweaker.mc164.block.MCBlockDefinition; +import minetweaker.mc164.block.MCSpecificBlock; +import minetweaker.mc164.block.MCWorldBlock; import minetweaker.mc164.data.NBTConverter; import minetweaker.mc164.item.MCItemStack; import minetweaker.mc164.oredict.MCOreDictEntry; import minetweaker.mc164.player.MCPlayer; +import minetweaker.mc164.world.MCDimension; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.OreDictionary; /** @@ -24,6 +38,8 @@ import net.minecraftforge.oredict.OreDictionary; * @author Stan Hebben */ public class MineTweakerMC { + private static final Map blockDefinitions = new HashMap(); + private MineTweakerMC() {} /** @@ -286,4 +302,91 @@ public class MineTweakerMC { return (NBTTagCompound) NBTConverter.from(data); } + + /** + * Retrieves the block at the given position. + * + * @param blocks block access + * @param x block x position + * @param y block y position + * @param z block z position + * @return block instance + */ + public static IBlock getBlock(IBlockAccess blocks, int x, int y, int z) { + return new MCWorldBlock(blocks, x, y, z); + } + + /** + * Retrieves the block definition for the given block. + * + * @param block block object + * @return block definition + */ + public static IBlockDefinition getBlockDefinition(Block block) { + if (!blockDefinitions.containsKey(block)) { + blockDefinitions.put(block, new MCBlockDefinition(block)); + } + return blockDefinitions.get(block); + } + + /** + * Retrieves the dimension instance for a given world. + * + * @param world world + * @return dimension + */ + public static IDimension getDimension(World world) { + if (world == null) return null; + + return new MCDimension(world); + } + + /** + * Returns an instance of the given block. + * + * @param block MC block definition + * @return MT block instance + */ + public static IBlock getBlockAnyMeta(Block block) { + return new MCSpecificBlock(block, OreDictionary.WILDCARD_VALUE); + } + + /** + * Returns an instance of the given block. + * + * @param block MC block definition + * @param meta block meta value + * @return MT block instance + */ + public static IBlock getBlock(Block block, int meta) { + return new MCSpecificBlock(block, meta); + } + + /** + * Retrieves the internal fluid stack of the given stack. + * + * @param stack MT liquid stack + * @return MCF fluid stack + */ + public static FluidStack getLiquidStack(ILiquidStack stack) { + return (FluidStack) stack.getInternal(); + } + + public static int getBlockId(IBlockDefinition blockDefinition) { + if (blockDefinition instanceof MCBlockDefinition) { + return ((MCBlockDefinition) blockDefinition).getInternalId(); + } else { + throw new IllegalArgumentException("block definition is not generated by MineTweaker"); + } + } + + public static ItemStack toItemStack(IBlock block) { + int mcBlockId = getBlockId(block.getDefinition()); + ItemStack result = new ItemStack(mcBlockId, 1, block.getMeta()); + IData data = block.getTileData(); + if (data != null) { + result.setTagCompound(MineTweakerMC.getNBTCompound(data)); + } + return result; + } } 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 43ccd58..08740dd 100644 --- a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/MineTweakerMod.java @@ -58,7 +58,8 @@ 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.mfr.ClassRegistry" }; @Mod.Instance(MODID) diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCBlockDefinition.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCBlockDefinition.java new file mode 100644 index 0000000..3ae613f --- /dev/null +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCBlockDefinition.java @@ -0,0 +1,35 @@ +/* + * 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.mc164.block; + +import minetweaker.api.block.IBlockDefinition; +import net.minecraft.block.Block; + +/** + * + * @author Stan + */ +public class MCBlockDefinition implements IBlockDefinition { + private final Block block; + + public MCBlockDefinition(Block block) { + this.block = block; + } + + public Block getInternalBlock() { + return block; + } + + public int getInternalId() { + return block.blockID; + } + + @Override + public String getId() { + return block.getUnlocalizedName(); + } +} diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCItemBlock.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCItemBlock.java new file mode 100644 index 0000000..3a762fc --- /dev/null +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCItemBlock.java @@ -0,0 +1,71 @@ +/* + * 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.mc164.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCItemBlock implements IBlock { + private final ItemStack item; + + public MCItemBlock(ItemStack item) { + this.item = item; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(Block.blocksList[item.itemID]); + } + + @Override + public int getMeta() { + return item.getItemDamage(); + } + + @Override + public IData getTileData() { + if (item.stackTagCompound == null) + return null; + + return MineTweakerMC.getIData(item.stackTagCompound); + } + + @Override + public String getDisplayName() { + return item.getDisplayName(); + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return getDefinition() == block.getDefinition() + && (getMeta() == OreDictionary.WILDCARD_VALUE || getMeta() == block.getMeta()) + && (getTileData() == null || (block.getTileData() != null && block.getTileData().contains(getTileData()))); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } +} diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCSpecificBlock.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCSpecificBlock.java new file mode 100644 index 0000000..e0ac7e9 --- /dev/null +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCSpecificBlock.java @@ -0,0 +1,68 @@ +/* + * 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.mc164.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCSpecificBlock implements IBlock { + private final Block block; + private final int meta; + + public MCSpecificBlock(Block block, int meta) { + this.block = block; + this.meta = meta; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(block); + } + + @Override + public int getMeta() { + return meta; + } + + @Override + public IData getTileData() { + return null; + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return block.getDefinition() == getDefinition() + && (meta == OreDictionary.WILDCARD_VALUE || block.getMeta() == meta); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } + + @Override + public String getDisplayName() { + return block.getLocalizedName(); + } +} diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCWorldBlock.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCWorldBlock.java new file mode 100644 index 0000000..085a299 --- /dev/null +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/block/MCWorldBlock.java @@ -0,0 +1,90 @@ +/* + * 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.mc164.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCWorldBlock implements IBlock { + private final IBlockAccess blocks; + private final int x; + private final int y; + private final int z; + + public MCWorldBlock(IBlockAccess blocks, int x, int y, int z) { + this.blocks = blocks; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(Block.blocksList[blocks.getBlockId(x, y, z)]); + } + + @Override + public int getMeta() { + return blocks.getBlockMetadata(x, y, z); + } + + @Override + public IData getTileData() { + TileEntity tileEntity = blocks.getBlockTileEntity(x, y, z); + + if (tileEntity == null) + return null; + + NBTTagCompound nbt = new NBTTagCompound(); + tileEntity.writeToNBT(nbt); + return MineTweakerMC.getIData(nbt); + } + + @Override + public String getDisplayName() { + int blockId = blocks.getBlockId(x, y, z); + if (Item.itemsList[blockId] != null) { + return (new ItemStack(blockId, 1, getMeta())).getDisplayName(); + } else { + return Block.blocksList[blockId].getLocalizedName(); + } + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return getDefinition() == block.getDefinition() + && (getMeta() == OreDictionary.WILDCARD_VALUE || getMeta() == block.getMeta()) + && (getTileData() == null || (block.getTileData() != null && block.getTileData().contains(getTileData()))); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } +} diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/game/MCGame.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/game/MCGame.java index 28f0eec..1f22265 100644 --- a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/game/MCGame.java +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/game/MCGame.java @@ -26,7 +26,7 @@ public class MCGame implements IGame { public static final MCGame INSTANCE = new MCGame(); private MCGame() {} - + @Override public List getItems() { List result = new ArrayList(); diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/item/MCItemStack.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/item/MCItemStack.java index e89c8a5..c1f73d4 100644 --- a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/item/MCItemStack.java +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/item/MCItemStack.java @@ -9,6 +9,7 @@ package minetweaker.mc164.item; import java.util.Collections; import java.util.List; import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlock; import minetweaker.api.data.DataMap; import minetweaker.mc164.data.NBTConverter; import minetweaker.mc164.liquid.MCLiquidStack; @@ -19,11 +20,14 @@ import minetweaker.api.item.IItemDefinition; import minetweaker.api.item.IItemStack; import minetweaker.api.item.IItemTransformer; import minetweaker.api.item.IngredientItem; +import minetweaker.api.item.IngredientOr; import minetweaker.api.item.WeightedItemStack; import minetweaker.api.liquid.ILiquidStack; import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; import minetweaker.mc164.actions.SetTranslationAction; +import minetweaker.mc164.block.MCItemBlock; import minetweaker.util.ArrayUtil; +import net.minecraft.block.Block; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidContainerRegistry; @@ -209,6 +213,11 @@ public class MCItemStack implements IItemStack { public IIngredient marked(String mark) { return new IngredientItem(this, mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } @Override public boolean matches(IItemStack item) { @@ -218,7 +227,7 @@ public class MCItemStack implements IItemStack { } return internal.getItem() == stack.getItem() - && (wildcardSize || internal.stackSize == stack.stackSize) + && (wildcardSize || internal.stackSize >= stack.stackSize) && (stack.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack.getItemDamage() == internal.getItemDamage() || (!stack.getHasSubtypes() && !stack.getItem().isDamageable())); @@ -241,6 +250,15 @@ public class MCItemStack implements IItemStack { return false; } + @Override + public IBlock asBlock() { + if (stack.itemID >= Block.blocksList.length || Block.blocksList[stack.itemID] == null) { + throw new ClassCastException("This item is not a block"); + } else { + return new MCItemBlock(stack); + } + } + @Override public Object getInternal() { return stack; diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/oredict/MCOreDictEntry.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/oredict/MCOreDictEntry.java index 2eabef5..59aa10e 100644 --- a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/oredict/MCOreDictEntry.java +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/oredict/MCOreDictEntry.java @@ -15,6 +15,7 @@ import minetweaker.api.item.IIngredient; import minetweaker.api.item.IItemCondition; import minetweaker.api.item.IItemStack; import minetweaker.api.item.IItemTransformer; +import minetweaker.api.item.IngredientOr; import minetweaker.api.item.IngredientStack; import static minetweaker.api.minecraft.MineTweakerMC.getIItemStackWildcardSize; import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; @@ -145,6 +146,11 @@ public class MCOreDictEntry implements IOreDictEntry { public IIngredient marked(String mark) { return new IngredientOreDict(this, mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } @Override public boolean matches(IItemStack item) { diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/util/MineTweakerHacks.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/util/MineTweakerHacks.java index b343faa..c7a2223 100644 --- a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/util/MineTweakerHacks.java +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/util/MineTweakerHacks.java @@ -159,6 +159,22 @@ public class MineTweakerHacks { } } + public static T getPrivateStaticObject(Class cls, String name) { + try { + Field field = cls.getDeclaredField(name); + field.setAccessible(true); + return (T) field.get(null); + } catch (NoSuchFieldException ex) { + + } catch (SecurityException ex) { + + } catch (IllegalAccessException ex) { + + } + + return null; + } + // ####################### // ### Private Methods ### // ####################### diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/util/MineTweakerPlatformUtils.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/util/MineTweakerPlatformUtils.java new file mode 100644 index 0000000..be92d90 --- /dev/null +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/util/MineTweakerPlatformUtils.java @@ -0,0 +1,29 @@ +/* + * 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.mc164.util; + +import net.minecraft.entity.EntityLivingBase; + +/** + * + * @author Stan + */ +public class MineTweakerPlatformUtils { + private MineTweakerPlatformUtils() {} + + public static Class getLivingEntityClass(String entityClassName) { + try { + Class entityClass = Class.forName(entityClassName); + if (!EntityLivingBase.class.isAssignableFrom(entityClass)) { + throw new RuntimeException("Not an entity class: " + entityClassName); + } + return (Class) entityClass; + } catch (ClassNotFoundException ex) { + throw new RuntimeException("entity class not found: " + entityClassName); + } + } +} diff --git a/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/world/MCDimension.java b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/world/MCDimension.java new file mode 100644 index 0000000..2a2055b --- /dev/null +++ b/MineTweaker3-MC164-Main/src/main/java/minetweaker/mc164/world/MCDimension.java @@ -0,0 +1,44 @@ +/* + * 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.mc164.world; + +import minetweaker.api.block.IBlock; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.world.IDimension; +import net.minecraft.world.World; + +/** + * + * @author Stan + */ +public class MCDimension implements IDimension { + private final World world; + + public MCDimension(World world) { + this.world = world; + } + + @Override + public boolean isDay() { + return world.isDaytime(); + } + + @Override + public int getBrightness(int x, int y, int z) { + return world.getBlockLightValue(x, y, z); + } + + @Override + public IDimension getDimension() { + return this; + } + + @Override + public IBlock getBlock(int x, int y, int z) { + return MineTweakerMC.getBlock(world, x, y, z); + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/build.gradle b/MineTweaker3-MC164-Mod-MFR/build.gradle new file mode 100644 index 0000000..1b2c1e1 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/build.gradle @@ -0,0 +1,38 @@ +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 = "1.6.4-9.11.1.964"} +version = "1.0" +archivesBaseName = project.projectDir.name + +dependencies { + compile project(':ZenScript') + compile project(':MineTweaker3-API') + compile project(':MineTweaker3-MC164-Main') + compile files('libs/MineFactoryReloaded-2.7.9-final.jar', 'libs/PowerCrystalsCore-1.1.8-9.jar') +} + +task makeRegistry(type: RegisterZenClassesTask) { + inputDir = file('build/classes/main') + outputDir = file('build/classes/main') + className = 'minetweaker.mods.mfr.ClassRegistry' +} + +tasks.jar.dependsOn(makeRegistry) diff --git a/MineTweaker3-MC164-Mod-MFR/libs/MineFactoryReloaded-2.7.9-final.jar b/MineTweaker3-MC164-Mod-MFR/libs/MineFactoryReloaded-2.7.9-final.jar new file mode 100644 index 0000000..0b27a34 Binary files /dev/null and b/MineTweaker3-MC164-Mod-MFR/libs/MineFactoryReloaded-2.7.9-final.jar differ diff --git a/MineTweaker3-MC164-Mod-MFR/libs/PowerCrystalsCore-1.1.8-9.jar b/MineTweaker3-MC164-Mod-MFR/libs/PowerCrystalsCore-1.1.8-9.jar new file mode 100644 index 0000000..163d320 Binary files /dev/null and b/MineTweaker3-MC164-Mod-MFR/libs/PowerCrystalsCore-1.1.8-9.jar differ diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/FertilizableType.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/FertilizableType.java new file mode 100644 index 0000000..0968b36 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/FertilizableType.java @@ -0,0 +1,16 @@ +/* + * 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 stanhebben.minetweaker.mods.mfr; + +/** + * + * @author Stanneke + */ +public enum FertilizableType { + REPLACE, + BONEMEAL +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/MFRHacks.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/MFRHacks.java new file mode 100644 index 0000000..624ac2f --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/MFRHacks.java @@ -0,0 +1,86 @@ +/* + * 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.mfr; + +import java.util.List; +import java.util.Map; +import static minetweaker.mc164.util.MineTweakerHacks.getPrivateStaticObject; +import net.minecraft.item.ItemStack; +import powercrystals.core.random.WeightedRandomItemStack; +import powercrystals.minefactoryreloaded.MFRRegistry; +import powercrystals.minefactoryreloaded.api.IFactoryFertilizable; +import powercrystals.minefactoryreloaded.api.IFactoryFertilizer; +import powercrystals.minefactoryreloaded.api.IFactoryFruit; +import powercrystals.minefactoryreloaded.api.IFactoryGrindable; +import powercrystals.minefactoryreloaded.api.IFactoryHarvestable; +import powercrystals.minefactoryreloaded.api.IFactoryPlantable; +import powercrystals.minefactoryreloaded.api.IFactoryRanchable; +import powercrystals.minefactoryreloaded.api.IMobEggHandler; +import powercrystals.minefactoryreloaded.api.IRandomMobProvider; +import powercrystals.minefactoryreloaded.api.ISafariNetHandler; +import powercrystals.minefactoryreloaded.api.rednet.IRedNetLogicCircuit; + +/** + * + * @author Stanneke + */ +public class MFRHacks { + public static Map plantables = null; + public static Map harvestables = null; + public static Map fertilizers = null; + public static Map fertilizables = null; + public static Map, IFactoryRanchable> ranchables = null; + public static Map, IFactoryGrindable> grindables = null; + public static Map, List> breederFoods = null; + public static List fruitLogBlocks = null; + public static Map fruitBlocks = null; + public static List sludgeDrops = null; + public static List eggHandlers = null; + public static List safariNetHandlers = null; + public static List rubberTreeBiomes = null; + public static List> safariNetBlacklist = null; + public static List randomMobProviders = null; + public static List laserOres = null; + public static List> grindableBlacklist = null; + public static List> autoSpawnerBlacklist = null; + public static List> slaughterhouseBlacklist = null; + public static List> conveyerBlacklist = null; + public static Map> laserPreferredOres = null; + public static List redNetCircuits = null; + + static { + try { + Class registry = MFRRegistry.class; + + plantables = getPrivateStaticObject(registry, "_plantables"); + harvestables = getPrivateStaticObject(registry, "_harvestables"); + fertilizers = getPrivateStaticObject(registry, "_fertilizers"); + fertilizables = getPrivateStaticObject(registry, "_fertilizables"); + ranchables = getPrivateStaticObject(registry, "_ranchables"); + grindables = getPrivateStaticObject(registry, "_grindables"); + breederFoods = getPrivateStaticObject(registry, "_breederFoods"); + fruitLogBlocks = getPrivateStaticObject(registry, "_fruitLogBlocks"); + fruitBlocks = getPrivateStaticObject(registry, "_fruitBlocks"); + sludgeDrops = getPrivateStaticObject(registry, "_sludgeDrops"); + eggHandlers = getPrivateStaticObject(registry, "_eggHandlers"); + safariNetHandlers = getPrivateStaticObject(registry, "_safariNetHandlers"); + rubberTreeBiomes = getPrivateStaticObject(registry, "_rubberTreeBiomes"); + safariNetBlacklist = getPrivateStaticObject(registry, "_safariNetBlacklist"); + randomMobProviders = getPrivateStaticObject(registry, "_randomMobProviders"); + laserOres = getPrivateStaticObject(registry, "_laserOres"); + grindableBlacklist = getPrivateStaticObject(registry, "_grindableBlacklist"); + autoSpawnerBlacklist = getPrivateStaticObject(registry, "_autoSpawnerBlacklist"); + slaughterhouseBlacklist = getPrivateStaticObject(registry, "_slaughterhouseBlacklist"); + conveyerBlacklist = getPrivateStaticObject(registry, "_conveyerBlacklist"); + laserPreferredOres = getPrivateStaticObject(registry, "_laserPreferredOres"); + redNetCircuits = getPrivateStaticObject(registry, "_redNetLogicCircuits"); + } catch (ClassCastException ex) { + } + } + + private MFRHacks() {} +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/PrePlantAction.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/PrePlantAction.java new file mode 100644 index 0000000..0b0ee1e --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/PrePlantAction.java @@ -0,0 +1,16 @@ +/* + * 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 stanhebben.minetweaker.mods.mfr; + +/** + * + * @author Stanneke + */ +public enum PrePlantAction { + NONE, + TILL +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/AutoSpawner.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/AutoSpawner.java new file mode 100644 index 0000000..a731023 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/AutoSpawner.java @@ -0,0 +1,116 @@ +package minetweaker.mods.mfr.machines; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.mods.mfr.MFRHacks; +import static minetweaker.mc164.util.MineTweakerPlatformUtils.getLivingEntityClass; +import net.minecraft.entity.EntityList; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.AutoSpawner") +@ModOnly("MineFactoryReloaded") +public class AutoSpawner { + @ZenMethod + public static void addBlacklist(String entityClassName) { + MineTweakerAPI.apply(new AutoSpawnerAddBlacklistAction(getLivingEntityClass(entityClassName))); + } + + @ZenMethod + public static void removeBlacklist(String entityClassName) { + MineTweakerAPI.apply(new AutoSpawnerRemoveBlacklistAction(getLivingEntityClass(entityClassName))); + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AutoSpawnerAddBlacklistAction implements IUndoableAction { + private final Class entityClass; + private final boolean existed; + + public AutoSpawnerAddBlacklistAction(Class entityClass) { + this.entityClass = entityClass; + existed = MFRHacks.autoSpawnerBlacklist == null ? false : MFRHacks.autoSpawnerBlacklist.contains(entityClass); + } + + @Override + public void apply() { + if (!existed) + FactoryRegistry.registerAutoSpawnerBlacklist((String) EntityList.classToStringMapping.get(entityClass)); + } + + @Override + public boolean canUndo() { + return MFRHacks.autoSpawnerBlacklist != null; + } + + @Override + public void undo() { + if (!existed) + MFRHacks.autoSpawnerBlacklist.remove(entityClass); + } + + @Override + public String describe() { + return "Adding auto-spawner blacklist " + entityClass.getCanonicalName(); + } + + @Override + public String describeUndo() { + return "Removing auto-spawner blacklist " + entityClass.getCanonicalName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AutoSpawnerRemoveBlacklistAction implements IUndoableAction { + private final Class entityClass; + private final boolean existed; + + public AutoSpawnerRemoveBlacklistAction(Class entityClass) { + this.entityClass = entityClass; + existed = MFRHacks.autoSpawnerBlacklist.contains(entityClass); + } + + @Override + public void apply() { + if (existed) + MFRHacks.autoSpawnerBlacklist.remove(entityClass); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + if (existed) MFRHacks.autoSpawnerBlacklist.add(entityClass); + } + + @Override + public String describe() { + return "Removing auto-spawner blacklist " + entityClass.getCanonicalName(); + } + + @Override + public String describeUndo() { + return "Restoring auto-spawner blacklist " + entityClass.getCanonicalName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Breeder.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Breeder.java new file mode 100644 index 0000000..7681920 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Breeder.java @@ -0,0 +1,144 @@ +/* + * 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.mfr.machines; + +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 minetweaker.mods.mfr.MFRHacks; +import static minetweaker.mc164.util.MineTweakerPlatformUtils.getLivingEntityClass; +import net.minecraft.item.ItemStack; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.Breeder") +@ModOnly("MineFactoryReloaded") +public class Breeder { + @ZenMethod + public static void addFood(String entityClassName, IItemStack item) { + Class entityClass = getLivingEntityClass(entityClassName); + MineTweakerAPI.apply(new BreederAddFoodAction(entityClass, item)); + } + + @ZenMethod + public static void removeFood(String entityClassName, IIngredient item) { + Class entityClass = getLivingEntityClass(entityClassName); + + if (MFRHacks.breederFoods == null) { + MineTweakerAPI.logWarning("Breeder.removeFood is unavailable"); + } else { + List toRemove = new ArrayList(); + List foods = MFRHacks.breederFoods.get(entityClass); + + for (int i = foods.size() - 1; i >= 0; i--) { + if (item.matches(MineTweakerMC.getIItemStack(foods.get(i)))) { + toRemove.add(i); + } + } + for (int i : toRemove) { + MineTweakerAPI.apply(new BreederRemoveFoodAction(entityClass, i)); + } + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class BreederAddFoodAction implements IUndoableAction { + private final Class entityClass; + private final IItemStack item; + + public BreederAddFoodAction(Class entityClass, IItemStack item) { + this.entityClass = entityClass; + this.item = item; + } + + @Override + public void apply() { + FactoryRegistry.registerBreederFood(entityClass, MineTweakerMC.getItemStack(item)); + } + + @Override + public boolean canUndo() { + return MFRHacks.breederFoods != null; + } + + @Override + public void undo() { + List list = MFRHacks.breederFoods.get(entityClass); + list.remove(list.size() - 1); + } + + @Override + public String describe() { + return "Adding breeder food " + item.getDisplayName() + " for " + entityClass.getCanonicalName(); + } + + @Override + public String describeUndo() { + return "Removing breeder food " + item.getDisplayName() + " for " + entityClass.getCanonicalName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class BreederRemoveFoodAction implements IUndoableAction { + private final Class entityClass; + private final int index; + private final ItemStack item; + + public BreederRemoveFoodAction(Class entityClass, int index) { + this.entityClass = entityClass; + this.index = index; + item = MFRHacks.breederFoods.get(entityClass).get(index); + } + + @Override + public void apply() { + MFRHacks.breederFoods.get(entityClass).remove(index); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + MFRHacks.breederFoods.get(entityClass).add(index, item); + } + + @Override + public String describe() { + return "Removing breeder food " + item.getDisplayName() + " for " + entityClass.getCanonicalName(); + } + + @Override + public String describeUndo() { + return "Restoring breeder food " + item.getDisplayName() + " for " + entityClass.getCanonicalName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Fertilizer.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Fertilizer.java new file mode 100644 index 0000000..189e3a1 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Fertilizer.java @@ -0,0 +1,350 @@ +/* + * 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.mfr.machines; + +import java.util.Random; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.mods.mfr.MFRHacks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemDye; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import powercrystals.minefactoryreloaded.api.FertilizerType; +import powercrystals.minefactoryreloaded.api.IFactoryFertilizable; +import powercrystals.minefactoryreloaded.api.IFactoryFertilizer; +import stanhebben.minetweaker.mods.mfr.FertilizableType; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.Fertilizer") +@ModOnly("MineFactoryReloaded") +public class Fertilizer { + @ZenMethod + public void addFertilizable(IItemStack block, String fertilizeType, @Optional String method, @Optional IItemStack replacement) { + FertilizerType fertilizer; + if (fertilizeType.equals("any")) { + fertilizer = null; + } else if (fertilizeType.equals("normal")) { + fertilizer = FertilizerType.GrowPlant; + } else if (fertilizeType.equals("grass")) { + fertilizer = FertilizerType.Grass; + } else if (fertilizeType.equals("magic")) { + fertilizer = FertilizerType.GrowMagicalCrop; + } else { + throw new IllegalArgumentException("Unknown fertilizer type: " + fertilizeType); + } + + FertilizableType type = FertilizableType.BONEMEAL; + + if (method == null || method.equals("bonemeal")) { + type = FertilizableType.BONEMEAL; + } else if (method.equals("replace")) { + type = FertilizableType.REPLACE; + if (replacement == null) + throw new IllegalArgumentException("replace method requires a replacement block"); + } else { + throw new IllegalArgumentException("Unknown fertilization method: " + method); + } + + MineTweakerAPI.apply(new FertilizerAddFertilizableAction(block, replacement, fertilizer, type)); + } + + @ZenMethod + public void removeFertilizable(IItemStack item) { + MineTweakerAPI.apply(new FertilizerRemoveFertilizableAction(item)); + } + + @ZenMethod + public void addFertilizer(IItemStack item, String type) { + FertilizerType fertilizerType; + if (type.equals("grass")) { + fertilizerType = FertilizerType.Grass; + } else if (type.equals("normal")) { + fertilizerType = FertilizerType.GrowPlant; + } else if (type.equals("magic")) { + fertilizerType = FertilizerType.GrowMagicalCrop; + } else { + throw new IllegalArgumentException("Unknown fertilizer type: " + type); + } + + MineTweakerAPI.apply(new FertilizerAddFertilizerAction(item, fertilizerType)); + } + + @ZenMethod + public void remmoveFertilizer(IItemStack item) { + MineTweakerAPI.apply(new FertilizerRemoveFertilizerAction(item)); + } + + // ###################### + // ### Action Classes ### + // ###################### + + public class FertilizerAddFertilizableAction implements IUndoableAction { + private final IItemStack block; + private final IItemStack plant; + private final FertilizerType type; + private final FertilizableType method; + + private final IFactoryFertilizable old; + + public FertilizerAddFertilizableAction(IItemStack block, IItemStack plant, FertilizerType type, FertilizableType method) { + this.block = block; + this.plant = plant; + this.type = type; + this.method = method; + + old = MFRHacks.fertilizables == null ? null : MFRHacks.fertilizables.get(MineTweakerMC.getItemStack(block).itemID); + } + + @Override + public void apply() { + FactoryRegistry.registerFertilizable(new SimpleFertilizable(block, plant, type)); + } + + @Override + public boolean canUndo() { + return MFRHacks.fertilizables != null; + } + + @Override + public void undo() { + if (old == null) { + MFRHacks.fertilizables.remove(MineTweakerMC.getItemStack(block).itemID); + } else { + FactoryRegistry.registerFertilizable(old); + } + } + + @Override + public String describe() { + return "Making " + block.getDisplayName() + " fertilizable"; + } + + @Override + public String describeUndo() { + if (old == null) { + return "Removing fertilizable " + block.getDisplayName(); + } else { + return "Restoring fertilizable " + block.getDisplayName(); + } + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class FertilizerAddFertilizerAction implements IUndoableAction { + private final IItemStack item; + private final FertilizerType type; + + private final IFactoryFertilizer old; + + public FertilizerAddFertilizerAction(IItemStack item, FertilizerType type) { + this.item = item; + this.type = type; + + old = MFRHacks.fertilizers == null ? null : MFRHacks.fertilizers.get(MineTweakerMC.getItemStack(item).itemID); + } + + @Override + public void apply() { + FactoryRegistry.registerFertilizer(new SimpleFertilizer(MineTweakerMC.getItemStack(item), type)); + } + + @Override + public boolean canUndo() { + return MFRHacks.fertilizers != null; + } + + @Override + public void undo() { + if (old == null) { + MFRHacks.fertilizers.remove(MineTweakerMC.getItemStack(item).itemID); + } else { + FactoryRegistry.registerFertilizer(old); + } + } + + @Override + public String describe() { + return "Adding fertilizer " + item.getDisplayName(); + } + + @Override + public String describeUndo() { + if (old == null) { + return "Removing fertilizer " + item.getDisplayName(); + } else { + return "Restoring fertilizer " + item.getDisplayName(); + } + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + public class FertilizerRemoveFertilizableAction implements IUndoableAction { + private final IItemStack item; + private final IFactoryFertilizable old; + + public FertilizerRemoveFertilizableAction(IItemStack item) { + this.item = item; + old = MFRHacks.fertilizables.get(MineTweakerMC.getItemStack(item).itemID); + } + + @Override + public void apply() { + MFRHacks.fertilizables.remove(MineTweakerMC.getItemStack(item).itemID); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + FactoryRegistry.registerFertilizable(old); + } + + @Override + public String describe() { + return "Removing fertilizable " + item.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Restoring fertilizable " + item.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + public class FertilizerRemoveFertilizerAction implements IUndoableAction { + private final IItemStack item; + private final IFactoryFertilizer old; + + public FertilizerRemoveFertilizerAction(IItemStack item) { + this.item = item; + this.old = MFRHacks.fertilizers.get(MineTweakerMC.getItemStack(item).itemID); + } + + @Override + public void apply() { + MFRHacks.fertilizers.remove(MineTweakerMC.getItemStack(item).itemID); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + FactoryRegistry.registerFertilizer(old); + } + + @Override + public String describe() { + return "Removing fertilizer " + item.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Restoring fertilizer " + item.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class SimpleFertilizable implements IFactoryFertilizable { + private final IItemStack block; + private final IItemStack plant; + private final FertilizerType type; + + public SimpleFertilizable(IItemStack block, IItemStack plant, FertilizerType type) { + this.block = block; + this.plant = plant; + this.type = type; + } + + @Override + public int getFertilizableBlockId() { + return MineTweakerMC.getItemStack(block).itemID; + } + + @Override + public boolean canFertilizeBlock(World world, int x, int y, int z, FertilizerType fertilizerType) { + if (this.type != null && type != fertilizerType) + return false; + + IItemStack blockAt = MineTweakerMC.getIItemStack(new ItemStack(world.getBlockId(x, y, z), 1, world.getBlockMetadata(x, y, z))); + return block.matches(blockAt); + } + + @Override + public boolean fertilize(World world, Random rand, int x, int y, int z, FertilizerType fertilizerType) { + if (plant == null) { + return ItemDye.applyBonemeal(new ItemStack(Item.dyePowder.itemID, 1, 15), world, x, y, z, null); + } else { + ItemStack istack = MineTweakerMC.getItemStack(plant); + world.setBlock(x, y, z, istack.itemID, plant.getDamage(), 0); + return true; + } + } + } + + private static class SimpleFertilizer implements IFactoryFertilizer { + private final ItemStack item; + private final FertilizerType type; + + public SimpleFertilizer(ItemStack item, FertilizerType type) { + this.item = item; + this.type = type; + } + + @Override + public int getFertilizerId() { + return item.itemID; + } + + @Override + public int getFertilizerMeta() { + return item.getItemDamage(); + } + + @Override + public FertilizerType getFertilizerType() { + return type; + } + + @Override + public void consume(ItemStack fertilizer) { + fertilizer.stackSize--; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/FruitPicker.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/FruitPicker.java new file mode 100644 index 0000000..9aae9ec --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/FruitPicker.java @@ -0,0 +1,361 @@ +/* + * 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.mfr.machines; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.item.WeightedItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.mods.mfr.MFRHacks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import powercrystals.minefactoryreloaded.api.IFactoryFruit; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.FruitPicker") +@ModOnly("MineFactoryReloaded") +public class FruitPicker { + @ZenMethod + public static void addFruit(IBlockPattern block, IBlock replacement, WeightedItemStack drop) { + addFruit(block, replacement, new WeightedItemStack[] { drop }); + } + + @ZenMethod + public static void addFruit(IBlockPattern block, IBlock replacement, WeightedItemStack[] drops) { + TweakerFruit fruit = new TweakerFruit(block, replacement, drops); + MineTweakerAPI.apply(new AddFruitAction(fruit)); + } + + @ZenMethod + public static void removeFruit(IBlockPattern block) { + if (MFRHacks.fruitBlocks == null) { + MineTweakerAPI.logWarning("Could not remove MFR Fruit Picker fruits"); + } else { + MineTweakerAPI.apply(new RemoveFruitAction(block)); + } + } + + @ZenMethod + public static void addLog(IBlockPattern block) { + MineTweakerAPI.apply(new AddLogAction(block)); + } + + @ZenMethod + public static void removeLog(IBlockPattern block) { + if (MFRHacks.fruitLogBlocks == null) { + MineTweakerAPI.logWarning("Cannot remove MFR Fruit Picker Logs"); + } else { + MineTweakerAPI.apply(new RemoveLogAction(block)); + } + } + + // ##################### + // ### Inner classes ### + // ##################### + + private static class TweakerFruit { + private final IBlockPattern block; + private final IBlock replacement; + private final WeightedItemStack[] possibleDrops; + + public TweakerFruit(IBlockPattern block, IBlock replacement, WeightedItemStack[] possibleDrops) { + this.block = block; + this.replacement = replacement; + this.possibleDrops = possibleDrops; + } + } + + private static class TweakerFruitPartial implements IFactoryFruit { + private final int blockId; + private final List fruits; + + public TweakerFruitPartial(int blockId) { + this.blockId = blockId; + fruits = new ArrayList(); + } + + @Override + public int getSourceBlockId() { + return blockId; + } + + @Override + public boolean canBePicked(World world, int x, int y, int z) { + for (TweakerFruit fruit : fruits) { + if (fruit.block.matches(MineTweakerMC.getBlock(world, x, y, z))) + return true; + } + + return false; + } + + @Override + public ItemStack getReplacementBlock(World world, int x, int y, int z) { + IBlock block = MineTweakerMC.getBlock(world, x, y, z); + for (TweakerFruit fruit : fruits) { + if (fruit.block.matches(block)) + return MineTweakerMC.toItemStack(fruit.replacement); + } + return null; + } + + @Override + public void prePick(World world, int x, int y, int z) {} + + @Override + public List getDrops(World world, Random rand, int x, int y, int z) { + IBlock block = MineTweakerMC.getBlock(world, x, y, z); + for (TweakerFruit fruit : fruits) { + if (fruit.block.matches(block)) + return Arrays.asList(MineTweakerMC.getItemStacks(WeightedItemStack.pickRandomDrops(rand, fruit.possibleDrops))); + } + + return Collections.EMPTY_LIST; + } + + @Override + public void postPick(World world, int x, int y, int z) {} + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddFruitAction implements IUndoableAction { + private final TweakerFruit fruit; + + public AddFruitAction(TweakerFruit fruit) { + this.fruit = fruit; + } + + @Override + public void apply() { + Map fruits = MFRHacks.fruitBlocks; + for (IBlock partial : fruit.block.getBlocks()) { + int blockId = MineTweakerMC.getBlockId(partial.getDefinition()); + if (fruits != null && fruits.containsKey(blockId)) { + IFactoryFruit existingFruit = fruits.get(blockId); + if (existingFruit instanceof TweakerFruitPartial) { + TweakerFruitPartial existingFruitPartial = (TweakerFruitPartial) existingFruit; + if (!existingFruitPartial.fruits.contains(fruit)) { + existingFruitPartial.fruits.add(fruit); + } + } else { + MineTweakerAPI.logError("A non-MineTweaker fruit already exists for this ID"); + } + } else { + TweakerFruitPartial factoryFruit = new TweakerFruitPartial(blockId); + FactoryRegistry.registerFruit(factoryFruit); + } + } + } + + @Override + public boolean canUndo() { + return MFRHacks.fruitBlocks != null; + } + + @Override + public void undo() { + Map fruits = MFRHacks.fruitBlocks; + for (IBlock partial : fruit.block.getBlocks()) { + int blockId = MineTweakerMC.getBlockId(partial.getDefinition()); + IFactoryFruit factoryFruit = fruits.get(blockId); + if (factoryFruit != null && factoryFruit instanceof TweakerFruitPartial) { + ((TweakerFruitPartial) factoryFruit).fruits.remove(fruit); + } + } + } + + @Override + public String describe() { + return "Adding Fruit Picker fruit block " + fruit.block.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Removing Fruit Picker fruit block " + fruit.block.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveFruitAction implements IUndoableAction { + private final IBlockPattern block; + private final Map removed; + + public RemoveFruitAction(IBlockPattern block) { + this.block = block; + + Map fruits = MFRHacks.fruitBlocks; + removed = new HashMap(); + for (IBlock partial : block.getBlocks()) { + int blockId = MineTweakerMC.getBlockId(partial.getDefinition()); + if (fruits.containsKey(blockId)) { + removed.put(blockId, fruits.get(blockId)); + } + } + } + + @Override + public void apply() { + Map fruits = MFRHacks.fruitBlocks; + for (Integer key : removed.keySet()) { + fruits.remove(key); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + Map fruits = MFRHacks.fruitBlocks; + for (Map.Entry restore : removed.entrySet()) { + fruits.put(restore.getKey(), restore.getValue()); + } + } + + @Override + public String describe() { + return "Removing fruit picker fruit block " + block.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Restoring fruit picker fruit block " + block.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AddLogAction implements IUndoableAction { + private final IBlockPattern block; + private final List addedLogs = new ArrayList(); + + public AddLogAction(IBlockPattern block) { + this.block = block; + + for (IBlock partial : block.getBlocks()) { + int blockId = MineTweakerMC.getBlockId(partial.getDefinition()); + if (MFRHacks.fruitLogBlocks == null || !MFRHacks.fruitLogBlocks.contains(blockId)) { + if (!addedLogs.contains(blockId)) + addedLogs.add(blockId); + } + } + } + + @Override + public void apply() { + for (int log : addedLogs) { + FactoryRegistry.registerFruitLogBlockId(log); + } + } + + @Override + public boolean canUndo() { + return MFRHacks.fruitLogBlocks != null; + } + + @Override + public void undo() { + for (int log : addedLogs) { + MFRHacks.fruitLogBlocks.remove(log); + } + } + + @Override + public String describe() { + return "Adding MFR Fruit Picker log block " + block.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Removing MFR Fruit Picker log block " + block.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveLogAction implements IUndoableAction { + private final IBlockPattern block; + private final List removedLogs = new ArrayList(); + + public RemoveLogAction(IBlockPattern block) { + this.block = block; + + for (IBlock partial : block.getBlocks()) { + int blockId = MineTweakerMC.getBlockId(partial.getDefinition()); + if (MFRHacks.fruitLogBlocks.contains(blockId)) { + if (!removedLogs.contains(blockId)) + removedLogs.add(blockId); + } + } + } + + @Override + public void apply() { + for (int log : removedLogs) { + MFRHacks.fruitLogBlocks.remove(log); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + for (int log : removedLogs) { + FactoryRegistry.registerFruitLogBlockId(log); + } + } + + @Override + public String describe() { + return "Removing MFR Fruit Picker log block " + block.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Restoring MFR Fruit Picker log block " + block.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Grinder.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Grinder.java new file mode 100644 index 0000000..c6178da --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Grinder.java @@ -0,0 +1,266 @@ +/* + * 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.mfr.machines; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.item.IItemStack; +import minetweaker.api.item.WeightedItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import static minetweaker.mc164.util.MineTweakerPlatformUtils.getLivingEntityClass; +import minetweaker.mods.mfr.MFRHacks; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import powercrystals.minefactoryreloaded.api.IFactoryGrindable; +import powercrystals.minefactoryreloaded.api.MobDrop; +import stanhebben.zenscript.annotations.ZenClass; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.Grinder") +@ModOnly("MineFactoryReloaded") +public class Grinder { + public static void addBlacklist(String entityClassName) { + Class entityClass = getLivingEntityClass(entityClassName); + MineTweakerAPI.apply(new AddBlacklistAction(entityClass)); + } + + public static void removeBlacklist(String entityClassName) { + Class entityClass = getLivingEntityClass(entityClassName); + if (MFRHacks.grindableBlacklist == null) { + MineTweakerAPI.logWarning("Cannot remove MFR Grinder blacklist entries"); + } else if (!MFRHacks.grindableBlacklist.contains(entityClass)) { + MineTweakerAPI.logWarning(entityClassName + " is not blacklisted in the MFR Grinder"); + } else { + MineTweakerAPI.apply(new RemoveBlacklistAction(entityClass)); + } + } + + public static void addGrindable(String entityClassName) { + addGrindable(entityClassName, new WeightedItemStack[0]); + } + + public static void addGrindable(String entityClassName, WeightedItemStack possibleDrop) { + addGrindable(entityClassName, new WeightedItemStack[] { possibleDrop }); + } + + public static void addGrindable(String entityClassName, WeightedItemStack[] possibleDrops) { + Class entityClass = getLivingEntityClass(entityClassName); + MineTweakerAPI.apply(new AddGrindableAction(entityClass, possibleDrops)); + } + + public static void removeGrindable(String entityClassName) { + Class entityClass = getLivingEntityClass(entityClassName); + if (MFRHacks.grindables == null) { + MineTweakerAPI.logWarning("Cannot remove MFR grindables"); + } else if (!MFRHacks.grindables.containsKey(entityClass)) { + MineTweakerAPI.logError("No such grindable entity: " + entityClassName); + } else { + MineTweakerAPI.apply(new RemoveGrindableAction(entityClass)); + } + } + + // ####################### + // ### Private classes ### + // ####################### + + private static class SimpleGrindable implements IFactoryGrindable { + private final Class entityClass; + private final WeightedItemStack[] drops; + + public SimpleGrindable(Class entityClass, WeightedItemStack[] drops) { + this.entityClass = entityClass; + this.drops = drops; + } + + @Override + public Class getGrindableEntity() { + return entityClass; + } + + @Override + public List grind(World world, EntityLivingBase entity, Random random) { + List dropList = new ArrayList(); + for (IItemStack itemStack : WeightedItemStack.pickRandomDrops(random, drops)) { + dropList.add(new MobDrop(1, MineTweakerMC.getItemStack(itemStack))); + } + return dropList; + } + + @Override + public boolean processEntity(EntityLivingBase entity) { + entity.attackEntityFrom(DamageSource.generic, entity.getMaxHealth() * 20); + return entity.isDead; + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddBlacklistAction implements IUndoableAction { + private final Class entityClass; + + public AddBlacklistAction(Class entityClass) { + this.entityClass = entityClass; + } + + @Override + public void apply() { + FactoryRegistry.registerGrinderBlacklist(entityClass); + } + + @Override + public boolean canUndo() { + return MFRHacks.grindableBlacklist != null; + } + + @Override + public void undo() { + MFRHacks.grindableBlacklist.remove(entityClass); + } + + @Override + public String describe() { + return "Adding " + entityClass.getName() + " to the MFR Grinder blacklist"; + } + + @Override + public String describeUndo() { + return "Removing " + entityClass.getName() + " from the MFR Grinder blacklist"; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveBlacklistAction implements IUndoableAction { + private final Class entityClass; + + public RemoveBlacklistAction(Class entityClass) { + this.entityClass = entityClass; + } + + @Override + public void apply() { + MFRHacks.grindableBlacklist.remove(entityClass); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + FactoryRegistry.registerGrinderBlacklist(entityClass); + } + + @Override + public String describe() { + return "Removing " + entityClass + " from the MFR Grinder blacklist"; + } + + @Override + public String describeUndo() { + return "Restoring " + entityClass + " to the MFR Grinder blacklist"; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AddGrindableAction implements IUndoableAction { + private final SimpleGrindable grindable; + + public AddGrindableAction(Class entityClass, WeightedItemStack[] possibleDrops) { + grindable = new SimpleGrindable(entityClass, possibleDrops); + } + + @Override + public void apply() { + FactoryRegistry.registerGrindable(grindable); + } + + @Override + public boolean canUndo() { + return MFRHacks.grindables != null; + } + + @Override + public void undo() { + MFRHacks.grindables.remove(grindable.entityClass); + } + + @Override + public String describe() { + return "Adding MFR Grindable " + grindable.entityClass.getName(); + } + + @Override + public String describeUndo() { + return "Removing MFR Grindable " + grindable.entityClass.getName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveGrindableAction implements IUndoableAction { + private final Class entityClass; + private final IFactoryGrindable grindable; + + public RemoveGrindableAction(Class entityClass) { + this.entityClass = entityClass; + grindable = MFRHacks.grindables.get(entityClass); + } + + @Override + public void apply() { + MFRHacks.grindables.remove(entityClass); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + FactoryRegistry.registerGrindable(grindable); + } + + @Override + public String describe() { + return "Removing grindable " + entityClass.getName(); + } + + @Override + public String describeUndo() { + return "Restoring grindable " + entityClass.getName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Harvester.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Harvester.java new file mode 100644 index 0000000..f0de3e8 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Harvester.java @@ -0,0 +1,272 @@ +/* + * 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.mfr.machines; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.item.WeightedItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.mods.mfr.MFRHacks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import powercrystals.minefactoryreloaded.api.HarvestType; +import powercrystals.minefactoryreloaded.api.IFactoryFruit; +import powercrystals.minefactoryreloaded.api.IFactoryHarvestable; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.Harvester") +@ModOnly("MineFactoryReloaded") +public class Harvester { + @ZenMethod + public static void addHarvestable(IBlockPattern block, WeightedItemStack drop, @Optional String type) { + addHarvestable(block, new WeightedItemStack[] { drop }, type); + } + + @ZenMethod + public static void addHarvestable(IBlockPattern block, WeightedItemStack[] drops, @Optional String type) { + TweakerHarvestable harvestable = new TweakerHarvestable(block, drops, type); + MineTweakerAPI.apply(new AddHarvestableAction(harvestable)); + } + + @ZenMethod + public static void removeHarvestable(IBlockPattern block) { + if (MFRHacks.harvestables == null) { + MineTweakerAPI.logWarning("Could not remove MFR Harvester harvestable"); + } else { + MineTweakerAPI.apply(new RemoveHarvestableAction(block)); + } + } + + // ##################### + // ### Inner classes ### + // ##################### + + private static class TweakerHarvestable { + private final IBlockPattern block; + private final WeightedItemStack[] possibleDrops; + private final HarvestType type; + + public TweakerHarvestable(IBlockPattern block, WeightedItemStack[] possibleDrops, String stringType) { + this.block = block; + this.possibleDrops = possibleDrops; + + HarvestType type = HarvestType.Normal; + if (stringType.equals("normal")) { + type = HarvestType.Normal; + } else if (stringType.equals("column")) { + type = HarvestType.Column; + } else if (stringType.equals("leaveBottom")) { + type = HarvestType.LeaveBottom; + } else if (stringType.equals("tree")) { + type = HarvestType.Tree; + } else if (stringType.equals("treeFlipped")) { + type = HarvestType.TreeFlipped; + } else if (stringType.equals("treeLeaf")) { + type = HarvestType.TreeLeaf; + } else { + throw new IllegalArgumentException("Unknown harvestable type: " + stringType); + } + + this.type = type; + } + } + + private static class TweakerHarvestablePartial implements IFactoryHarvestable { + private final int blockId; + private final List harvestables; + + public TweakerHarvestablePartial(int blockId) { + this.blockId = blockId; + harvestables = new ArrayList(); + } + + @Override + public int getPlantId() { + return blockId; + } + + @Override + public HarvestType getHarvestType() { + // WARNING: first type will be used + return harvestables.get(0).type; + } + + @Override + public boolean breakBlock() { + return true; + } + + @Override + public boolean canBeHarvested(World world, Map map, int x, int y, int z) { + for (TweakerHarvestable fruit : harvestables) { + if (fruit.block.matches(MineTweakerMC.getBlock(world, x, y, z))) + return true; + } + + return false; + } + + @Override + public List getDrops(World world, Random random, Map map, int x, int y, int z) { + IBlock block = MineTweakerMC.getBlock(world, x, y, z); + + for (TweakerHarvestable harvestable : harvestables) { + if (harvestable.block.matches(block)) + return Arrays.asList(MineTweakerMC.getItemStacks(WeightedItemStack.pickRandomDrops(random, harvestable.possibleDrops))); + } + + return Collections.EMPTY_LIST; + } + + @Override + public void preHarvest(World world, int x, int y, int z) { + + } + + @Override + public void postHarvest(World world, int x, int y, int z) { + + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddHarvestableAction implements IUndoableAction { + private final TweakerHarvestable harvestable; + + public AddHarvestableAction(TweakerHarvestable harvestable) { + this.harvestable = harvestable; + } + + @Override + public void apply() { + Map harvestables = MFRHacks.harvestables; + for (IBlock partial : harvestable.block.getBlocks()) { + int blockId = MineTweakerMC.getBlockId(partial.getDefinition()); + if (harvestable != null && harvestables.containsKey(blockId)) { + IFactoryHarvestable existingHarvestable = harvestables.get(blockId); + if (existingHarvestable instanceof TweakerHarvestablePartial) { + TweakerHarvestablePartial existingHarvestablePartial = (TweakerHarvestablePartial) existingHarvestable; + if (!existingHarvestablePartial.harvestables.contains(harvestable)) { + existingHarvestablePartial.harvestables.add(harvestable); + } + } else { + MineTweakerAPI.logError("A non-MineTweaker fruit already exists for this ID"); + } + } else { + TweakerHarvestablePartial factoryFruit = new TweakerHarvestablePartial(blockId); + FactoryRegistry.registerHarvestable(factoryFruit); + } + } + } + + @Override + public boolean canUndo() { + return MFRHacks.fruitBlocks != null; + } + + @Override + public void undo() { + Map harvestables = MFRHacks.harvestables; + for (IBlock partial : harvestable.block.getBlocks()) { + int blockId = MineTweakerMC.getBlockId(partial.getDefinition()); + IFactoryHarvestable factoryHarvestable = harvestables.get(blockId); + if (factoryHarvestable != null && factoryHarvestable instanceof TweakerHarvestablePartial) { + ((TweakerHarvestablePartial) factoryHarvestable).harvestables.remove(harvestable); + } + } + } + + @Override + public String describe() { + return "Adding Harvester harvestable block " + harvestable.block.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Removing Harvester harvestable block " + harvestable.block.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveHarvestableAction implements IUndoableAction { + private final IBlockPattern block; + private final Map removed; + + public RemoveHarvestableAction(IBlockPattern block) { + this.block = block; + + Map fruits = MFRHacks.fruitBlocks; + removed = new HashMap(); + for (IBlock partial : block.getBlocks()) { + int blockId = MineTweakerMC.getBlockId(partial.getDefinition()); + if (fruits.containsKey(blockId)) { + removed.put(blockId, fruits.get(blockId)); + } + } + } + + @Override + public void apply() { + Map fruits = MFRHacks.fruitBlocks; + for (Integer key : removed.keySet()) { + fruits.remove(key); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + Map fruits = MFRHacks.fruitBlocks; + for (Map.Entry restore : removed.entrySet()) { + fruits.put(restore.getKey(), restore.getValue()); + } + } + + @Override + public String describe() { + return "Removing Harvester harvestable block " + block.getDisplayName(); + } + + @Override + public String describeUndo() { + return "Restoring Harvester harvestable block " + block.getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/IRedNetFunction.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/IRedNetFunction.java new file mode 100644 index 0000000..90524d2 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/IRedNetFunction.java @@ -0,0 +1,15 @@ +/* + * 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.mfr.machines; + +/** + * + * @author Stan + */ +public interface IRedNetFunction { + public int[] calculate(long time, int[] inputs); +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/MiningLaser.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/MiningLaser.java new file mode 100644 index 0000000..6ca4621 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/MiningLaser.java @@ -0,0 +1,236 @@ +/* + * 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.mfr.machines; + +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.item.WeightedItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.mods.mfr.MFRHacks; +import net.minecraft.item.ItemStack; +import powercrystals.core.random.WeightedRandomItemStack; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.MiningLaser") +@ModOnly("MineFactoryReloaded") +public class MiningLaser { + @ZenMethod + public static void addOre(WeightedItemStack ore) { + MineTweakerAPI.apply(new AddOreAction(ore)); + } + + @ZenMethod + public static void removeOre(IIngredient ore) { + MineTweakerAPI.apply(new RemoveOreAction(ore)); + } + + @ZenMethod + public static void addPreferredOre(int color, IIngredient ore) { + MineTweakerAPI.apply(new AddPreferredOreAction(color, ore)); + } + + @ZenMethod + public static void removePreferredOre(int color, IIngredient ore) { + MineTweakerAPI.apply(new RemovePreferredOreAction(color, ore)); + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddOreAction implements IUndoableAction { + private final WeightedRandomItemStack item; + + public AddOreAction(WeightedItemStack item) { + this.item = new WeightedRandomItemStack((int) item.getChance(), MineTweakerMC.getItemStack(item.getStack())); + } + + @Override + public void apply() { + if (MFRHacks.laserOres == null) { + FactoryRegistry.registerLaserOre(item.itemWeight, item.getStack()); + } else { + MFRHacks.laserOres.add(item); + } + } + + @Override + public boolean canUndo() { + return MFRHacks.laserOres != null; + } + + @Override + public void undo() { + MFRHacks.laserOres.remove(item); + } + + @Override + public String describe() { + return "Adding laser ore " + item.getStack().getDisplayName(); + } + + @Override + public String describeUndo() { + return "Removing laser ore " + item.getStack().getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveOreAction implements IUndoableAction { + private final IIngredient ingredient; + private final List removed; + + public RemoveOreAction(IIngredient ingredient) { + this.ingredient = ingredient; + removed = new ArrayList(); + + for (WeightedRandomItemStack stack : MFRHacks.laserOres) { + if (ingredient.matches(MineTweakerMC.getIItemStack(stack.getStack()))) { + removed.add(stack); + } + } + } + + @Override + public void apply() { + MFRHacks.laserOres.removeAll(removed); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + MFRHacks.laserOres.addAll(removed); + } + + @Override + public String describe() { + return "Removing laser ore " + ingredient.toString(); + } + + @Override + public String describeUndo() { + return "Restoring laser ore " + ingredient.toString(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AddPreferredOreAction implements IUndoableAction { + private final int color; + private final IIngredient ore; + + public AddPreferredOreAction(int color, IIngredient ore) { + this.color = color; + this.ore = ore; + } + + @Override + public void apply() { + for (IItemStack item : ore.getItems()) { + FactoryRegistry.addLaserPreferredOre(color, MineTweakerMC.getItemStack(item)); + } + } + + @Override + public boolean canUndo() { + return MFRHacks.laserPreferredOres != null; + } + + @Override + public void undo() { + for (IItemStack item : ore.getItems()) { + ItemStack stack = MineTweakerMC.getItemStack(item); + MFRHacks.laserPreferredOres.get(stack.itemID).remove(stack); + } + } + + @Override + public String describe() { + return "Adding laser preferred ore " + ore + " to color " + color; + } + + @Override + public String describeUndo() { + return "Removing laser preferred ore " + ore + " from color " + color; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemovePreferredOreAction implements IUndoableAction { + private final int color; + private final IIngredient ore; + private final List toRemove; + + public RemovePreferredOreAction(int color, IIngredient ore) { + this.color = color; + this.ore = ore; + + toRemove = new ArrayList(); + for (ItemStack item : MFRHacks.laserPreferredOres.get(color)) { + if (ore.matches(MineTweakerMC.getIItemStack(item))) { + toRemove.add(item); + } + } + } + + @Override + public void apply() { + MFRHacks.laserPreferredOres.get(color).removeAll(toRemove); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + MFRHacks.laserPreferredOres.get(color).addAll(toRemove); + } + + @Override + public String describe() { + return "Removing preferred ore " + ore + " for color " + color; + } + + @Override + public String describeUndo() { + return "Adding preferred ore " + ore + " for color " + color; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Planter.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Planter.java new file mode 100644 index 0000000..2b7d513 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Planter.java @@ -0,0 +1,275 @@ +/* + * 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.mfr.machines; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.mods.mfr.MFRHacks; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import powercrystals.minefactoryreloaded.api.IFactoryPlantable; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.Planter") +@ModOnly("MineFactoryReloaded") +public class Planter { + private static final IBlockPattern GRASS_OR_DIRT; + + static { + IBlock blockDirt = MineTweakerMC.getBlockAnyMeta(Block.dirt); + IBlock blockGrass = MineTweakerMC.getBlockAnyMeta(Block.grass); + GRASS_OR_DIRT = blockDirt.or(blockGrass); + } + + @ZenMethod + public static void addPlantable(IItemStack seed, @Optional IBlockPattern canPlantOn) { + IBlock block = seed.asBlock(); + if (block == null) { + MineTweakerAPI.logError("The given seed has no block equivalant"); + } + addPlantable(seed, block, canPlantOn); + } + + @ZenMethod + public static void addPlantable(IIngredient seed, IBlock block, @Optional IBlockPattern canPlantOn) { + if (canPlantOn == null) { + canPlantOn = GRASS_OR_DIRT; + } + + if (seed.getItems() == null) { + MineTweakerAPI.logError("Seed must be a defined ingredient and cannot be <*>"); + } else { + MineTweakerAPI.apply(new AddPlantableAction(new TweakerPlantable(seed, block, canPlantOn))); + } + } + + @ZenMethod + public static void removePlantable(IIngredient seed) { + if (MFRHacks.plantables == null) { + MineTweakerAPI.logWarning("Could not remove MFR Planter plantable"); + } else { + MineTweakerAPI.apply(new RemovePlantableAction(seed)); + } + } + + // ##################### + // ### Inner classes ### + // ##################### + + private static class TweakerPlantable { + private final IIngredient seed; + private final IBlock block; + private final IBlockPattern canPlantOn; + + public TweakerPlantable(IIngredient seed, IBlock block, IBlockPattern canPlantOn) { + this.seed = seed; + this.block = block; + this.canPlantOn = canPlantOn; + } + } + + private static class TweakerPlantablePartial implements IFactoryPlantable { + private final int seedId; + private final List plantables; + + public TweakerPlantablePartial(int seedId) { + this.seedId = seedId; + plantables = new ArrayList(); + } + + public TweakerPlantablePartial(int seedId, TweakerPlantable plantable) { + this(seedId); + + plantables.add(plantable); + } + + @Override + public int getSeedId() { + return seedId; + } + + @Override + public int getPlantedBlockId(World world, int i, int i1, int i2, ItemStack seed) { + IItemStack iSeed = MineTweakerMC.getIItemStack(seed); + for (TweakerPlantable plantable : plantables) { + if (plantable.seed.matches(iSeed)) + return MineTweakerMC.getBlockId(plantable.block.getDefinition()); + } + + return 1; + } + + @Override + public int getPlantedBlockMetadata(World world, int i, int i1, int i2, ItemStack seed) { + IItemStack iSeed = MineTweakerMC.getIItemStack(seed); + for (TweakerPlantable plantable : plantables) { + if (plantable.seed.matches(iSeed)) + return plantable.block.getMeta(); + } + + return 0; + } + + @Override + public boolean canBePlantedHere(World world, int x, int y, int z, ItemStack seed) { + for (TweakerPlantable plantable : plantables) { + if (!plantable.seed.matches(MineTweakerMC.getIItemStack(seed))) + return false; + + if (!plantable.canPlantOn.matches(MineTweakerMC.getBlock(world, x, y - 1, x))) + return false; + } + + return true; + } + + @Override + public void prePlant(World world, int i, int i1, int i2, ItemStack is) { + + } + + @Override + public void postPlant(World world, int i, int i1, int i2, ItemStack is) { + + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddPlantableAction implements IUndoableAction { + private final TweakerPlantable plantable; + + private AddPlantableAction(TweakerPlantable plantable) { + this.plantable = plantable; + } + + @Override + public void apply() { + for (IItemStack item : plantable.seed.getItems()) { + int itemId = MineTweakerMC.getItemStack(item).itemID; + if (MFRHacks.plantables == null) { + FactoryRegistry.registerPlantable(new TweakerPlantablePartial(itemId, plantable)); + } else { + if (MFRHacks.plantables.containsKey(itemId)) { + IFactoryPlantable existing = MFRHacks.plantables.get(itemId); + if (existing instanceof TweakerPlantablePartial) { + ((TweakerPlantablePartial) existing).plantables.add(plantable); + } else { + MineTweakerAPI.logError("Existing non-MineTweaker plantable already exists for seed ID " + itemId); + } + } else { + FactoryRegistry.registerPlantable(new TweakerPlantablePartial(itemId, plantable)); + } + } + } + } + + @Override + public boolean canUndo() { + return MFRHacks.plantables != null; + } + + @Override + public void undo() { + for (IItemStack item : plantable.seed.getItems()) { + int itemId = MineTweakerMC.getItemStack(item).itemID; + IFactoryPlantable existing = MFRHacks.plantables.get(itemId); + if (existing instanceof TweakerPlantablePartial) { + ((TweakerPlantablePartial) existing).plantables.remove(plantable); + } + } + } + + @Override + public String describe() { + return "Adding MFR Plantable for seed " + plantable.seed; + } + + @Override + public String describeUndo() { + return "Removing MFR Plantable for seed " + plantable.seed; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemovePlantableAction implements IUndoableAction { + private final IIngredient seed; + private final Map removed; + + private RemovePlantableAction(IIngredient seed) { + this.seed = seed; + + removed = new HashMap(); + for (IItemStack item : seed.getItems()) { + int itemId = MineTweakerMC.getItemStack(item).itemID; + if (!removed.containsKey(itemId)) { + if (MFRHacks.plantables.containsKey(itemId)) { + removed.put(itemId, MFRHacks.plantables.get(itemId)); + } + } + } + } + + @Override + public void apply() { + for (Integer seedId : removed.keySet()) { + MFRHacks.plantables.remove(seedId); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + for (Map.Entry removedEntry : removed.entrySet()) { + MFRHacks.plantables.put(removedEntry.getKey(), removedEntry.getValue()); + } + } + + @Override + public String describe() { + return "Removing MFR Planter seed " + seed; + } + + @Override + public String describeUndo() { + return "Restoring MFR Planter seed " + seed; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Rancher.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Rancher.java new file mode 100644 index 0000000..aa51669 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/Rancher.java @@ -0,0 +1,189 @@ +/* + * 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.mfr.machines; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.api.item.IItemStack; +import minetweaker.api.item.WeightedItemStack; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.liquid.WeightedLiquidStack; +import minetweaker.api.minecraft.MineTweakerMC; +import static minetweaker.mc164.util.MineTweakerPlatformUtils.getLivingEntityClass; +import minetweaker.mods.mfr.MFRHacks; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidContainerRegistry; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import powercrystals.minefactoryreloaded.api.IFactoryRanchable; +import powercrystals.minefactoryreloaded.api.RanchedItem; +import stanhebben.zenscript.annotations.Optional; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.AutoSpawner") +@ModOnly("MineFactoryReloaded") +public class Rancher { + private static final Random random = new Random(); + + @ZenMethod + public static void addRanchable(String entityClassName, WeightedItemStack[] possibleDrops, @Optional WeightedLiquidStack[] possibleLiquids) { + if (possibleLiquids == null) + possibleLiquids = new WeightedLiquidStack[0]; + + Class entityClass = getLivingEntityClass(entityClassName); + MineTweakerAPI.apply(new AddRanchableAction(new TweakerRanchable(entityClass, possibleDrops, possibleLiquids))); + } + + @ZenMethod + public static void removeRanchable(String entityClassName) { + Class entityClass = getLivingEntityClass(entityClassName); + if (MFRHacks.ranchables == null) { + MineTweakerAPI.logWarning("Cannot remove MFR Ranchables"); + } else if (!MFRHacks.ranchables.containsKey(entityClass)) { + MineTweakerAPI.logWarning("No such ranchable: " + entityClassName); + } else { + MineTweakerAPI.apply(new RemoveRanchableAction(MFRHacks.ranchables.get(entityClass))); + } + } + + // ####################### + // ### Private classes ### + // ####################### + + private static class TweakerRanchable implements IFactoryRanchable { + private final Class entityClass; + private final WeightedItemStack[] possibleDrops; + private final WeightedLiquidStack[] possibleLiquids; + + public TweakerRanchable(Class entityClass, WeightedItemStack[] possibleDrops, WeightedLiquidStack[] possibleLiquids) { + this.entityClass = entityClass; + this.possibleDrops = possibleDrops; + this.possibleLiquids = possibleLiquids; + } + + @Override + public Class getRanchableEntity() { + return entityClass; + } + + @Override + public List ranch(World world, EntityLivingBase entity, IInventory inventory) { + List result = new ArrayList(); + if (entityClass.isAssignableFrom(entity.getClass())) { + for (IItemStack droppedItem : WeightedItemStack.pickRandomDrops(random, possibleDrops)) { + result.add(new RanchedItem(MineTweakerMC.getItemStack(droppedItem))); + } + + for (ILiquidStack droppedLiquid : WeightedLiquidStack.pickRandomDrops(random, possibleLiquids)) { + for (int i = 0; i < inventory.getSizeInventory(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + if (stack != null) { + ItemStack filled = FluidContainerRegistry.fillFluidContainer(MineTweakerMC.getLiquidStack(droppedLiquid), stack); + if (filled != null) { + inventory.setInventorySlotContents(i, filled); + break; + } + } + } + } + } + + return result; + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddRanchableAction implements IUndoableAction { + private final TweakerRanchable ranchable; + + public AddRanchableAction(TweakerRanchable ranchable) { + this.ranchable = ranchable; + } + + @Override + public void apply() { + FactoryRegistry.registerRanchable(ranchable); + } + + @Override + public boolean canUndo() { + return MFRHacks.ranchables != null; + } + + @Override + public void undo() { + MFRHacks.ranchables.remove(ranchable.entityClass); + } + + @Override + public String describe() { + return "Adding ranchable entity " + ranchable.entityClass.getName(); + } + + @Override + public String describeUndo() { + return "Removing ranchable entity " + ranchable.entityClass.getName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveRanchableAction implements IUndoableAction { + private final IFactoryRanchable ranchable; + + public RemoveRanchableAction(IFactoryRanchable ranchable) { + this.ranchable = ranchable; + } + + @Override + public void apply() { + MFRHacks.ranchables.remove(ranchable.getRanchableEntity()); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + MFRHacks.ranchables.put(ranchable.getRanchableEntity(), ranchable); + } + + @Override + public String describe() { + return "Removing ranchable entity " + ranchable.getRanchableEntity().getName(); + } + + @Override + public String describeUndo() { + return "Restoring ranchable entity " + ranchable.getRanchableEntity().getName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/RedNet.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/RedNet.java new file mode 100644 index 0000000..315dff2 --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/RedNet.java @@ -0,0 +1,191 @@ +/* + * 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.mfr.machines; + +import java.util.ArrayList; +import java.util.List; +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.mods.mfr.MFRHacks; +import net.minecraft.nbt.NBTTagCompound; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import powercrystals.minefactoryreloaded.api.rednet.IRedNetLogicCircuit; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.RedNet") +@ModOnly("MineFactoryReloaded") +public class RedNet { + @ZenMethod + public static void addCircuit(String name, String[] inputs, String[] outputs, IRedNetFunction function) { + MineTweakerAPI.apply(new AddCircuitAction(new TweakerRedNetLogicCircuit(name, inputs, outputs, function))); + } + + @ZenMethod + public static void removeCircuit(String name) { + if (MFRHacks.redNetCircuits == null) { + MineTweakerAPI.logWarning("Cannot remove rednet circuits"); + return; + } + + List toRemove = new ArrayList(); + for (IRedNetLogicCircuit circuit : MFRHacks.redNetCircuits) { + if (circuit.getUnlocalizedName().equals(name)) { + toRemove.add(circuit); + } + } + + if (toRemove.isEmpty()) { + MineTweakerAPI.logWarning("No such rednet circuit: " + name); + } else { + for (IRedNetLogicCircuit toRemoveEntry : toRemove) { + MineTweakerAPI.apply(new RemoveCircuitAction(toRemoveEntry)); + } + } + } + + // ############################# + // ### Private inner classes ### + // ############################# + + private static class TweakerRedNetLogicCircuit implements IRedNetLogicCircuit { + private final String name; + private final String[] inputs; + private final String[] outputs; + private final IRedNetFunction function; + + public TweakerRedNetLogicCircuit(String name, String[] inputs, String[] outputs, IRedNetFunction function) { + this.name = name; + this.inputs = inputs; + this.outputs = outputs; + this.function = function; + } + + @Override + public int getInputCount() { + return inputs.length; + } + + @Override + public int getOutputCount() { + return outputs.length; + } + + @Override + public int[] recalculateOutputValues(long l, int[] ints) { + return function.calculate(l, ints); + } + + @Override + public String getUnlocalizedName() { + return name; + } + + @Override + public String getInputPinLabel(int i) { + return inputs[i]; + } + + @Override + public String getOutputPinLabel(int i) { + return outputs[i]; + } + + @Override + public void readFromNBT(NBTTagCompound nbttc) { + } + + @Override + public void writeToNBT(NBTTagCompound nbttc) { + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddCircuitAction implements IUndoableAction { + private final TweakerRedNetLogicCircuit circuit; + + public AddCircuitAction(TweakerRedNetLogicCircuit circuit) { + this.circuit = circuit; + } + + @Override + public void apply() { + FactoryRegistry.registerRedNetLogicCircuit(circuit); + } + + @Override + public boolean canUndo() { + return MFRHacks.redNetCircuits != null; + } + + @Override + public void undo() { + MFRHacks.redNetCircuits.remove(circuit); + } + + @Override + public String describe() { + return "Adding rednet circuit " + circuit.name; + } + + @Override + public String describeUndo() { + return "Removing rednet circuit " + circuit.name; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveCircuitAction implements IUndoableAction { + private final IRedNetLogicCircuit circuit; + + public RemoveCircuitAction(IRedNetLogicCircuit circuit) { + this.circuit = circuit; + } + + @Override + public void apply() { + MFRHacks.redNetCircuits.remove(circuit); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + MFRHacks.redNetCircuits.add(circuit); + } + + @Override + public String describe() { + return "Removing RedNet circuit " + circuit.getUnlocalizedName(); + } + + @Override + public String describeUndo() { + return "Restoring RedNet circuit " + circuit.getUnlocalizedName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/RubberTree.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/RubberTree.java new file mode 100644 index 0000000..bc7302c --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/RubberTree.java @@ -0,0 +1,117 @@ +/* + * 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.mfr.machines; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import minetweaker.mods.mfr.MFRHacks; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.RubberTree") +@ModOnly("MineFactoryReloaded") +public class RubberTree { + @ZenMethod + public static void addBiome(String biome) { + MineTweakerAPI.apply(new AddBiomeAction(biome)); + } + + @ZenMethod + public static void removeBiome(String biome) { + if (MFRHacks.rubberTreeBiomes == null) { + MineTweakerAPI.logWarning("Cannot remove rubber tree biomes"); + } else { + MineTweakerAPI.apply(new RemoveBiomeAction(biome)); + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddBiomeAction implements IUndoableAction { + private final String biome; + + public AddBiomeAction(String biome) { + this.biome = biome; + } + + @Override + public void apply() { + FactoryRegistry.registerRubberTreeBiome(biome); + } + + @Override + public boolean canUndo() { + return MFRHacks.rubberTreeBiomes != null; + } + + @Override + public void undo() { + MFRHacks.rubberTreeBiomes.remove(biome); + } + + @Override + public String describe() { + return "Adding rubber tree biome " + biome; + } + + @Override + public String describeUndo() { + return "Removing rubber tree biome " + biome; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveBiomeAction implements IUndoableAction { + private final String biome; + + private RemoveBiomeAction(String biome) { + this.biome = biome; + } + + @Override + public void apply() { + MFRHacks.rubberTreeBiomes.remove(biome); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + MFRHacks.rubberTreeBiomes.add(biome); + } + + @Override + public String describe() { + return "Removing rubber tree biome " + biome; + } + + @Override + public String describeUndo() { + return "Adding rubber tree biome " + biome; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/SafariNet.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/SafariNet.java new file mode 100644 index 0000000..4f19e4e --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/SafariNet.java @@ -0,0 +1,122 @@ +/* + * 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.mfr.machines; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.ModOnly; +import static minetweaker.mc164.util.MineTweakerPlatformUtils.getLivingEntityClass; +import minetweaker.mods.mfr.MFRHacks; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.AutoSpawner") +@ModOnly("MineFactoryReloaded") +public class SafariNet { + @ZenMethod + public static void addBlacklist(String entityClassName) { + Class entityClass = getLivingEntityClass(entityClassName); + MineTweakerAPI.apply(new AddBlacklistAction(entityClass)); + } + + @ZenMethod + public static void removeBlacklist(String entityClassName) { + Class entityClass = getLivingEntityClass(entityClassName); + if (MFRHacks.safariNetBlacklist == null) { + MineTweakerAPI.logWarning("Cannot remove safari net blacklist entries"); + } else if (!MFRHacks.safariNetBlacklist.contains(entityClass)) { + MineTweakerAPI.logWarning(entityClassName + " is not in the safari net blacklist"); + } else { + MineTweakerAPI.apply(new RemoveBlacklistAction(entityClass)); + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddBlacklistAction implements IUndoableAction { + private final Class entityClass; + + public AddBlacklistAction(Class entityClass) { + this.entityClass = entityClass; + } + + @Override + public void apply() { + FactoryRegistry.registerSafariNetBlacklist(entityClass); + } + + @Override + public boolean canUndo() { + return MFRHacks.safariNetBlacklist != null; + } + + @Override + public void undo() { + MFRHacks.safariNetBlacklist.remove(entityClass); + } + + @Override + public String describe() { + return "Blacklisting " + entityClass.getName() + " in the safari net"; + } + + @Override + public String describeUndo() { + return "Removing " + entityClass.getName() + " from the safari net blacklist"; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveBlacklistAction implements IUndoableAction { + private final Class entityClass; + + public RemoveBlacklistAction(Class entityClass) { + this.entityClass = entityClass; + } + + @Override + public void apply() { + MFRHacks.safariNetBlacklist.remove(entityClass); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + MFRHacks.safariNetBlacklist.add(entityClass); + } + + @Override + public String describe() { + return "Removing " + entityClass.getName() + " from the safari net blacklist"; + } + + @Override + public String describeUndo() { + return "Restoring " + entityClass.getName() + " to the safari net blacklist"; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/SludgeBoiler.java b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/SludgeBoiler.java new file mode 100644 index 0000000..eb39a3c --- /dev/null +++ b/MineTweaker3-MC164-Mod-MFR/src/main/java/minetweaker/mods/mfr/machines/SludgeBoiler.java @@ -0,0 +1,139 @@ +/* + * 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.mfr.machines; + +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.WeightedItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.mods.mfr.MFRHacks; +import powercrystals.core.random.WeightedRandomItemStack; +import powercrystals.minefactoryreloaded.api.FactoryRegistry; +import stanhebben.zenscript.annotations.ZenClass; +import stanhebben.zenscript.annotations.ZenMethod; + +/** + * + * @author Stan + */ +@ZenClass("mods.mfr.SludgeBoiler") +@ModOnly("MineFactoryReloaded") +public class SludgeBoiler { + @ZenMethod + public static void addDrop(WeightedItemStack item) { + MineTweakerAPI.apply(new AddDropAction(item)); + } + + @ZenMethod + public static void removeDrop(IIngredient item) { + if (MFRHacks.sludgeDrops == null) { + MineTweakerAPI.logWarning("Cannot remove drops from the sludge boiler"); + } else { + MineTweakerAPI.apply(new RemoveDropAction(item)); + } + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddDropAction implements IUndoableAction { + private final WeightedRandomItemStack item; + + public AddDropAction(WeightedItemStack item) { + this.item = new WeightedRandomItemStack((int) item.getChance(), MineTweakerMC.getItemStack(item.getStack())); + } + + @Override + public void apply() { + if (MFRHacks.sludgeDrops == null) { + FactoryRegistry.registerSludgeDrop(item.itemWeight, item.getStack()); + } else { + MFRHacks.sludgeDrops.add(item); + } + } + + @Override + public boolean canUndo() { + return MFRHacks.sludgeDrops != null; + } + + @Override + public void undo() { + MFRHacks.sludgeDrops.remove(item); + } + + @Override + public String describe() { + return "Adding sludge boiler drop " + item.getStack().getDisplayName(); + } + + @Override + public String describeUndo() { + return "Removing sludge boiler drop " + item.getStack().getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveDropAction implements IUndoableAction { + private final IIngredient item; + private final List toRemove; + + private RemoveDropAction(IIngredient item) { + this.item = item; + + toRemove = new ArrayList(); + for (WeightedRandomItemStack itemStack : MFRHacks.sludgeDrops) { + if (item.matches(MineTweakerMC.getIItemStack(itemStack.getStack()))) { + toRemove.add(itemStack); + } + } + } + + @Override + public void apply() { + for (WeightedRandomItemStack itemStack : toRemove) { + MFRHacks.sludgeDrops.remove(itemStack); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + for (WeightedRandomItemStack item : toRemove) { + MFRHacks.sludgeDrops.add(item); + } + } + + @Override + public String describe() { + return "Removing " + toRemove.size() + " sludge boiler drops for " + item; + } + + @Override + public String describeUndo() { + return "Restoring " + toRemove.size() + " sludge boiler drops for " + item; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC164-Mod-NEI - kopie/src/main/java/minetweaker/mods/nei/NEI.java b/MineTweaker3-MC164-Mod-NEI - kopie/src/main/java/minetweaker/mods/nei/NEI.java deleted file mode 100644 index 2b8c521..0000000 --- a/MineTweaker3-MC164-Mod-NEI - kopie/src/main/java/minetweaker/mods/nei/NEI.java +++ /dev/null @@ -1,165 +0,0 @@ -package minetweaker.mods.nei; - -import codechicken.nei.api.API; -import net.minecraft.item.ItemStack; -import stanhebben.zenscript.annotations.NotNull; -import stanhebben.zenscript.annotations.ZenClass; -import stanhebben.zenscript.annotations.ZenMethod; -import minetweaker.IUndoableAction; -import minetweaker.MineTweakerAPI; -import minetweaker.OneWayAction; -import minetweaker.annotations.ModOnly; -import minetweaker.api.item.IItemStack; -import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; - -/** - * MineTweaker NEI support. - * - * Enables hiding NEI items as well as adding new item stacks. These item stacks - * can then show a custom message or contain NBT data. Can be used to show - * a custom message or lore with certain items, or to provide spawnable items - * with specific NBT tags. - * - * @author Stan Hebben - */ -@ZenClass("mods.nei.NEI") -@ModOnly("NotEnoughItems") -public class NEI { - /** - * Hides a specific item in NEI. Will take into account metadata values, if - * any. - * - * @param item item to be hidden - */ - @ZenMethod - public static void hide(@NotNull IItemStack item) { - MineTweakerAPI.apply(new NEIHideItemAction(getItemStack(item))); - } - - /** - * Adds a NEI entry. The item stack can contain damage values and NBT tags. - * - * @param stack item stack to be added - */ - @ZenMethod - public static void addEntry(@NotNull IItemStack stack) { - MineTweakerAPI.apply(new NEIAddEntryAction(getItemStack(stack))); - } - - /** - * Overrides a name in NEI. Note that this will not change the original - * display name, but it will change the way it is displayed in NEI. - * - * @param item item - * @param name item name - */ - @ZenMethod - public static void overrideName(@NotNull IItemStack item, @NotNull String name) { - MineTweakerAPI.apply(new NEIOverrideNameAction(getItemStack(item), name)); - } - - // ############################# - // ### Private inner classes ### - // ############################# - - private static class NEIAddEntryAction implements IUndoableAction { - private final ItemStack item; - - public NEIAddEntryAction(ItemStack item) { - this.item = item; - } - - @Override - public void apply() { - API.addNBTItem(item); - } - - @Override - public boolean canUndo() { - return true; - } - - @Override - public void undo() { - API.hideItem(item.itemID); - } - - @Override - public String describe() { - return "Adding " + item.getDisplayName() + " as NEI entry"; - } - - @Override - public String describeUndo() { - return "Removing " + item.getDisplayName() + " as NEI entry"; - } - - @Override - public Object getOverrideKey() { - return null; - } - } - - private static class NEIHideItemAction implements IUndoableAction { - private final ItemStack stack; - - public NEIHideItemAction(ItemStack stack) { - this.stack = stack; - } - - @Override - public void apply() { - API.hideItem(stack.itemID); - } - - @Override - public boolean canUndo() { - return true; - } - - @Override - public void undo() { - API.addNBTItem(stack); - } - - @Override - public String describe() { - return "Hiding " + stack.getUnlocalizedName() + " in NEI"; - } - - @Override - public String describeUndo() { - return "Displaying " + stack.getUnlocalizedName() + " in NEI"; - } - - @Override - public Object getOverrideKey() { - return null; - } - } - - private static class NEIOverrideNameAction extends OneWayAction { - private final ItemStack item; - private final String name; - - public NEIOverrideNameAction(ItemStack item, String name) { - this.item = item; - this.name = name; - } - - @Override - public void apply() { - API.setOverrideName(item.itemID, item.getItemDamage(), name); - } - - @Override - public String describe() { - return "Overriding NEI item name of " + item.getUnlocalizedName() + " to " + name; - } - - @Override - public Object getOverrideKey() { - return null; - } - } -} diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java index d3585ea..573f3da 100644 --- a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java @@ -1,21 +1,35 @@ package minetweaker.api.minecraft; +import java.util.HashMap; import java.util.List; +import java.util.Map; import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; import minetweaker.api.data.IData; import minetweaker.api.item.IIngredient; import minetweaker.api.item.IItemStack; +import minetweaker.api.liquid.ILiquidStack; import minetweaker.api.oredict.IOreDictEntry; import minetweaker.api.player.IPlayer; +import minetweaker.api.world.IDimension; +import minetweaker.mc1710.block.MCBlockDefinition; +import minetweaker.mc1710.block.MCSpecificBlock; import minetweaker.mc1710.data.NBTConverter; import minetweaker.mc1710.item.MCItemStack; import minetweaker.mc1710.oredict.MCOreDictEntry; import minetweaker.mc1710.player.MCPlayer; +import minetweaker.mc1710.world.MCDimension; +import minetweaker.mc1710.block.MCWorldBlock; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.OreDictionary; /** @@ -24,6 +38,8 @@ import net.minecraftforge.oredict.OreDictionary; * @author Stan Hebben */ public class MineTweakerMC { + private static final Map blockDefinitions = new HashMap(); + private MineTweakerMC() {} /** @@ -286,4 +302,73 @@ public class MineTweakerMC { return (NBTTagCompound) NBTConverter.from(data); } + + /** + * Retrieves the block at the given position. + * + * @param blocks block access + * @param x block x position + * @param y block y position + * @param z block z position + * @return block instance + */ + public static IBlock getBlock(IBlockAccess blocks, int x, int y, int z) { + return new MCWorldBlock(blocks, x, y, z); + } + + /** + * Retrieves the block definition for the given block. + * + * @param block block object + * @return block definition + */ + public static IBlockDefinition getBlockDefinition(Block block) { + if (!blockDefinitions.containsKey(block)) { + blockDefinitions.put(block, new MCBlockDefinition(block)); + } + return blockDefinitions.get(block); + } + + /** + * Retrieves the dimension instance for a given world. + * + * @param world world + * @return dimension + */ + public static IDimension getDimension(World world) { + if (world == null) return null; + + return new MCDimension(world); + } + + /** + * Returns an instance of the given block. + * + * @param block MC block definition + * @return MT block instance + */ + public static IBlock getBlockAnyMeta(Block block) { + return new MCSpecificBlock(block, OreDictionary.WILDCARD_VALUE); + } + + /** + * Returns an instance of the given block. + * + * @param block MC block definition + * @param meta block meta value + * @return MT block instance + */ + public static IBlock getBlock(Block block, int meta) { + return new MCSpecificBlock(block, meta); + } + + /** + * Retrieves the internal fluid stack of the given stack. + * + * @param stack MT liquid stack + * @return MCF fluid stack + */ + public static FluidStack getLiquidStack(ILiquidStack stack) { + return (FluidStack) stack.getInternal(); + } } diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/ForgeEventHandler.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/ForgeEventHandler.java index 5a8d264..69f3265 100644 --- a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/ForgeEventHandler.java +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/ForgeEventHandler.java @@ -8,12 +8,28 @@ package minetweaker.mc1710; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.PlayerEvent; +import minetweaker.MineTweakerImplementationAPI; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; /** * * @author Stan */ public class ForgeEventHandler { + @SubscribeEvent + public void onPlayerInteract(PlayerInteractEvent ev) { + System.out.println("Player interact"); + + minetweaker.api.event.PlayerInteractEvent event = new minetweaker.api.event.PlayerInteractEvent( + MineTweakerMC.getIPlayer(ev.entityPlayer), + MineTweakerMC.getDimension(ev.world), + ev.x, ev.y, ev.z + ); + + MineTweakerImplementationAPI.events.publishPlayerInteract(event); + } + @SubscribeEvent public void onCrafted(PlayerEvent.ItemCraftedEvent ev) { diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/MineTweakerMod.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/MineTweakerMod.java index 5774507..87b2aeb 100644 --- a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/MineTweakerMod.java +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/MineTweakerMod.java @@ -92,7 +92,7 @@ public class MineTweakerMod { @EventHandler public void onLoad(FMLPreInitializationEvent ev) { - MinecraftForge.EVENT_BUS.register(new FMLEventHandler()); + MinecraftForge.EVENT_BUS.register(new ForgeEventHandler()); FMLCommonHandler.instance().bus().register(new FMLEventHandler()); } diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCBlockDefinition.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCBlockDefinition.java new file mode 100644 index 0000000..6d992ae --- /dev/null +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCBlockDefinition.java @@ -0,0 +1,27 @@ +/* + * 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.mc1710.block; + +import minetweaker.api.block.IBlockDefinition; +import net.minecraft.block.Block; + +/** + * + * @author Stan + */ +public class MCBlockDefinition implements IBlockDefinition { + private final Block block; + + public MCBlockDefinition(Block block) { + this.block = block; + } + + @Override + public String getId() { + return Block.blockRegistry.getNameForObject(block); + } +} diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCItemBlock.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCItemBlock.java new file mode 100644 index 0000000..e41f9f5 --- /dev/null +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCItemBlock.java @@ -0,0 +1,71 @@ +/* + * 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.mc1710.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCItemBlock implements IBlock { + private final ItemStack item; + + public MCItemBlock(ItemStack item) { + this.item = item; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(Block.getBlockFromItem(item.getItem())); + } + + @Override + public int getMeta() { + return item.getItemDamage(); + } + + @Override + public IData getTileData() { + if (item.stackTagCompound == null) + return null; + + return MineTweakerMC.getIData(item.stackTagCompound); + } + + @Override + public String getDisplayName() { + return item.getDisplayName(); + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return getDefinition() == block.getDefinition() + && (getMeta() == OreDictionary.WILDCARD_VALUE || getMeta() == block.getMeta()) + && (getTileData() == null || (block.getTileData() != null && block.getTileData().contains(getTileData()))); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } +} diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCSpecificBlock.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCSpecificBlock.java new file mode 100644 index 0000000..800d755 --- /dev/null +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCSpecificBlock.java @@ -0,0 +1,68 @@ +/* + * 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.mc1710.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCSpecificBlock implements IBlock { + private final Block block; + private final int meta; + + public MCSpecificBlock(Block block, int meta) { + this.block = block; + this.meta = meta; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(block); + } + + @Override + public int getMeta() { + return meta; + } + + @Override + public IData getTileData() { + return null; + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return block.getDefinition() == getDefinition() + && (meta == OreDictionary.WILDCARD_VALUE || block.getMeta() == meta); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } + + @Override + public String getDisplayName() { + return block.getLocalizedName(); + } +} diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCWorldBlock.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCWorldBlock.java new file mode 100644 index 0000000..09cac4d --- /dev/null +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/block/MCWorldBlock.java @@ -0,0 +1,91 @@ +/* + * 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.mc1710.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCWorldBlock implements IBlock { + private final IBlockAccess blocks; + private final int x; + private final int y; + private final int z; + + public MCWorldBlock(IBlockAccess blocks, int x, int y, int z) { + this.blocks = blocks; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(blocks.getBlock(x, y, z)); + } + + @Override + public int getMeta() { + return blocks.getBlockMetadata(x, y, z); + } + + @Override + public IData getTileData() { + TileEntity tileEntity = blocks.getTileEntity(x, y, z); + + if (tileEntity == null) + return null; + + NBTTagCompound nbt = new NBTTagCompound(); + tileEntity.writeToNBT(nbt); + return MineTweakerMC.getIData(nbt); + } + + @Override + public String getDisplayName() { + Block block = blocks.getBlock(x, y, z); + Item item = Item.getItemFromBlock(block); + if (item != null) { + return (new ItemStack(item, 1, getMeta())).getDisplayName(); + } else { + return block.getLocalizedName(); + } + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return getDefinition() == block.getDefinition() + && (getMeta() == OreDictionary.WILDCARD_VALUE || getMeta() == block.getMeta()) + && (getTileData() == null || (block.getTileData() != null && block.getTileData().contains(getTileData()))); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } +} diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/item/MCItemStack.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/item/MCItemStack.java index 831c166..b5f50a3 100644 --- a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/item/MCItemStack.java +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/item/MCItemStack.java @@ -9,6 +9,7 @@ package minetweaker.mc1710.item; import java.util.Collections; import java.util.List; import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlock; import minetweaker.api.data.DataMap; import minetweaker.mc1710.data.NBTConverter; import minetweaker.mc1710.liquid.MCLiquidStack; @@ -19,11 +20,14 @@ import minetweaker.api.item.IItemDefinition; import minetweaker.api.item.IItemStack; import minetweaker.api.item.IItemTransformer; import minetweaker.api.item.IngredientItem; +import minetweaker.api.item.IngredientOr; import minetweaker.api.item.WeightedItemStack; import minetweaker.api.liquid.ILiquidStack; import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; import minetweaker.mc1710.actions.SetTranslationAction; +import minetweaker.mc1710.block.MCItemBlock; import minetweaker.util.ArrayUtil; +import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -212,12 +216,17 @@ public class MCItemStack implements IItemStack { public IIngredient marked(String mark) { return new IngredientItem(this, mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } @Override public boolean matches(IItemStack item) { ItemStack internal = getItemStack(item); return internal.getItem() == stack.getItem() - && (wildcardSize || internal.stackSize == stack.stackSize) + && (wildcardSize || internal.stackSize >= stack.stackSize) && (stack.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack.getItemDamage() == internal.getItemDamage() || (!stack.getHasSubtypes() && !stack.getItem().isDamageable())); @@ -244,6 +253,15 @@ public class MCItemStack implements IItemStack { public Object getInternal() { return stack; } + + @Override + public IBlock asBlock() { + if (Block.getBlockFromItem(stack.getItem()) == null) { + throw new ClassCastException("This item is not a block"); + } else { + return new MCItemBlock(stack); + } + } // ############################# // ### Object implementation ### diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/oredict/MCOreDictEntry.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/oredict/MCOreDictEntry.java index 4c75a60..4d57511 100644 --- a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/oredict/MCOreDictEntry.java +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/oredict/MCOreDictEntry.java @@ -15,6 +15,7 @@ import minetweaker.api.item.IIngredient; import minetweaker.api.item.IItemCondition; import minetweaker.api.item.IItemStack; import minetweaker.api.item.IItemTransformer; +import minetweaker.api.item.IngredientOr; import minetweaker.api.item.IngredientStack; import static minetweaker.api.minecraft.MineTweakerMC.getIItemStackWildcardSize; import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; @@ -146,6 +147,11 @@ public class MCOreDictEntry implements IOreDictEntry { public IIngredient marked(String mark) { return new IngredientOreDict(this, mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } @Override public boolean matches(IItemStack item) { diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/player/MCPlayer.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/player/MCPlayer.java index 019569c..9e84f25 100644 --- a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/player/MCPlayer.java +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/player/MCPlayer.java @@ -97,4 +97,19 @@ public class MCPlayer implements IPlayer { (EntityPlayerMP) player); } } + + @Override + public boolean equals(Object other) { + if (other.getClass() != this.getClass()) + return false; + + return ((MCPlayer) other).player == player; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 23 * hash + (this.player != null ? this.player.hashCode() : 0); + return hash; + } } diff --git a/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/world/MCDimension.java b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/world/MCDimension.java new file mode 100644 index 0000000..c83d25f --- /dev/null +++ b/MineTweaker3-MC1710-Main/src/main/java/minetweaker/mc1710/world/MCDimension.java @@ -0,0 +1,44 @@ +/* + * 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.mc1710.world; + +import minetweaker.api.block.IBlock; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.world.IDimension; +import net.minecraft.world.World; + +/** + * + * @author Stan + */ +public class MCDimension implements IDimension { + private final World world; + + public MCDimension(World world) { + this.world = world; + } + + @Override + public boolean isDay() { + return world.isDaytime(); + } + + @Override + public int getBrightness(int x, int y, int z) { + return world.getBlockLightValue(x, y, z); + } + + @Override + public IDimension getDimension() { + return this; + } + + @Override + public IBlock getBlock(int x, int y, int z) { + return MineTweakerMC.getBlock(world, x, y, z); + } +} 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 0400f9c..7ebc44c 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 @@ -1,21 +1,35 @@ package minetweaker.api.minecraft; +import java.util.HashMap; import java.util.List; +import java.util.Map; import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; import minetweaker.api.data.IData; import minetweaker.api.item.IIngredient; import minetweaker.api.item.IItemStack; +import minetweaker.api.liquid.ILiquidStack; import minetweaker.api.oredict.IOreDictEntry; import minetweaker.api.player.IPlayer; +import minetweaker.api.world.IDimension; +import minetweaker.mc172.block.MCBlockDefinition; +import minetweaker.mc172.block.MCSpecificBlock; +import minetweaker.mc172.block.MCWorldBlock; import minetweaker.mc172.data.NBTConverter; import minetweaker.mc172.item.MCItemStack; import minetweaker.mc172.oredict.MCOreDictEntry; import minetweaker.mc172.player.MCPlayer; +import minetweaker.mc172.world.MCDimension; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.OreDictionary; /** @@ -24,6 +38,8 @@ import net.minecraftforge.oredict.OreDictionary; * @author Stan Hebben */ public class MineTweakerMC { + private static final Map blockDefinitions = new HashMap(); + private MineTweakerMC() {} /** @@ -287,4 +303,73 @@ public class MineTweakerMC { return (NBTTagCompound) NBTConverter.from(data); } + + /** + * Retrieves the block at the given position. + * + * @param blocks block access + * @param x block x position + * @param y block y position + * @param z block z position + * @return block instance + */ + public static IBlock getBlock(IBlockAccess blocks, int x, int y, int z) { + return new MCWorldBlock(blocks, x, y, z); + } + + /** + * Retrieves the block definition for the given block. + * + * @param block block object + * @return block definition + */ + public static IBlockDefinition getBlockDefinition(Block block) { + if (!blockDefinitions.containsKey(block)) { + blockDefinitions.put(block, new MCBlockDefinition(block)); + } + return blockDefinitions.get(block); + } + + /** + * Retrieves the dimension instance for a given world. + * + * @param world world + * @return dimension + */ + public static IDimension getDimension(World world) { + if (world == null) return null; + + return new MCDimension(world); + } + + /** + * Returns an instance of the given block. + * + * @param block MC block definition + * @return MT block instance + */ + public static IBlock getBlockAnyMeta(Block block) { + return new MCSpecificBlock(block, OreDictionary.WILDCARD_VALUE); + } + + /** + * Returns an instance of the given block. + * + * @param block MC block definition + * @param meta block meta value + * @return MT block instance + */ + public static IBlock getBlock(Block block, int meta) { + return new MCSpecificBlock(block, meta); + } + + /** + * Retrieves the internal fluid stack of the given stack. + * + * @param stack MT liquid stack + * @return MCF fluid stack + */ + public static FluidStack getLiquidStack(ILiquidStack stack) { + return (FluidStack) stack.getInternal(); + } } diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCBlockDefinition.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCBlockDefinition.java new file mode 100644 index 0000000..2cc7eb1 --- /dev/null +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCBlockDefinition.java @@ -0,0 +1,27 @@ +/* + * 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.mc172.block; + +import minetweaker.api.block.IBlockDefinition; +import net.minecraft.block.Block; + +/** + * + * @author Stan + */ +public class MCBlockDefinition implements IBlockDefinition { + private final Block block; + + public MCBlockDefinition(Block block) { + this.block = block; + } + + @Override + public String getId() { + return Block.blockRegistry.getNameForObject(block); + } +} diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCItemBlock.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCItemBlock.java new file mode 100644 index 0000000..5c7f07d --- /dev/null +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCItemBlock.java @@ -0,0 +1,71 @@ +/* + * 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.mc172.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCItemBlock implements IBlock { + private final ItemStack item; + + public MCItemBlock(ItemStack item) { + this.item = item; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(Block.getBlockFromItem(item.getItem())); + } + + @Override + public int getMeta() { + return item.getItemDamage(); + } + + @Override + public IData getTileData() { + if (item.stackTagCompound == null) + return null; + + return MineTweakerMC.getIData(item.stackTagCompound); + } + + @Override + public String getDisplayName() { + return item.getDisplayName(); + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return getDefinition() == block.getDefinition() + && (getMeta() == OreDictionary.WILDCARD_VALUE || getMeta() == block.getMeta()) + && (getTileData() == null || (block.getTileData() != null && block.getTileData().contains(getTileData()))); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } +} diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCSpecificBlock.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCSpecificBlock.java new file mode 100644 index 0000000..03bcbba --- /dev/null +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCSpecificBlock.java @@ -0,0 +1,68 @@ +/* + * 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.mc172.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCSpecificBlock implements IBlock { + private final Block block; + private final int meta; + + public MCSpecificBlock(Block block, int meta) { + this.block = block; + this.meta = meta; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(block); + } + + @Override + public int getMeta() { + return meta; + } + + @Override + public IData getTileData() { + return null; + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return block.getDefinition() == getDefinition() + && (meta == OreDictionary.WILDCARD_VALUE || block.getMeta() == meta); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } + + @Override + public String getDisplayName() { + return block.getLocalizedName(); + } +} diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCWorldBlock.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCWorldBlock.java new file mode 100644 index 0000000..dcb3778 --- /dev/null +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/block/MCWorldBlock.java @@ -0,0 +1,91 @@ +/* + * 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.mc172.block; + +import java.util.Collections; +import java.util.List; +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCWorldBlock implements IBlock { + private final IBlockAccess blocks; + private final int x; + private final int y; + private final int z; + + public MCWorldBlock(IBlockAccess blocks, int x, int y, int z) { + this.blocks = blocks; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(blocks.getBlock(x, y, z)); + } + + @Override + public int getMeta() { + return blocks.getBlockMetadata(x, y, z); + } + + @Override + public IData getTileData() { + TileEntity tileEntity = blocks.getTileEntity(x, y, z); + + if (tileEntity == null) + return null; + + NBTTagCompound nbt = new NBTTagCompound(); + tileEntity.writeToNBT(nbt); + return MineTweakerMC.getIData(nbt); + } + + @Override + public String getDisplayName() { + Block block = blocks.getBlock(x, y, z); + Item item = Item.getItemFromBlock(block); + if (item != null) { + return (new ItemStack(item, 1, getMeta())).getDisplayName(); + } else { + return block.getLocalizedName(); + } + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return getDefinition() == block.getDefinition() + && (getMeta() == OreDictionary.WILDCARD_VALUE || getMeta() == block.getMeta()) + && (getTileData() == null || (block.getTileData() != null && block.getTileData().contains(getTileData()))); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } +} diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/item/MCItemStack.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/item/MCItemStack.java index e2e0a25..c45da2c 100644 --- a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/item/MCItemStack.java +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/item/MCItemStack.java @@ -9,6 +9,7 @@ package minetweaker.mc172.item; import java.util.Collections; import java.util.List; import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlock; import minetweaker.api.data.DataMap; import minetweaker.mc172.data.NBTConverter; import minetweaker.mc172.liquid.MCLiquidStack; @@ -19,11 +20,14 @@ import minetweaker.api.item.IItemDefinition; import minetweaker.api.item.IItemStack; import minetweaker.api.item.IItemTransformer; import minetweaker.api.item.IngredientItem; +import minetweaker.api.item.IngredientOr; import minetweaker.api.item.WeightedItemStack; import minetweaker.api.liquid.ILiquidStack; import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; import minetweaker.mc172.actions.SetTranslationAction; +import minetweaker.mc172.block.MCItemBlock; import minetweaker.util.ArrayUtil; +import net.minecraft.block.Block; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -212,12 +216,17 @@ public class MCItemStack implements IItemStack { public IIngredient marked(String mark) { return new IngredientItem(this, mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } @Override public boolean matches(IItemStack item) { ItemStack internal = getItemStack(item); return internal.getItem() == stack.getItem() - && (wildcardSize || internal.stackSize == stack.stackSize) + && (wildcardSize || internal.stackSize >= stack.stackSize) && (stack.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack.getItemDamage() == internal.getItemDamage() || (!stack.getHasSubtypes() && !stack.getItem().isDamageable())); @@ -240,6 +249,15 @@ public class MCItemStack implements IItemStack { return false; } + @Override + public IBlock asBlock() { + if (Block.getBlockFromItem(stack.getItem()) == null) { + throw new ClassCastException("This item is not a block"); + } else { + return new MCItemBlock(stack); + } + } + @Override public Object getInternal() { return stack; diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/oredict/MCOreDictEntry.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/oredict/MCOreDictEntry.java index aea2b7a..a5815e2 100644 --- a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/oredict/MCOreDictEntry.java +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/oredict/MCOreDictEntry.java @@ -15,6 +15,7 @@ import minetweaker.api.item.IIngredient; import minetweaker.api.item.IItemCondition; import minetweaker.api.item.IItemStack; import minetweaker.api.item.IItemTransformer; +import minetweaker.api.item.IngredientOr; import minetweaker.api.item.IngredientStack; import static minetweaker.api.minecraft.MineTweakerMC.getIItemStackWildcardSize; import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; @@ -146,6 +147,11 @@ public class MCOreDictEntry implements IOreDictEntry { public IIngredient marked(String mark) { return new IngredientOreDict(this, mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } @Override public boolean matches(IItemStack item) { diff --git a/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/world/MCDimension.java b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/world/MCDimension.java new file mode 100644 index 0000000..89e1585 --- /dev/null +++ b/MineTweaker3-MC172-Main/src/main/java/minetweaker/mc172/world/MCDimension.java @@ -0,0 +1,44 @@ +/* + * 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.mc172.world; + +import minetweaker.api.block.IBlock; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.world.IDimension; +import net.minecraft.world.World; + +/** + * + * @author Stan + */ +public class MCDimension implements IDimension { + private final World world; + + public MCDimension(World world) { + this.world = world; + } + + @Override + public boolean isDay() { + return world.isDaytime(); + } + + @Override + public int getBrightness(int x, int y, int z) { + return world.getBlockLightValue(x, y, z); + } + + @Override + public IDimension getDimension() { + return this; + } + + @Override + public IBlock getBlock(int x, int y, int z) { + return MineTweakerMC.getBlock(world, x, y, z); + } +} diff --git a/MineTweaker3-Web/index.html b/MineTweaker3-Web/index.html index d7e89f7..9b09ee6 100644 --- a/MineTweaker3-Web/index.html +++ b/MineTweaker3-Web/index.html @@ -96,9 +96,10 @@

Downloads

-

1.6.4 - 3.0.5

-

1.7.2 - 3.0.5

-

1.7.10 - 3.0.5

+

Installation: it's a forge mod. Make sure you have Forge installed and put it in your mods folder. No configuration needed, just follow the wiki tutorials to start scripting!

+

1.6.4 - 3.0.6

+

1.7.2 - 3.0.6

+

1.7.10 - 3.0.6

Forums

diff --git a/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionArray.java b/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionArray.java index 1c7e9dc..85a8c40 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionArray.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionArray.java @@ -52,17 +52,18 @@ public class ExpressionArray extends Expression { @Override public void compile(boolean result, IEnvironmentMethod environment) { - Type baseType = type.getBaseType().toASMType(); + ZenType baseType = type.getBaseType(); + Type asmBaseType = type.getBaseType().toASMType(); MethodOutput output = environment.getOutput(); output.constant(contents.length); - output.newArray(baseType); + output.newArray(asmBaseType); for (int i = 0; i < contents.length; i++) { output.dup(); output.constant(i); - contents[i].compile(result, environment); - output.arrayStore(baseType); + contents[i].cast(this.getPosition(), environment, baseType).compile(result, environment); + output.arrayStore(asmBaseType); } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionMapIndexGet.java b/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionMapIndexGet.java index c45330e..757c7f1 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionMapIndexGet.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionMapIndexGet.java @@ -46,6 +46,7 @@ public class ExpressionMapIndexGet extends Expression { internal(Map.class), "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); + environment.getOutput().checkCast(type.toASMType().getInternalName()); } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionTable.java b/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionTable.java index c16896c..71ad385 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionTable.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/expression/ExpressionTable.java @@ -14,7 +14,7 @@ import static stanhebben.zenscript.util.ZenTypeUtil.internal; public class ExpressionTable extends Expression { private final Expression[] keys; private final Expression[] values; - private final ZenType type; + private final ZenTypeAssociative type; public ExpressionTable(ZenPosition position, Expression[] keys, Expression[] values) { super(position); @@ -25,7 +25,7 @@ public class ExpressionTable extends Expression { type = new ZenTypeAssociative(ZenTypeAny.INSTANCE, ZenTypeAny.INSTANCE); } - public ExpressionTable(ZenPosition position, Expression[] keys, Expression[] values, ZenType type) { + public ExpressionTable(ZenPosition position, Expression[] keys, Expression[] values, ZenTypeAssociative type) { super(position); this.keys = keys; @@ -42,6 +42,9 @@ public class ExpressionTable extends Expression { @Override public void compile(boolean result, IEnvironmentMethod environment) { if (result) { + ZenType keyType = type.getKeyType(); + ZenType valueType = type.getValueType(); + MethodOutput output = environment.getOutput(); output.newObject(HashMap.class); output.dup(); @@ -49,8 +52,8 @@ public class ExpressionTable extends Expression { for (int i = 0; i < keys.length; i++) { output.dup(); - keys[i].compile(true, environment); - values[i].compile(true, environment); + keys[i].cast(getPosition(), environment, keyType).compile(true, environment); + values[i].cast(getPosition(), environment, valueType).compile(true, environment); output.invokeInterface(internal(Map.class), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); output.pop(); } @@ -76,7 +79,7 @@ public class ExpressionTable extends Expression { newValues[i] = values[i].cast(position, environment, keyType.getValueType()); } - return new ExpressionTable(getPosition(), newKeys, newValues, type); + return new ExpressionTable(getPosition(), newKeys, newValues, keyType); } else if (this.type.canCastImplicit(type, environment)) { return this.type.cast(position, environment, this, type); } else { diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeAny.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeAny.java index 1618827..b4b70fc 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeAny.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeAny.java @@ -2,6 +2,7 @@ package stanhebben.zenscript.type; import java.util.HashMap; import java.util.Map; +import org.objectweb.asm.Label; import org.objectweb.asm.Type; import stanhebben.zenscript.annotations.CompareType; import stanhebben.zenscript.annotations.OperatorType; @@ -78,62 +79,152 @@ public class ZenTypeAny extends ZenType { CASTERS.put("string", new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asString", String.class); + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); } }); CASTERS.put(Boolean.class.getName(), new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asBool", boolean.class); output.invokeStatic(Boolean.class, "valueOf", Boolean.class, boolean.class); + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); } }); CASTERS.put(Byte.class.getName(), new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asByte", boolean.class); output.invokeStatic(Byte.class, "valueOf", Byte.class, byte.class); + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); } }); CASTERS.put(Short.class.getName(), new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asShort", short.class); output.invokeStatic(Short.class, "valueOf", Short.class, short.class); + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); } }); CASTERS.put(Integer.class.getName(), new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asInt", int.class); output.invokeStatic(Integer.class, "valueOf", Integer.class, int.class); - } + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); + } }); CASTERS.put(Long.class.getName(), new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asLong", long.class); output.invokeStatic(Long.class, "valueOf", Long.class, long.class); + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); } }); CASTERS.put(Float.class.getName(), new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asFloat", float.class); output.invokeStatic(Float.class, "valueOf", Float.class, float.class); + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); } }); CASTERS.put(Double.class.getName(), new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asDouble", double.class); output.invokeStatic(Double.class, "valueOf", Double.class, double.class); + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); } }); CASTERS.put(String.class.getName(), new MethodCompiler() { @Override public void compile(MethodOutput output) { + Label lblNull = new Label(); + Label lblAfter = new Label(); + output.dup(); + output.ifNull(lblNull); output.invokeInterface(IAny.class, "asString", String.class); + output.goTo(lblAfter); + + output.label(lblNull); + output.pop(); + output.aConstNull(); + output.label(lblAfter); } }); } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeArrayBasic.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeArrayBasic.java index eba0d79..43516f4 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeArrayBasic.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeArrayBasic.java @@ -185,7 +185,7 @@ public class ZenTypeArrayBasic extends ZenTypeArray { methodOutput.dup(); methodOutput.arrayLength(); methodOutput.loadInt(index); - methodOutput.ifICmpGE(exit); + methodOutput.ifICmpLE(exit); methodOutput.dup(); methodOutput.loadInt(index); @@ -229,7 +229,7 @@ public class ZenTypeArrayBasic extends ZenTypeArray { methodOutput.dup(); methodOutput.arrayLength(); methodOutput.loadInt(locals[0]); - methodOutput.ifICmpGE(exit); + methodOutput.ifICmpLE(exit); methodOutput.dup(); methodOutput.loadInt(locals[0]); @@ -251,7 +251,7 @@ public class ZenTypeArrayBasic extends ZenTypeArray { @Override public ZenType getType(int i) { - return getBaseType(); + return i == 0 ? INT : getBaseType(); } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeAssociative.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeAssociative.java index 7d79f63..da43db9 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeAssociative.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeAssociative.java @@ -119,7 +119,7 @@ public class ZenTypeAssociative extends ZenType { public IPartialExpression getMember(ZenPosition position, IEnvironmentGlobal environment, IPartialExpression value, String name) { if (name.equals("length")) { return new ExpressionMapSize(position, value.eval(environment)); - } else if (ZenTypeString.INSTANCE.canCastImplicit(key, environment)) { + } else if (STRING.canCastImplicit(key, environment)) { return new ExpressionMapIndexGet( position, value.eval(environment), diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeBool.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeBool.java index 700035f..c40d410 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeBool.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeBool.java @@ -88,6 +88,14 @@ public class ZenTypeBool extends ZenType { @Override public Expression binary(ZenPosition position, IEnvironmentGlobal environment, Expression left, Expression right, OperatorType operator) { + if (operator == OperatorType.CAT) { + return STRING.binary( + position, + environment, + left.cast(position, environment, STRING), + right.cast(position, environment, STRING), OperatorType.CAT); + } + if (right.getType().canCastImplicit(BOOL, environment)) { switch (operator) { case AND: @@ -510,6 +518,27 @@ public class ZenTypeBool extends ZenType { public void defineIteratorMulti(MethodOutput output) { throwUnsupportedException(output, "bool", "iterator"); } + + @Override + public void defineEquals(MethodOutput output) { + Label lblEqual = new Label(); + output.loadObject(0); + output.loadObject(1); + + output.ifACmpEq(lblEqual); + + output.iConst0(); + output.returnInt(); + + output.label(lblEqual); + output.iConst1(); + output.returnInt(); + } + + @Override + public void defineHashCode(MethodOutput output) { + output.invokeSpecial("java/lang/Object", "hashCode", "()I"); + } private void getValue(MethodOutput output) { output.loadObject(0); diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeByte.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeByte.java index d5019bd..66a7291 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeByte.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeByte.java @@ -159,6 +159,14 @@ public class ZenTypeByte extends ZenType { @Override public Expression binary(ZenPosition position, IEnvironmentGlobal environment, Expression left, Expression right, OperatorType operator) { + if (operator == OperatorType.CAT) { + return STRING.binary( + position, + environment, + left.cast(position, environment, STRING), + right.cast(position, environment, STRING), OperatorType.CAT); + } + return new ExpressionArithmeticBinary(position, operator, left, right.cast(position, environment, this)); } @@ -567,6 +575,33 @@ public class ZenTypeByte extends ZenType { public void defineIteratorMulti(MethodOutput output) { throwUnsupportedException(output, "byte", "iterator"); } + + @Override + public void defineEquals(MethodOutput output) { + Label lblNope = new Label(); + + output.loadObject(1); + output.instanceOf(IAny.NAME); + output.ifEQ(lblNope); + + getValue(output); + output.loadObject(1); + output.invoke(METHOD_ASBYTE); + output.ifICmpNE(lblNope); + + output.iConst1(); + output.returnInt(); + + output.label(lblNope); + output.iConst0(); + output.returnInt(); + } + + @Override + public void defineHashCode(MethodOutput output) { + getValue(output); + output.returnInt(); + } private void getValue(MethodOutput output) { output.loadObject(0); diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeDouble.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeDouble.java index dec91f6..c5447e1 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeDouble.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeDouble.java @@ -167,6 +167,14 @@ public class ZenTypeDouble extends ZenType { @Override public Expression binary(ZenPosition position, IEnvironmentGlobal environment, Expression left, Expression right, OperatorType operator) { + if (operator == OperatorType.CAT) { + return STRING.binary( + position, + environment, + left.cast(position, environment, STRING), + right.cast(position, environment, STRING), OperatorType.CAT); + } + return new ExpressionArithmeticBinary(position, operator, left, right.cast(position, environment, this)); } @@ -562,5 +570,46 @@ public class ZenTypeDouble extends ZenType { output.loadObject(0); output.getField(ANY_NAME, "value", "D"); } + + @Override + public void defineEquals(MethodOutput output) { + Label lblNope = new Label(); + + output.loadObject(1); + output.instanceOf(IAny.NAME); + output.ifEQ(lblNope); + + getValue(output); + output.loadObject(1); + output.invoke(METHOD_ASDOUBLE); + output.dCmp(); + output.ifNE(lblNope); + + output.iConst1(); + output.returnInt(); + + output.label(lblNope); + output.iConst0(); + output.returnInt(); + } + + @Override + public void defineHashCode(MethodOutput output) { + // long bits = Double.doubleToLongBits(value); + // return (int) (bits ^ bits >> 32) + int bits = output.local(Type.LONG_TYPE); + output.invokeStatic(Double.class, "doubleToLongBits", double.class, long.class); + output.store(Type.LONG_TYPE, bits); + + output.load(Type.LONG_TYPE, bits); + output.l2i(); + output.load(Type.LONG_TYPE, bits); + output.constant(32); + output.lShr(); + output.l2i(); + output.iXor(); + + output.returnInt(); + } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeFloat.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeFloat.java index 775d3c8..edd98bf 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeFloat.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeFloat.java @@ -162,6 +162,14 @@ public class ZenTypeFloat extends ZenType { @Override public Expression binary(ZenPosition position, IEnvironmentGlobal environment, Expression left, Expression right, OperatorType operator) { + if (operator == OperatorType.CAT) { + return STRING.binary( + position, + environment, + left.cast(position, environment, STRING), + right.cast(position, environment, STRING), OperatorType.CAT); + } + return new ExpressionArithmeticBinary(position, operator, left, right.cast(position, environment, this)); } @@ -557,5 +565,35 @@ public class ZenTypeFloat extends ZenType { output.loadObject(0); output.getField(ANY_NAME, "value", "F"); } + + @Override + public void defineEquals(MethodOutput output) { + Label lblNope = new Label(); + + output.loadObject(1); + output.instanceOf(IAny.NAME); + output.ifEQ(lblNope); + + getValue(output); + output.loadObject(1); + output.invoke(METHOD_ASFLOAT); + output.fCmp(); + output.ifICmpNE(lblNope); + + output.iConst1(); + output.returnInt(); + + output.label(lblNope); + output.iConst0(); + output.returnInt(); + } + + @Override + public void defineHashCode(MethodOutput output) { + //return Float.floatToIntBits(value); + getValue(output); + output.invokeStatic(Float.class, "floatToIntBits", float.class, int.class); + output.returnInt(); + } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeInt.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeInt.java index 4930af5..ca6ce51 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeInt.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeInt.java @@ -158,6 +158,14 @@ public class ZenTypeInt extends ZenType { @Override public Expression binary(ZenPosition position, IEnvironmentGlobal environment, Expression left, Expression right, OperatorType operator) { + if (operator == OperatorType.CAT) { + return STRING.binary( + position, + environment, + left.cast(position, environment, STRING), + right.cast(position, environment, STRING), OperatorType.CAT); + } + return new ExpressionArithmeticBinary(position, operator, left, right.cast(position, environment, this)); } @@ -578,5 +586,32 @@ public class ZenTypeInt extends ZenType { output.loadObject(0); output.getField(ANY_NAME, "value", "I"); } + + @Override + public void defineEquals(MethodOutput output) { + Label lblNope = new Label(); + + output.loadObject(1); + output.instanceOf(IAny.NAME); + output.ifEQ(lblNope); + + getValue(output); + output.loadObject(1); + output.invoke(METHOD_ASINT); + output.ifICmpNE(lblNope); + + output.iConst1(); + output.returnInt(); + + output.label(lblNope); + output.iConst0(); + output.returnInt(); + } + + @Override + public void defineHashCode(MethodOutput output) { + getValue(output); + output.returnInt(); + } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeLong.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeLong.java index 1e1db79..5a17833 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeLong.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeLong.java @@ -162,6 +162,14 @@ public class ZenTypeLong extends ZenType { @Override public Expression binary(ZenPosition position, IEnvironmentGlobal environment, Expression left, Expression right, OperatorType operator) { + if (operator == OperatorType.CAT) { + return STRING.binary( + position, + environment, + left.cast(position, environment, STRING), + right.cast(position, environment, STRING), OperatorType.CAT); + } + return new ExpressionArithmeticBinary(position, operator, left, right.cast(position, environment, this)); } @@ -590,5 +598,39 @@ public class ZenTypeLong extends ZenType { output.loadObject(0); output.getField(ANY_NAME, "value", "J"); } + + @Override + public void defineEquals(MethodOutput output) { + Label lblNope = new Label(); + + output.loadObject(1); + output.instanceOf(IAny.NAME); + output.ifEQ(lblNope); + + getValue(output); + output.loadObject(1); + output.invoke(METHOD_ASLONG); + output.lCmp(); + output.ifICmpNE(lblNope); + + output.iConst1(); + output.returnInt(); + + output.label(lblNope); + output.iConst0(); + output.returnInt(); + } + + @Override + public void defineHashCode(MethodOutput output) { + getValue(output); + output.l2i(); + getValue(output); + output.constant(32); + output.lShr(); + output.l2i(); + output.iXor(); + output.returnInt(); + } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeShort.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeShort.java index e81d24c..0cf613d 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeShort.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeShort.java @@ -164,6 +164,14 @@ public class ZenTypeShort extends ZenType { @Override public Expression binary(ZenPosition position, IEnvironmentGlobal environment, Expression left, Expression right, OperatorType operator) { + if (operator == OperatorType.CAT) { + return STRING.binary( + position, + environment, + left.cast(position, environment, STRING), + right.cast(position, environment, STRING), OperatorType.CAT); + } + return new ExpressionArithmeticBinary(position, operator, left, right.cast(position, environment, this)); } @@ -583,5 +591,32 @@ public class ZenTypeShort extends ZenType { output.loadObject(0); output.getField(ANY_NAME, "value", "S"); } + + @Override + public void defineEquals(MethodOutput output) { + Label lblNope = new Label(); + + output.loadObject(1); + output.instanceOf(IAny.NAME); + output.ifEQ(lblNope); + + getValue(output); + output.loadObject(1); + output.invoke(METHOD_ASSHORT); + output.ifICmpNE(lblNope); + + output.iConst1(); + output.returnInt(); + + output.label(lblNope); + output.iConst0(); + output.returnInt(); + } + + @Override + public void defineHashCode(MethodOutput output) { + getValue(output); + output.returnInt(); + } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeString.java b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeString.java index 8806d09..6ab67f6 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeString.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/ZenTypeString.java @@ -51,12 +51,12 @@ public class ZenTypeString extends ZenType { @Override public boolean canCastImplicit(ZenType type, IEnvironmentGlobal environment) { - return type == this || canCastExpansion(environment, type); + return type == this || type == ANY || canCastExpansion(environment, type); } @Override public boolean canCastExplicit(ZenType type, IEnvironmentGlobal environment) { - return type == this || type == BOOL || type.getNumberType() > 0 || canCastExpansion(environment, type); + return type == this || type == ANY || type == BOOL || type.getNumberType() > 0 || canCastExpansion(environment, type); } @Override @@ -149,6 +149,8 @@ public class ZenTypeString extends ZenType { output.invokeStatic(Double.class, "parseDouble", double.class, String.class); } else if (type == ZenTypeDoubleObject.INSTANCE) { output.invokeStatic(Double.class, "valueOf", Double.class, String.class); + } else if (type == ANY) { + output.invokeStatic(getAnyClassName(environment), "valueOf", "(Ljava/lang/String;)" + signature(IAny.class)); } else if (!compileCastExpansion(position, environment, type)) { environment.error(position, "cannot cast " + this + " to " + type); } @@ -557,5 +559,21 @@ public class ZenTypeString extends ZenType { output.loadObject(0); output.getField(ANY_NAME, "value", "Ljava/lang/String;"); } + + @Override + public void defineEquals(MethodOutput output) { + getValue(output); + output.loadObject(1); + output.invoke(METHOD_ASSTRING); + output.invokeVirtual(String.class, "equals", boolean.class, Object.class); + output.returnInt(); + } + + @Override + public void defineHashCode(MethodOutput output) { + getValue(output); + output.invokeVirtual(String.class, "hashCode", int.class); + output.returnInt(); + } } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorIterable.java b/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorIterable.java index 6812dab..01fb718 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorIterable.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorIterable.java @@ -45,7 +45,7 @@ public class IteratorIterable implements IZenIterator { methodOutput.loadObject(iterator); methodOutput.invokeInterface(Iterator.class, "next", Object.class); - methodOutput.checkCast(iteratorType.getSignature()); + methodOutput.checkCast(iteratorType.toASMType().getInternalName()); methodOutput.store(iteratorType.toASMType(), locals[0]); } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorMap.java b/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorMap.java index a6ab16d..c3e6875 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorMap.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorMap.java @@ -41,13 +41,14 @@ public class IteratorMap implements IZenIterator { @Override public void compilePreIterate(int[] locals, Label exit) { - methodOutput.dup(); + methodOutput.loadObject(iterator); methodOutput.invokeInterface( Iterator.class, "hasNext", boolean.class); methodOutput.ifEQ(exit); + methodOutput.loadObject(iterator); methodOutput.invokeInterface(Iterator.class, "next", Object.class); methodOutput.dup(); @@ -65,7 +66,7 @@ public class IteratorMap implements IZenIterator { @Override public void compileEnd() { - methodOutput.pop(); + } @Override diff --git a/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorMapKeys.java b/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorMapKeys.java index 68630f9..d16516b 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorMapKeys.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/type/iterator/IteratorMapKeys.java @@ -32,7 +32,7 @@ public class IteratorMapKeys implements IZenIterator { @Override public void compileStart(int[] locals) { - methodOutput.invokeInterface(Map.class, "entrySet", Set.class); + methodOutput.invokeInterface(Map.class, "keySet", Set.class); iterator = methodOutput.local(Type.getType(Iterator.class)); methodOutput.invokeInterface(Set.class, "iterator", Iterator.class); @@ -41,16 +41,15 @@ public class IteratorMapKeys implements IZenIterator { @Override public void compilePreIterate(int[] locals, Label exit) { - methodOutput.dup(); + methodOutput.loadObject(iterator); methodOutput.invokeInterface( Iterator.class, "hasNext", boolean.class); methodOutput.ifEQ(exit); - + + methodOutput.loadObject(iterator); methodOutput.invokeInterface(Iterator.class, "next", Object.class); - - methodOutput.invokeInterface(Map.Entry.class, "getKey", Object.class); methodOutput.store(type.getKeyType().toASMType(), locals[0]); } @@ -61,7 +60,7 @@ public class IteratorMapKeys implements IZenIterator { @Override public void compileEnd() { - methodOutput.pop(); + } @Override diff --git a/ZenScript/src/main/java/stanhebben/zenscript/util/AnyClassWriter.java b/ZenScript/src/main/java/stanhebben/zenscript/util/AnyClassWriter.java index c71b8ab..2713381 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/util/AnyClassWriter.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/util/AnyClassWriter.java @@ -382,6 +382,28 @@ public class AnyClassWriter { definition.defineIteratorMulti(outputIteratorMulti); outputIteratorMulti.end(); + MethodOutput outputHashCode = new MethodOutput( + writer, + Opcodes.ACC_PUBLIC, + "hashCode", + "()I", + null, + null); + outputHashCode.start(); + definition.defineHashCode(outputHashCode); + outputHashCode.end(); + + MethodOutput outputEquals = new MethodOutput( + writer, + Opcodes.ACC_PUBLIC, + "equals", + "(Ljava/lang/Object;)Z", + null, + null); + outputEquals.start(); + definition.defineEquals(outputEquals); + outputEquals.end(); + writer.visitEnd(); return writer.toByteArray(); } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/util/IAnyDefinition.java b/ZenScript/src/main/java/stanhebben/zenscript/util/IAnyDefinition.java index 4f17c74..790b2f7 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/util/IAnyDefinition.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/util/IAnyDefinition.java @@ -84,4 +84,8 @@ public interface IAnyDefinition { public void defineIteratorSingle(MethodOutput output); public void defineIteratorMulti(MethodOutput output); + + public void defineEquals(MethodOutput output); + + public void defineHashCode(MethodOutput output); } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/util/MethodOutput.java b/ZenScript/src/main/java/stanhebben/zenscript/util/MethodOutput.java index b5aba09..b1e96f0 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/util/MethodOutput.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/util/MethodOutput.java @@ -183,7 +183,7 @@ public class MethodOutput { } public void checkCast(String newClass) { - visitor.visitTypeInsn(CHECKCAST, newClass.substring(1, newClass.length() - 1)); + visitor.visitTypeInsn(CHECKCAST, newClass); } public void iNeg() { @@ -227,6 +227,14 @@ public class MethodOutput { visitor.visitInsn(IXOR); } + public void iShr() { + visitor.visitInsn(ISHR); + } + + public void iShl() { + visitor.visitInsn(ISHL); + } + public void lNeg() { visitor.visitInsn(LNEG); } @@ -268,6 +276,14 @@ public class MethodOutput { lXor(); } + public void lShr() { + visitor.visitInsn(LSHR); + } + + public void lShl() { + visitor.visitInsn(LSHL); + } + public void fNeg() { visitor.visitInsn(FNEG); } @@ -392,6 +408,10 @@ public class MethodOutput { visitor.visitInsn(DCMPL); } + public void instanceOf(String clsName) { + visitor.visitTypeInsn(INSTANCEOF, clsName); + } + public void invokeStatic(String owner, String name, String descriptor) { if (owner == null) throw new IllegalArgumentException("owner cannot be null"); diff --git a/ZenScript/src/main/java/stanhebben/zenscript/util/ZenPosition.java b/ZenScript/src/main/java/stanhebben/zenscript/util/ZenPosition.java index c3140aa..7200f94 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/util/ZenPosition.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/util/ZenPosition.java @@ -39,6 +39,6 @@ public class ZenPosition { @Override public String toString() { - return (file == null ? "?" : file.getFileName()) + " - " + Integer.toString(line) + ":" + offset; + return (file == null ? "?" : file.getFileName()) + ":" + Integer.toString(line); } } diff --git a/ZenScript/src/main/java/stanhebben/zenscript/value/IAny.java b/ZenScript/src/main/java/stanhebben/zenscript/value/IAny.java index 0e4754d..654de1f 100644 --- a/ZenScript/src/main/java/stanhebben/zenscript/value/IAny.java +++ b/ZenScript/src/main/java/stanhebben/zenscript/value/IAny.java @@ -13,6 +13,8 @@ import java.util.Iterator; * @author Stan Hebben */ public interface IAny { + public static final String NAME = "stanhebben/zenscript/value/IAny"; + public static final int NUM_BYTE = 1; public static final int NUM_SHORT = 2; public static final int NUM_INT = 3; diff --git a/build.gradle b/build.gradle index 3e55d3b..6d09fab 100644 --- a/build.gradle +++ b/build.gradle @@ -59,13 +59,15 @@ task assembleMC164(type: Jar, dependsOn: [\ ':MineTweaker3-MC164-Main:build', ':MineTweaker3-MC164-Mod-IC2:build', ':MineTweaker3-MC164-Mod-NEI:build', - ':MineTweaker3-MC164-Mod-GregTech:build']) { + ':MineTweaker3-MC164-Mod-GregTech:build', + ':MineTweaker3-MC164-Mod-MFR:build']) { from zipTree(project(":ZenScript").jar.archivePath) from zipTree(project(':MineTweaker3-API').jar.archivePath) from zipTree(project(':MineTweaker3-MC164-Main').jar.archivePath) from zipTree(project(':MineTweaker3-MC164-Mod-IC2').jar.archivePath) from zipTree(project(':MineTweaker3-MC164-Mod-NEI').jar.archivePath) from zipTree(project(':MineTweaker3-MC164-Mod-GregTech').jar.archivePath) + from zipTree(project(':MineTweaker3-MC164-Mod-MFR').jar.archivePath) } task zendoc164(type: Javadoc) { @@ -74,7 +76,8 @@ task zendoc164(type: Javadoc) { 'MineTweaker3-MC164-Main/src/main/java', 'MineTweaker3-MC164-Mod-IC2/src/main/java', 'MineTweaker3-MC164-Mod-NEI/src/main/java', - 'MineTweaker3-MC164-Mod-GregTech/src/main/java') + 'MineTweaker3-MC164-Mod-GregTech/src/main/java', + 'MineTweaker3-MC164-Mod-MFR/src/main/java') destinationDir = file("build/zendoc164") options.docletpath = [file('buildSrc/build/libs/buildSrc.jar')].asList() options.doclet = 'stanhebben.zenscript.docs.ZenScriptDoclet' @@ -93,6 +96,9 @@ task zendoc164(type: Javadoc) { for (file in project(':MineTweaker3-MC164-Mod-GregTech').configurations.compile) { classpathList += file } + for (file in project(':MineTweaker3-MC164-Mod-MFR').configurations.compile) { + classpathList += file + } for (file in project(':MineTweaker3-MC164-Mod-NEI').configurations.compile) { classpathList += file } diff --git a/buildSrc/src/main/java/minetweaker/tasks/RegisterZenClassesTask.java b/buildSrc/src/main/java/minetweaker/tasks/RegisterZenClassesTask.java index 38fe826..47e7648 100644 --- a/buildSrc/src/main/java/minetweaker/tasks/RegisterZenClassesTask.java +++ b/buildSrc/src/main/java/minetweaker/tasks/RegisterZenClassesTask.java @@ -46,7 +46,8 @@ public class RegisterZenClassesTask extends DefaultTask { if (outputDir == null) outputDir = inputDir; List classNames = new ArrayList(); - iterate(inputDir, null, classNames); + List onRegisterMethods = new ArrayList(); + iterate(inputDir, null, classNames, onRegisterMethods); String fullClassName = className.replace('.', '/'); @@ -63,6 +64,10 @@ public class RegisterZenClassesTask extends DefaultTask { method.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z"); } + for (OnRegisterMethod onRegisterMethod : onRegisterMethods) { + method.visitMethodInsn(Opcodes.INVOKESTATIC, onRegisterMethod.className, onRegisterMethod.methodName, "()V"); + } + method.visitInsn(Opcodes.RETURN); method.visitMaxs(0, 0); @@ -89,23 +94,23 @@ public class RegisterZenClassesTask extends DefaultTask { } } - private void iterate(File dir, String pkg, List classNames) { + private void iterate(File dir, String pkg, List classNames, List onRegisterMethods) { for (File f : dir.listFiles()) { if (f.isDirectory()) { if (pkg == null) { - iterate(f, f.getName(), classNames); + iterate(f, f.getName(), classNames, onRegisterMethods); } else { - iterate(f, pkg + "/" + f.getName(), classNames); + iterate(f, pkg + "/" + f.getName(), classNames, onRegisterMethods); } } else if (f.isFile()) { if (f.getName().endsWith(".class")) { - processJavaClass(f, pkg, classNames); + processJavaClass(f, pkg, classNames, onRegisterMethods); } } } } - private void processJavaClass(File cls, String pkg, List classNames) { + private void processJavaClass(File cls, String pkg, List classNames, List onRegisterMethods) { try { InputStream input = new BufferedInputStream(new FileInputStream(cls)); ClassReader reader = new ClassReader(input); @@ -117,6 +122,11 @@ public class RegisterZenClassesTask extends DefaultTask { if (detector.isAnnotated) { classNames.add(pkg + "/" + cls.getName().substring(0, cls.getName().length() - 6)); } + for (MethodAnnotationDetector onRegisterMethod : detector.onRegister) { + onRegisterMethods.add(new OnRegisterMethod( + pkg + "/" + cls.getName().substring(0, cls.getName().length() - 6), + onRegisterMethod.name)); + } } catch (IOException ex) { } @@ -124,6 +134,7 @@ public class RegisterZenClassesTask extends DefaultTask { private static class AnnotationDetector extends ClassVisitor { private boolean isAnnotated = false; + private List onRegister = new ArrayList(); public AnnotationDetector() { super(Opcodes.ASM4); @@ -141,5 +152,47 @@ public class RegisterZenClassesTask extends DefaultTask { return super.visitAnnotation(desc, visible); } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + return new MethodAnnotationDetector(this, name, desc); + } + } + + private static class MethodAnnotationDetector extends MethodVisitor { + private final AnnotationDetector detector; + private final String name; + private final String desc; + + public MethodAnnotationDetector(AnnotationDetector detector, String name, String desc) { + super(Opcodes.ASM4); + + this.detector = detector; + this.name = name; + this.desc = desc; + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + if (desc.equals("Lminetweaker/annotations/OnRegister;")) { + if (this.desc.equals("()V")) { + detector.onRegister.add(this); + } else { + throw new RuntimeException("OnRegister annotation must be used on a static method without arguments or return value"); + } + } + + return super.visitAnnotation(desc, visible); + } + } + + private static class OnRegisterMethod { + private final String className; + private final String methodName; + + public OnRegisterMethod(String className, String methodName) { + this.className = className; + this.methodName = methodName; + } } } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..bb5df76 --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +org.gradle.configureondemand=true