From e5a16e25df47a544358adac45f494c2f36337043 Mon Sep 17 00:00:00 2001 From: LexManos Date: Thu, 12 Jan 2012 07:38:23 +0000 Subject: [PATCH] Merged in MCL branch --- .../net/minecraft/src/forge/ForgeHooks.java | 32 + .../src/forge/IMinecartCollisionHandler.java | 50 + .../minecraft/src/forge/IMinecartHandler.java | 38 + .../net/minecraft/src/forge/MinecartKey.java | 49 + .../minecraft/src/forge/MinecraftForge.java | 158 ++- .../net/minecraft/src/BlockRail.java.patch | 155 ++- .../minecraft/src/EntityMinecart.java.patch | 915 ++++++++++++++++++ .../net/minecraft/src/RailLogic.java.patch | 86 ++ .../net/minecraft/src/BlockRail.java.patch | 155 ++- .../net/minecraft/src/Entity.java.patch | 15 +- .../minecraft/src/EntityMinecart.java.patch | 910 +++++++++++++++++ .../net/minecraft/src/RailLogic.java.patch | 77 ++ 12 files changed, 2622 insertions(+), 18 deletions(-) create mode 100644 forge/forge_common/net/minecraft/src/forge/IMinecartCollisionHandler.java create mode 100644 forge/forge_common/net/minecraft/src/forge/IMinecartHandler.java create mode 100644 forge/forge_common/net/minecraft/src/forge/MinecartKey.java create mode 100644 forge/patches/minecraft/net/minecraft/src/EntityMinecart.java.patch create mode 100644 forge/patches/minecraft/net/minecraft/src/RailLogic.java.patch create mode 100644 forge/patches/minecraft_server/net/minecraft/src/EntityMinecart.java.patch create mode 100644 forge/patches/minecraft_server/net/minecraft/src/RailLogic.java.patch diff --git a/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java b/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java index d4436a75b..bfce0ad02 100644 --- a/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java +++ b/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java @@ -6,6 +6,8 @@ package net.minecraft.src.forge; import net.minecraft.src.Block; +import net.minecraft.src.Entity; +import net.minecraft.src.EntityMinecart; import net.minecraft.src.EntityPlayer; import net.minecraft.src.IInventory; import net.minecraft.src.ItemStack; @@ -70,6 +72,36 @@ public class ForgeHooks { } static LinkedList sleepHandlers = new LinkedList(); + + + public static void onMinecartUpdate(EntityMinecart minecart, int x, int y, int z) + { + for (IMinecartHandler handler : minecartHandlers) + { + handler.onMinecartUpdate(minecart, x, y, z); + } + } + + public static void onMinecartEntityCollision(EntityMinecart minecart, Entity entity) + { + for (IMinecartHandler handler : minecartHandlers) + { + handler.onMinecartEntityCollision(minecart, entity); + } + } + + public static boolean onMinecartInteract(EntityMinecart minecart, EntityPlayer player) + { + boolean canceled = true; + for (IMinecartHandler handler : minecartHandlers) + { + boolean tmp = handler.onMinecartInteract(minecart, player, canceled); + canceled = canceled && tmp; + } + return canceled; + } + + static LinkedList minecartHandlers = new LinkedList(); // Plant Management // ------------------------------------------------------------ diff --git a/forge/forge_common/net/minecraft/src/forge/IMinecartCollisionHandler.java b/forge/forge_common/net/minecraft/src/forge/IMinecartCollisionHandler.java new file mode 100644 index 000000000..8858be201 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/IMinecartCollisionHandler.java @@ -0,0 +1,50 @@ +package net.minecraft.src.forge; + +import net.minecraft.src.AxisAlignedBB; +import net.minecraft.src.Entity; +import net.minecraft.src.EntityMinecart; + +/** + * This class defines a replacement for the default minecart collision code. + * Only one handler can be registered at a time. It it registered with EntityMinecart.registerCollisionHandler(). + * If you use this, make it a configuration option. + * @author CovertJaguar + */ +public interface IMinecartCollisionHandler +{ + + /** + * This basically replaces the function of the same name in EnityMinecart. + * Code in IMinecartHooks.applyEntityCollisionHook is still run. + * @param cart The cart that called the collision. + * @param other The object it collided with. + */ + public void onEntityCollision(EntityMinecart cart, Entity other); + + /** + * This function replaced the function of the same name in EntityMinecart. + * It is used to define whether minecarts collide with specific entities, + * for example items. + * @param cart The cart for which the collision box was requested. + * @param other The entity requesting the collision box. + * @return The collision box or null. + */ + public AxisAlignedBB getCollisionBox(EntityMinecart cart, Entity other); + + /** + * This function is used to define the box used for detecting minecart collisions. + * It is generally bigger that the normal collision box. + * @param cart The cart for which the collision box was requested. + * @return The collision box, cannot be null. + */ + public AxisAlignedBB getMinecartCollisionBox(EntityMinecart cart); + + /** + * This function replaces the function of the same name in EntityMinecart. + * It defines whether minecarts are solid to the player. + * @param cart The cart for which the bounding box was requested. + * @return The bounding box or null. + */ + public AxisAlignedBB getBoundingBox(EntityMinecart cart); +} + diff --git a/forge/forge_common/net/minecraft/src/forge/IMinecartHandler.java b/forge/forge_common/net/minecraft/src/forge/IMinecartHandler.java new file mode 100644 index 000000000..831790425 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/IMinecartHandler.java @@ -0,0 +1,38 @@ +package net.minecraft.src.forge; + +import net.minecraft.src.Entity; +import net.minecraft.src.EntityMinecart; +import net.minecraft.src.EntityPlayer; + +public interface IMinecartHandler { + + /** + * This functions is called at the end of every minecart's doUpdate loop. + * If you override EntityMinecart.doUpdate(), is recommended that you retain the code that calls this function. + * @param cart The cart that called the function. + * @param i X coordinate of the rail + * @param j Y coordinate of the rail + * @param k Z coordinate of the rail + */ + public void onMinecartUpdate(EntityMinecart minecart, int x, int y, int z); + + /** + * This function allows several mods to add code into the collision routine at the same time regardless of the collision handler registered. + * If you override EntityMinecart.applyEntityCollision(), is recommended that you retain the code that calls this function. + * @param cart The cart that called the function. + * @param other + */ + public void onMinecartEntityCollision(EntityMinecart minecart, Entity entity); + + /** + * This function is called whenever a player attempts to interact with a minecart. + * The primary reason for this hook is to fix a few bugs and put restrictions on how a minecart can be used under certain circumstances. + * If you override EntityMinecart.interact(), is recommended that you retain the code that calls this function. + * @param cart The cart that called the function. + * @param player The player that tried to interact with the minecart. + * @param canceled Wither or not a pervious hook has canceled the interaction of a player. + * @return Whether the player can interact with the minecart. + */ + public boolean onMinecartInteract(EntityMinecart minecart, EntityPlayer player, boolean canceled); + +} diff --git a/forge/forge_common/net/minecraft/src/forge/MinecartKey.java b/forge/forge_common/net/minecraft/src/forge/MinecartKey.java new file mode 100644 index 000000000..35b23da48 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/MinecartKey.java @@ -0,0 +1,49 @@ +package net.minecraft.src.forge; + +import net.minecraft.src.EntityMinecart; + +/** + * Used to create hashmap values for Minecart/type pairs + * Written by CovertJaguar + */ +public class MinecartKey { + public final Class minecart; + public final int type; + + public MinecartKey(Class c, int t) + { + minecart = c; + type = t; + } + + @Override + public boolean equals(Object obj) + { + if(obj == null) + { + return false; + } + + if(getClass() != obj.getClass()) + { + return false; + } + + final MinecartKey other = (MinecartKey)obj; + if(this.minecart != other.minecart && (this.minecart == null || !this.minecart.equals(other.minecart))) + { + return false; + } + + return (this.type == other.type); + } + + @Override + public int hashCode() + { + int hash = 7; + hash = 59 * hash + (this.minecart != null ? this.minecart.hashCode() : 0); + hash = 59 * hash + this.type; + return hash; + } +} diff --git a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java index cb2fa45de..de4e8e61a 100755 --- a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java +++ b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java @@ -6,6 +6,7 @@ package net.minecraft.src.forge; import net.minecraft.src.Block; +import net.minecraft.src.EntityMinecart; import net.minecraft.src.Item; import net.minecraft.src.ItemStack; import net.minecraft.src.World; @@ -56,6 +57,15 @@ public class MinecraftForge { public static void registerCraftingHandler(ICraftingHandler handler) { ForgeHooks.craftingHandlers.add(handler); } + + /** + * Registers a new minecart handler + * @param handler The Handler to be registered + */ + public static void registerMinecartHandler(IMinecartHandler handler) + { + ForgeHooks.minecartHandlers.add(handler); + } /** * This is not supposed to be called outside of Minecraft internals. @@ -559,7 +569,6 @@ public class MinecraftForge { return rarity; } - /** * Gets a random item stack to place in a dungeon chest during world generation @@ -586,6 +595,149 @@ public class MinecraftForge { return null; } + + + //Minecart Dictionary -------------------------------------- + private static Map itemForMinecart = new HashMap(); + private static Map minecartForItem = new HashMap(); + /** + * Registers a custom minecart and its corresponding item. + * This should be the item used to place the minecart by the user, + * not the item dropped by the cart. + * @param cart The minecart. + * @param item The item used to place the cart. + */ + public static void registerMinecart(Class cart, ItemStack item) + { + registerMinecart(cart, 0, item); + } + + /** + * Registers a minecart and its corresponding item. + * This should be the item used to place the minecart by the user, + * not the item dropped by the cart. + * @param minecart The minecart. + * @param type The minecart type, used to differentiate carts that have the same class. + * @param item The item used to place the cart. + */ + public static void registerMinecart(Class minecart, int type, ItemStack item) + { + MinecartKey k = new MinecartKey(minecart, type); + itemForMinecart.put(k, item); + minecartForItem.put(item, k); + } + + /** + * Removes a previously registered Minecart. Useful for replacing the vanilla minecarts. + * @param minecart + * @param type + */ + public static void removeMinecart(Class minecart, int type) + { + MinecartKey k = new MinecartKey(minecart, type); + ItemStack item = itemForMinecart.remove(k); + if(item != null) + { + minecartForItem.remove(item); + } + } + + /** + * This function returns an ItemStack that represents this cart. + * The player should be able to use this item to place the minecart. + * This is the item that was registered with the cart via the registerMinecart function, + * but is not necessary the item the cart drops when destroyed. + * @param minecart The cart class + * @return An ItemStack that can be used to place the cart. + */ + public static ItemStack getItemForCart(Class minecart) + { + return getItemForCart(minecart, 0); + } + + /** + * This function returns an ItemStack that represents this cart. + * The player should be able to use this item to place the minecart. + * This is the item that was registered with the cart via the registerMinecart function, + * but is not necessary the item the cart drops when destroyed. + * @param minecart The cart class + * @param type The minecartType value + * @return An ItemStack that can be used to place the cart. + */ + public static ItemStack getItemForCart(Class minecart, int type) + { + ItemStack item = itemForMinecart.get(new MinecartKey(minecart, type)); + if (item == null) + { + return null; + } + return item.copy(); + } + + /** + * This function returns an ItemStack that represents this cart. + * The player should be able to use this item to place the minecart. + * This is the item that was registered with the cart via the registerMinecart function, + * but is not necessary the item the cart drops when destroyed. + * @param cart The cart entity + * @return An ItemStack that can be used to place the cart. + */ + public static ItemStack getItemForCart(EntityMinecart cart) + { + if(cart.getClass() == EntityMinecart.class) + { + return getItemForCart(cart.getClass(), cart.getMinecartType()); + } + return getItemForCart(cart.getClass(), 0); + } + + /** + * The function will return the cart class for a given item. + * If the item was not registered via the registerMinecart function it will return null. + * @param item The item to test. + * @return Cart if mapping exists, null if not. + */ + public static Class getCartClassForItem(ItemStack item) + { + MinecartKey k = minecartForItem.get(item); + if(k != null) + { + return k.minecart; + } + return null; + } + + /** + * The function will return the cart type for a given item. + * Will return -1 if the mapping doesn't exist. + * If the item was not registered via the registerMinecart function it will return null. + * @param item The item to test. + * @return the cart minecartType value. + */ + public static int getCartTypeForItem(ItemStack item) + { + MinecartKey k = minecartForItem.get(item); + if(k != null) + { + return k.type; + } + return -1; + } + + /** + * Will return a set of all registered minecart items. + * @return a copy of the set of all minecart items + */ + public static Set getAllCartItems() + { + Set ret = new HashSet(); + for(ItemStack item : minecartForItem.keySet()) + { + ret.add(item.copy()); + } + return ret; + } + static { @@ -605,6 +757,10 @@ public class MinecraftForge { addDungeonLoot(new ItemStack(Item.record13), 0.05f ); addDungeonLoot(new ItemStack(Item.recordCat), 0.05f ); addDungeonLoot(new ItemStack(Item.dyePowder, 1, 3), 1.00f ); + + registerMinecart(EntityMinecart.class, 0, new ItemStack(Item.minecartEmpty)); + registerMinecart(EntityMinecart.class, 1, new ItemStack(Item.minecartCrate)); + registerMinecart(EntityMinecart.class, 2, new ItemStack(Item.minecartPowered)); } } diff --git a/forge/patches/minecraft/net/minecraft/src/BlockRail.java.patch b/forge/patches/minecraft/net/minecraft/src/BlockRail.java.patch index bb8acdb06..8ef36c79e 100644 --- a/forge/patches/minecraft/net/minecraft/src/BlockRail.java.patch +++ b/forge/patches/minecraft/net/minecraft/src/BlockRail.java.patch @@ -1,21 +1,47 @@ --- ../src_base/minecraft/net/minecraft/src/BlockRail.java 0000-00-00 00:00:00.000000000 -0000 +++ ../src_work/minecraft/net/minecraft/src/BlockRail.java 0000-00-00 00:00:00.000000000 -0000 -@@ -18,12 +18,12 @@ +@@ -14,16 +14,29 @@ + { + + private final boolean isPowered; ++ ++ /** ++ * Forge: Moved render type to a field and a setter. ++ * This allows for a mod to change the render type ++ * for vanilla rails, and any mod rails that extend ++ * this class. ++ */ ++ private int renderType = 9; ++ ++ public void setRenderType(int value) ++ { ++ renderType = value; ++ } + public static final boolean isRailBlockAt(World world, int i, int j, int k) { int l = world.getBlockId(i, j, k); - return l == Block.rail.blockID || l == Block.railPowered.blockID || l == Block.railDetector.blockID; -+ return Block.blocksList[l] instanceof BlockRail; ++ return Block.blocksList[l] instanceof BlockRail; } public static final boolean isRailBlock(int i) { - return i == Block.rail.blockID || i == Block.railPowered.blockID || i == Block.railDetector.blockID; -+ return Block.blocksList[i] instanceof BlockRail; ++ return Block.blocksList[i] instanceof BlockRail; } protected BlockRail(int i, int j, boolean flag) -@@ -99,7 +99,7 @@ +@@ -89,7 +102,7 @@ + + public int getRenderType() + { +- return 9; ++ return renderType; + } + + public int quantityDropped(Random random) +@@ -99,7 +112,7 @@ public boolean canPlaceBlockAt(World world, int i, int j, int k) { @@ -24,7 +50,7 @@ } public void onBlockAdded(World world, int i, int j, int k) -@@ -123,23 +123,23 @@ +@@ -123,23 +136,23 @@ j1 &= 7; } boolean flag = false; @@ -53,3 +79,122 @@ { flag = true; } +@@ -313,8 +326,118 @@ + return 0; + } + ++ /** ++ * This function is no longer called by Minecraft ++ */ + static boolean isPoweredBlockRail(BlockRail blockrail) + { + return blockrail.isPowered; + } ++ ++ /** ++ * Return true if the rail can make corners. ++ * Used by placement logic. ++ * @param world The world. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return True if the rail can make corners. ++ */ ++ public boolean isFlexibleRail(World world, int i, int j, int k) ++ { ++ return !isPowered; ++ } ++ ++ /** ++ * Returns true if the rail can make up and down slopes. ++ * Used by placement logic. ++ * @param world The world. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return True if the rail can make slopes. ++ */ ++ public boolean canMakeSlopes(World world, int i, int j, int k) ++ { ++ return true; ++ } ++ ++ /** ++ * Return the rails metadata (without the power bit if the rail uses one). ++ * Can be used to make the cart think the rail something other than it is, ++ * for example when making diamond junctions or switches. ++ * The cart parameter will often be null unless it it called from EntityMinecart. ++ * ++ * Valid rail metadata is defined as follows: ++ * 0x0: flat track going North-South ++ * 0x1: flat track going West-East ++ * 0x2: track ascending to the East ++ * 0x3: track ascending to the West ++ * 0x4: track ascending to the North ++ * 0x5: track ascending to the South ++ * 0x6: WestNorth corner (connecting East and South) ++ * 0x7: EastNorth corner (connecting West and South) ++ * 0x8: EastSouth corner (connecting West and North) ++ * 0x9: WestSouth corner (connecting East and North) ++ * ++ * All directions are Notch defined. ++ * In MC Beta 1.8.3 the Sun rises in the North. ++ * In MC 1.0.0 the Sun rises in the East. ++ * @param world The world. ++ * @param cart The cart asking for the metadata, null if it is not called by EntityMinecart. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return The metadata. ++ */ ++ public int getBasicRailMetadata(IBlockAccess world, EntityMinecart cart, int i, int j, int k) ++ { ++ int meta = world.getBlockMetadata(i, j, k); ++ if(isPowered) { ++ meta = meta & 7; ++ } ++ return meta; ++ } ++ ++ /** ++ * Returns the max speed of the rail at [i, j, k]. ++ * @param world The world. ++ * @param cart The cart on the rail, may be null. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return The max speed of the current rail. ++ */ ++ public float getRailMaxSpeed(World world, EntityMinecart cart, int i, int j, int k) ++ { ++ return 0.4f; ++ } ++ ++ /** ++ * This function is called by any minecart that passes over this rail. ++ * It is called once per update tick that the minecart is on the rail. ++ * @param world The world. ++ * @param cart The cart on the rail. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ */ ++ public void onMinecartPass(World world, EntityMinecart cart, int i, int j, int k) ++ { ++ } ++ ++ /** ++ * Return true if this rail uses the 4th bit as a power bit. ++ * Avoid using this function when getBasicRailMetadata() can be used instead. ++ * The only reason to use this function is if you wish to change the rails metadata. ++ * @param world The world. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return True if the 4th bit is a power bit. ++ */ ++ public boolean hasPowerBit(World world, int i, int j, int k) ++ { ++ return isPowered; ++ } + } diff --git a/forge/patches/minecraft/net/minecraft/src/EntityMinecart.java.patch b/forge/patches/minecraft/net/minecraft/src/EntityMinecart.java.patch new file mode 100644 index 000000000..26aeb17a1 --- /dev/null +++ b/forge/patches/minecraft/net/minecraft/src/EntityMinecart.java.patch @@ -0,0 +1,915 @@ +--- ../src_base/minecraft/net/minecraft/src/EntityMinecart.java 0000-00-00 00:00:00.000000000 -0000 ++++ ../src_work/minecraft/net/minecraft/src/EntityMinecart.java 0000-00-00 00:00:00.000000000 -0000 +@@ -4,9 +4,14 @@ + + package net.minecraft.src; + ++import java.util.ArrayList; + import java.util.List; + import java.util.Random; + ++import net.minecraft.src.forge.ForgeHooks; ++import net.minecraft.src.forge.IMinecartCollisionHandler; ++import net.minecraft.src.forge.MinecraftForge; ++ + // Referenced classes of package net.minecraft.src: + // Entity, IInventory, ItemStack, DataWatcher, + // World, Item, EntityItem, Block, +@@ -18,13 +23,13 @@ + implements IInventory + { + +- private ItemStack cargoItems[]; +- private int fuel; +- private boolean field_856_i; ++ protected ItemStack cargoItems[]; ++ protected int fuel; ++ protected boolean field_856_i; + public int minecartType; + public double pushX; + public double pushZ; +- private static final int field_855_j[][][] = { ++ protected static final int field_855_j[][][] = { + { + { + 0, 0, -1 +@@ -87,16 +92,36 @@ + } + } + }; +- private int minecartPosRotationIncrements; +- private double minecartX; +- private double minecartY; +- private double minecartZ; +- private double minecartYaw; +- private double minecartPitch; +- private double velocityX; +- private double velocityY; +- private double velocityZ; +- ++ protected int minecartPosRotationIncrements; ++ protected double minecartX; ++ protected double minecartY; ++ protected double minecartZ; ++ protected double minecartYaw; ++ protected double minecartPitch; ++ protected double velocityX; ++ protected double velocityY; ++ protected double velocityZ; ++ ++ /*Forge: Minecart Compatibility Layer Integration. ++ */ ++ public static float defaultMaxSpeedRail = 0.4f; ++ public static float defaultMaxSpeedGround = 0.4f; ++ public static float defaultMaxSpeedAirLateral = 0.4f; ++ public static float defaultMaxSpeedAirVertical = -1f; ++ public static double defaultDragAir = 0.94999998807907104D; ++ protected boolean canUseRail = true; ++ protected boolean canBePushed = true; ++ private static IMinecartCollisionHandler collisionHandler = null; ++ ++ /* ++ * Instance versions of the above physics properties ++ */ ++ protected float maxSpeedRail; ++ protected float maxSpeedGround; ++ protected float maxSpeedAirLateral; ++ protected float maxSpeedAirVertical; ++ protected double dragAir; ++ + public EntityMinecart(World world) + { + super(world); +@@ -106,6 +131,18 @@ + preventEntitySpawning = true; + setSize(0.98F, 0.7F); + yOffset = height / 2.0F; ++ ++ maxSpeedRail = defaultMaxSpeedRail; ++ maxSpeedGround = defaultMaxSpeedGround; ++ maxSpeedAirLateral = defaultMaxSpeedAirLateral; ++ maxSpeedAirVertical = defaultMaxSpeedAirVertical; ++ dragAir = defaultDragAir; ++ } ++ ++ public EntityMinecart(World world, int type) ++ { ++ this(world); ++ minecartType = type; + } + + protected boolean canTriggerWalking() +@@ -123,17 +160,27 @@ + + public AxisAlignedBB getCollisionBox(Entity entity) + { ++ if (getCollisionHandler() != null) ++ { ++ return getCollisionHandler().getCollisionBox(this, entity); ++ } ++ + return entity.boundingBox; + } + + public AxisAlignedBB getBoundingBox() + { ++ if (getCollisionHandler() != null) ++ { ++ return getCollisionHandler().getBoundingBox(this); ++ } ++ + return null; + } + + public boolean canBePushed() + { +- return true; ++ return canBePushed; + } + + public EntityMinecart(World world, double d, double d1, double d2, +@@ -172,8 +219,10 @@ + riddenByEntity.mountEntity(this); + } + setEntityDead(); +- dropItemWithOffset(Item.minecartEmpty.shiftedIndex, 1, 0.0F); +- if(minecartType == 1) ++ ++ dropCartAsItem(); ++ ++ if(getSizeInventory() > 0) + { + EntityMinecart entityminecart = this; + label0: +@@ -207,12 +256,6 @@ + worldObj.spawnEntityInWorld(entityitem); + } while(true); + } +- +- dropItemWithOffset(Block.chest.blockID, 1, 0.0F); +- } else +- if(minecartType == 2) +- { +- dropItemWithOffset(Block.stoneOvenIdle.blockID, 1, 0.0F); + } + } + return true; +@@ -277,7 +320,7 @@ + { + func_41024_b(func_41025_i() - 1); + } +- if(isMinecartPowered() && rand.nextInt(4) == 0) ++ if(isMinecartPowered() && rand.nextInt(4) == 0 && minecartType == 2 && getClass() == EntityMinecart.class) + { + worldObj.spawnParticle("largesmoke", posX, posY + 0.80000000000000004D, posZ, 0.0D, 0.0D, 0.0D); + } +@@ -317,22 +360,19 @@ + double d2 = 0.40000000000000002D; + double d4 = 0.0078125D; + int l = worldObj.getBlockId(i, j, k); +- if(BlockRail.isRailBlock(l)) ++ if(canUseRail() && BlockRail.isRailBlock(l)) + { + Vec3D vec3d = func_514_g(posX, posY, posZ); +- int i1 = worldObj.getBlockMetadata(i, j, k); ++ int i1 = ((BlockRail)Block.blocksList[l]).getBasicRailMetadata(worldObj, this, i, j, k); + posY = j; + boolean flag = false; + boolean flag1 = false; + if(l == Block.railPowered.blockID) + { +- flag = (i1 & 8) != 0; ++ flag = (worldObj.getBlockMetadata(i, j, k) & 8) != 0; + flag1 = !flag; + } +- if(((BlockRail)Block.blocksList[l]).getIsPowered()) +- { +- i1 &= 7; +- } ++ + if(i1 >= 2 && i1 <= 5) + { + posY = j + 1; +@@ -366,7 +406,8 @@ + double d13 = Math.sqrt(motionX * motionX + motionZ * motionZ); + motionX = (d13 * d9) / d11; + motionZ = (d13 * d10) / d11; +- if(flag1) ++ ++ if(flag1 && shouldDoRailFunctions()) + { + double d16 = Math.sqrt(motionX * motionX + motionZ * motionZ); + if(d16 < 0.029999999999999999D) +@@ -407,30 +448,9 @@ + posX = d18 + d9 * d17; + posZ = d19 + d10 * d17; + setPosition(posX, posY + (double)yOffset, posZ); +- double d23 = motionX; +- double d25 = motionZ; +- if(riddenByEntity != null) +- { +- d23 *= 0.75D; +- d25 *= 0.75D; +- } +- if(d23 < -d2) +- { +- d23 = -d2; +- } +- if(d23 > d2) +- { +- d23 = d2; +- } +- if(d25 < -d2) +- { +- d25 = -d2; +- } +- if(d25 > d2) +- { +- d25 = d2; +- } +- moveEntity(d23, 0.0D, d25); ++ ++ moveMinecartOnRail(i, j, k); ++ + if(ai[0][1] != 0 && MathHelper.floor_double(posX) - i == ai[0][0] && MathHelper.floor_double(posZ) - k == ai[0][2]) + { + setPosition(posX, posY + (double)ai[0][1], posZ); +@@ -439,37 +459,9 @@ + { + setPosition(posX, posY + (double)ai[1][1], posZ); + } +- if(riddenByEntity != null) +- { +- motionX *= 0.99699997901916504D; +- motionY *= 0.0D; +- motionZ *= 0.99699997901916504D; +- } else +- { +- if(minecartType == 2) +- { +- double d27 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); +- if(d27 > 0.01D) +- { +- pushX /= d27; +- pushZ /= d27; +- double d29 = 0.040000000000000001D; +- motionX *= 0.80000001192092896D; +- motionY *= 0.0D; +- motionZ *= 0.80000001192092896D; +- motionX += pushX * d29; +- motionZ += pushZ * d29; +- } else +- { +- motionX *= 0.89999997615814209D; +- motionY *= 0.0D; +- motionZ *= 0.89999997615814209D; +- } +- } +- motionX *= 0.95999997854232788D; +- motionY *= 0.0D; +- motionZ *= 0.95999997854232788D; +- } ++ ++ applyDragAndPushForces(); ++ + Vec3D vec3d1 = func_514_g(posX, posY, posZ); + if(vec3d1 != null && vec3d != null) + { +@@ -490,25 +482,15 @@ + motionX = d15 * (double)(k1 - i); + motionZ = d15 * (double)(l1 - k); + } +- if(minecartType == 2) ++ ++ updatePushForces(); ++ ++ if (shouldDoRailFunctions()) + { +- double d30 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); +- if(d30 > 0.01D && motionX * motionX + motionZ * motionZ > 0.001D) +- { +- pushX /= d30; +- pushZ /= d30; +- if(pushX * motionX + pushZ * motionZ < 0.0D) +- { +- pushX = 0.0D; +- pushZ = 0.0D; +- } else +- { +- pushX = motionX; +- pushZ = motionZ; +- } +- } ++ ((BlockRail)Block.blocksList[l]).onMinecartPass(worldObj, this, i, j, k); + } +- if(flag) ++ ++ if(flag && shouldDoRailFunctions()) + { + double d31 = Math.sqrt(motionX * motionX + motionZ * motionZ); + if(d31 > 0.01D) +@@ -540,37 +522,10 @@ + } + } + } +- } else ++ } ++ else + { +- if(motionX < -d2) +- { +- motionX = -d2; +- } +- if(motionX > d2) +- { +- motionX = d2; +- } +- if(motionZ < -d2) +- { +- motionZ = -d2; +- } +- if(motionZ > d2) +- { +- motionZ = d2; +- } +- if(onGround) +- { +- motionX *= 0.5D; +- motionY *= 0.5D; +- motionZ *= 0.5D; +- } +- moveEntity(motionX, motionY, motionZ); +- if(!onGround) +- { +- motionX *= 0.94999998807907104D; +- motionY *= 0.94999998807907104D; +- motionZ *= 0.94999998807907104D; +- } ++ moveMinecartOffRail(i, j, k); + } + rotationPitch = 0.0F; + double d6 = prevPosX - posX; +@@ -592,7 +547,20 @@ + field_856_i = !field_856_i; + } + setRotation(rotationYaw, rotationPitch); +- List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D)); ++ ++ AxisAlignedBB box = null; ++ ++ if (getCollisionHandler() != null) ++ { ++ box = getCollisionHandler().getMinecartCollisionBox(this); ++ } ++ else ++ { ++ ++ box = boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D); ++ } ++ ++ List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, box); + if(list != null && list.size() > 0) + { + for(int j1 = 0; j1 < list.size(); j1++) +@@ -613,6 +581,178 @@ + } + riddenByEntity = null; + } ++ updateFuel(); ++ ForgeHooks.onMinecartUpdate(this, i, j, k); ++ } ++ ++ /** ++ * Carts should return their drag factor here ++ * @return The drag rate. ++ */ ++ protected double getDrag() ++ { ++ if(riddenByEntity != null) ++ { ++ return 0.99699997901916504D; ++ } ++ return 0.95999997854232788D; ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code applies drag and updates push forces. ++ */ ++ protected void applyDragAndPushForces() ++ { ++ if(isPoweredCart()) ++ { ++ double d27 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); ++ if(d27 > 0.01D) ++ { ++ pushX /= d27; ++ pushZ /= d27; ++ double d29 = 0.040000000000000001D; ++ motionX *= 0.80000001192092896D; ++ motionY *= 0.0D; ++ motionZ *= 0.80000001192092896D; ++ motionX += pushX * d29; ++ motionZ += pushZ * d29; ++ } else ++ { ++ motionX *= 0.89999997615814209D; ++ motionY *= 0.0D; ++ motionZ *= 0.89999997615814209D; ++ } ++ } ++ motionX *= getDrag(); ++ motionY *= 0.0D; ++ motionZ *= getDrag(); ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code updates push forces. ++ */ ++ protected void updatePushForces() ++ { ++ if(isPoweredCart()) ++ { ++ double push = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); ++ if(push > 0.01D && motionX * motionX + motionZ * motionZ > 0.001D) ++ { ++ pushX /= push; ++ pushZ /= push; ++ if(pushX * motionX + pushZ * motionZ < 0.0D) ++ { ++ pushX = 0.0D; ++ pushZ = 0.0D; ++ } else ++ { ++ pushX = motionX; ++ pushZ = motionZ; ++ } ++ } ++ } ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code handles minecart movement and speed capping when on a rail. ++ */ ++ protected void moveMinecartOnRail(int i, int j, int k) ++ { ++ int id = worldObj.getBlockId(i, j, k); ++ if (!BlockRail.isRailBlock(id)) ++ { ++ return; ++ } ++ float railMaxSpeed = ((BlockRail)Block.blocksList[id]).getRailMaxSpeed(worldObj, this, i, j, k); ++ ++ double maxSpeed = Math.min(railMaxSpeed, getMaxSpeedRail()); ++ double d23 = motionX; ++ double d25 = motionZ; ++ if(riddenByEntity != null) ++ { ++ d23 *= 0.75D; ++ d25 *= 0.75D; ++ } ++ if(d23 < -maxSpeed) ++ { ++ d23 = -maxSpeed; ++ } ++ if(d23 > maxSpeed) ++ { ++ d23 = maxSpeed; ++ } ++ if(d25 < -maxSpeed) ++ { ++ d25 = -maxSpeed; ++ } ++ if(d25 > maxSpeed) ++ { ++ d25 = maxSpeed; ++ } ++ moveEntity(d23, 0.0D, d25); ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code handles minecart movement and speed capping when not on a rail. ++ */ ++ protected void moveMinecartOffRail(int i, int j, int k) ++ { ++ double d2 = getMaxSpeedGround(); ++ if(!onGround) ++ { ++ d2 = getMaxSpeedAirLateral(); ++ } ++ if(motionX < -d2) ++ { ++ motionX = -d2; ++ } ++ if(motionX > d2) ++ { ++ motionX = d2; ++ } ++ if(motionZ < -d2) ++ { ++ motionZ = -d2; ++ } ++ if(motionZ > d2) ++ { ++ motionZ = d2; ++ } ++ double moveY = motionY; ++ if(getMaxSpeedAirVertical() > 0 && motionY > getMaxSpeedAirVertical()) ++ { ++ moveY = getMaxSpeedAirVertical(); ++ if(Math.abs(motionX) < 0.3f && Math.abs(motionZ) < 0.3f) ++ { ++ moveY = 0.15f; ++ motionY = moveY; ++ } ++ } ++ if(onGround) ++ { ++ motionX *= 0.5D; ++ motionY *= 0.5D; ++ motionZ *= 0.5D; ++ } ++ moveEntity(motionX, moveY, motionZ); ++ if(!onGround) ++ { ++ motionX *= getDragAir(); ++ motionY *= getDragAir(); ++ motionZ *= getDragAir(); ++ } ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code applies fuel consumption. ++ */ ++ protected void updateFuel() ++ { + if(fuel > 0) + { + fuel--; +@@ -636,11 +776,8 @@ + int l = worldObj.getBlockId(i, j, k); + if(BlockRail.isRailBlock(l)) + { +- int i1 = worldObj.getBlockMetadata(i, j, k); +- if(((BlockRail)Block.blocksList[l]).getIsPowered()) +- { +- i1 &= 7; +- } ++ int i1 = ((BlockRail)Block.blocksList[l]).getBasicRailMetadata(worldObj, this, i, j, k); ++ + d1 = j; + if(i1 >= 2 && i1 <= 5) + { +@@ -681,12 +818,8 @@ + int l = worldObj.getBlockId(i, j, k); + if(BlockRail.isRailBlock(l)) + { +- int i1 = worldObj.getBlockMetadata(i, j, k); ++ int i1 = ((BlockRail)Block.blocksList[l]).getBasicRailMetadata(worldObj, this, i, j, k); + d1 = j; +- if(((BlockRail)Block.blocksList[l]).getIsPowered()) +- { +- i1 &= 7; +- } + if(i1 >= 2 && i1 <= 5) + { + d1 = j + 1; +@@ -739,13 +872,14 @@ + protected void writeEntityToNBT(NBTTagCompound nbttagcompound) + { + nbttagcompound.setInteger("Type", minecartType); +- if(minecartType == 2) ++ if(isPoweredCart()) + { + nbttagcompound.setDouble("PushX", pushX); + nbttagcompound.setDouble("PushZ", pushZ); +- nbttagcompound.setShort("Fuel", (short)fuel); +- } else +- if(minecartType == 1) ++ nbttagcompound.setInteger("Fuel", fuel); ++ } ++ ++ if(getSizeInventory() > 0) + { + NBTTagList nbttaglist = new NBTTagList(); + for(int i = 0; i < cargoItems.length; i++) +@@ -766,13 +900,14 @@ + protected void readEntityFromNBT(NBTTagCompound nbttagcompound) + { + minecartType = nbttagcompound.getInteger("Type"); +- if(minecartType == 2) ++ if(isPoweredCart()) + { + pushX = nbttagcompound.getDouble("PushX"); + pushZ = nbttagcompound.getDouble("PushZ"); +- fuel = nbttagcompound.getShort("Fuel"); +- } else +- if(minecartType == 1) ++ fuel = nbttagcompound.getInteger("Fuel"); ++ } ++ ++ if(getSizeInventory() > 0) + { + NBTTagList nbttaglist = nbttagcompound.getTagList("Items"); + cargoItems = new ItemStack[getSizeInventory()]; +@@ -796,6 +931,16 @@ + + public void applyEntityCollision(Entity entity) + { ++ ForgeHooks.onMinecartEntityCollision(this, entity); ++ ++ ++ if (getCollisionHandler() != null) ++ { ++ getCollisionHandler().onEntityCollision(this, entity); ++ return; ++ } ++ ++ + if(worldObj.multiplayerWorld) + { + return; +@@ -804,7 +949,7 @@ + { + return; + } +- if((entity instanceof EntityLiving) && !(entity instanceof EntityPlayer) && minecartType == 0 && motionX * motionX + motionZ * motionZ > 0.01D && riddenByEntity == null && entity.ridingEntity == null) ++ if((entity instanceof EntityLiving) && !(entity instanceof EntityPlayer) && canBeRidden() && motionX * motionX + motionZ * motionZ > 0.01D && riddenByEntity == null && entity.ridingEntity == null) + { + entity.mountEntity(this); + } +@@ -842,7 +987,7 @@ + } + double d7 = entity.motionX + motionX; + double d8 = entity.motionZ + motionZ; +- if(((EntityMinecart)entity).minecartType == 2 && minecartType != 2) ++ if(((EntityMinecart)entity).isPoweredCart() && !isPoweredCart()) + { + motionX *= 0.20000000298023224D; + motionZ *= 0.20000000298023224D; +@@ -850,7 +995,7 @@ + entity.motionX *= 0.94999998807907104D; + entity.motionZ *= 0.94999998807907104D; + } else +- if(((EntityMinecart)entity).minecartType != 2 && minecartType == 2) ++ if(!((EntityMinecart)entity).isPoweredCart() && isPoweredCart()) + { + entity.motionX *= 0.20000000298023224D; + entity.motionZ *= 0.20000000298023224D; +@@ -878,7 +1023,7 @@ + + public int getSizeInventory() + { +- return 27; ++ return (minecartType == 1 && getClass() == EntityMinecart.class ? 27 : 0); + } + + public ItemStack getStackInSlot(int i) +@@ -933,7 +1078,12 @@ + + public boolean interact(EntityPlayer entityplayer) + { +- if(minecartType == 0) ++ if (!ForgeHooks.onMinecartInteract(this, entityplayer)) ++ { ++ return true; ++ } ++ ++ if(canBeRidden()) + { + if(riddenByEntity != null && (riddenByEntity instanceof EntityPlayer) && riddenByEntity != entityplayer) + { +@@ -944,14 +1094,14 @@ + entityplayer.mountEntity(this); + } + } else +- if(minecartType == 1) ++ if(getSizeInventory() > 0) + { + if(!worldObj.multiplayerWorld) + { + entityplayer.displayGUIChest(this); + } + } else +- if(minecartType == 2) ++ if(minecartType == 2 && getClass() == EntityMinecart.class) + { + ItemStack itemstack = entityplayer.inventory.getCurrentItem(); + if(itemstack != null && itemstack.itemID == Item.coal.shiftedIndex) +@@ -998,7 +1148,7 @@ + return entityplayer.getDistanceSqToEntity(this) <= 64D; + } + +- protected boolean isMinecartPowered() ++ public boolean isMinecartPowered() + { + return (dataWatcher.getWatchableObjectByte(16) & 1) != 0; + } +@@ -1051,5 +1201,203 @@ + { + return dataWatcher.getWatchableObjectInt(18); + } ++ ++ /** ++ * Drops the cart as a item. The exact item dropped is defined by getItemDropped(). ++ */ ++ public void dropCartAsItem() ++ { ++ for(ItemStack item : getItemsDropped()) ++ { ++ entityDropItem(item, 0); ++ } ++ } ++ ++ /** ++ * Override this to define which items your cart drops when broken. ++ * This does not include items contained in the inventory, ++ * that is handled elsewhere. ++ * @return A list of items dropped. ++ */ ++ public List getItemsDropped() ++ { ++ List items = new ArrayList(); ++ items.add(new ItemStack(Item.minecartEmpty)); ++ ++ switch(minecartType) ++ { ++ case 1: ++ items.add(new ItemStack(Block.chest)); ++ break; ++ case 2: ++ items.add(new ItemStack(Block.stoneOvenIdle)); ++ break; ++ } ++ return items; ++ } ++ ++ /** ++ * This function returns an ItemStack that represents this cart. ++ * This should be an ItemStack that can be used by the player to place the cart. ++ * This is the item that was registered with the cart via the registerMinecart function, ++ * but is not necessary the item the cart drops when destroyed. ++ * @return An ItemStack that can be used to place the cart. ++ */ ++ public ItemStack getCartItem() ++ { ++ return MinecraftForge.getItemForCart(this); ++ } ++ ++ /** ++ * Returns true if this cart is self propelled. ++ * @return True if powered. ++ */ ++ public boolean isPoweredCart() ++ { ++ return minecartType == 2 && getClass() == EntityMinecart.class; ++ } ++ ++ /** ++ * Returns true if this cart is a storage cart ++ * Some carts may have inventories but not be storage carts ++ * and some carts without inventories may be storage carts. ++ * @return True if this cart should be classified as a storage cart. ++ */ ++ public boolean isStorageCart() ++ { ++ return minecartType == 1 && getClass() == EntityMinecart.class; ++ } ++ ++ /** ++ * Returns true if this cart can be ridden by an Entity. ++ * @return True if this cart can be ridden. ++ */ ++ public boolean canBeRidden() ++ { ++ if(minecartType == 0 && getClass() == EntityMinecart.class) ++ { ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Returns true if this cart can currently use rails. ++ * This function is mainly used to gracefully detach a minecart from a rail. ++ * @return True if the minecart can use rails. ++ */ ++ public boolean canUseRail() ++ { ++ return canUseRail; ++ } ++ ++ /** ++ * Set whether the minecart can use rails. ++ * This function is mainly used to gracefully detach a minecart from a rail. ++ * @param use Whether the minecart can currently use rails. ++ */ ++ public void setCanUseRail(boolean use) ++ { ++ canUseRail = use; ++ } ++ ++ /** ++ * Return false if this cart should not call IRail.onMinecartPass() and should ignore Powered Rails. ++ * @return True if this cart should call IRail.onMinecartPass(). ++ */ ++ public boolean shouldDoRailFunctions() ++ { ++ return true; ++ } ++ ++ /** ++ * Simply returns the minecartType variable. ++ * @return minecartType ++ */ ++ public int getMinecartType() ++ { ++ return minecartType; ++ } ++ ++ /** ++ * Gets the current global Minecart Collision handler if none ++ * is registered, returns null ++ * @return The collision handler or null ++ */ ++ public static IMinecartCollisionHandler getCollisionHandler() ++ { ++ return collisionHandler; ++ } ++ ++ /** ++ * Sets the global Minecart Collision handler, overwrites any ++ * that is currently set. ++ * @param handler The new handler ++ */ ++ public static void setCollisionHandler(IMinecartCollisionHandler handler) ++ { ++ collisionHandler = handler; ++ } ++ ++ /** ++ * Getters/setters for physics variables ++ */ ++ ++ /** ++ * Returns the carts max speed. ++ * Carts going faster than 1.1 cause issues with chunk loading. ++ * Carts cant traverse slopes or corners at greater than 0.5 - 0.6. ++ * This value is compared with the rails max speed to determine ++ * the carts current max speed. A normal rails max speed is 0.4. ++ * @return Carts max speed. ++ */ ++ public float getMaxSpeedRail() ++ { ++ return maxSpeedRail; ++ } + ++ public void setMaxSpeedRail(float value) ++ { ++ maxSpeedRail = value; ++ } ++ ++ public float getMaxSpeedGround() ++ { ++ return maxSpeedGround; ++ } ++ ++ public void setMaxSpeedGround(float value) ++ { ++ maxSpeedGround = value; ++ } ++ ++ public float getMaxSpeedAirLateral() ++ { ++ return maxSpeedAirLateral; ++ } ++ ++ public void setMaxSpeedAirLateral(float value) ++ { ++ maxSpeedAirLateral = value; ++ } ++ ++ public float getMaxSpeedAirVertical() ++ { ++ return maxSpeedAirVertical; ++ } ++ ++ public void setMaxSpeedAirVertical(float value) ++ { ++ maxSpeedAirVertical = value; ++ } ++ ++ public double getDragAir() ++ { ++ return dragAir; ++ } ++ ++ public void setDragAir(double value) ++ { ++ dragAir = value; ++ } + } diff --git a/forge/patches/minecraft/net/minecraft/src/RailLogic.java.patch b/forge/patches/minecraft/net/minecraft/src/RailLogic.java.patch new file mode 100644 index 000000000..3c794b9e6 --- /dev/null +++ b/forge/patches/minecraft/net/minecraft/src/RailLogic.java.patch @@ -0,0 +1,86 @@ +--- ../src_base/minecraft/net/minecraft/src/RailLogic.java 0000-00-00 00:00:00.000000000 -0000 ++++ ../src_work/minecraft/net/minecraft/src/RailLogic.java 0000-00-00 00:00:00.000000000 -0000 +@@ -10,7 +10,7 @@ + // Referenced classes of package net.minecraft.src: + // World, Block, BlockRail, ChunkPosition + +-class RailLogic ++public class RailLogic + { + + private World worldObj; +@@ -20,6 +20,7 @@ + private final boolean isPoweredRail; + private List connectedTracks; + final BlockRail rail; /* synthetic field */ ++ private final boolean canMakeSlopes; + + public RailLogic(BlockRail blockrail, World world, int i, int j, int k) + { +@@ -31,15 +32,12 @@ + trackY = j; + trackZ = k; + int l = world.getBlockId(i, j, k); +- int i1 = world.getBlockMetadata(i, j, k); +- if(BlockRail.isPoweredBlockRail((BlockRail)Block.blocksList[l])) +- { +- isPoweredRail = true; +- i1 &= -9; +- } else +- { +- isPoweredRail = false; +- } ++ ++ BlockRail target = (BlockRail)Block.blocksList[l]; ++ int i1 = target.getBasicRailMetadata(world, null, i, j, k); ++ isPoweredRail = !target.isFlexibleRail(world, i, j, k); ++ canMakeSlopes = target.canMakeSlopes(world, i, j, k); ++ + setConnections(i1); + } + +@@ -249,7 +247,7 @@ + byte0 = 9; + } + } +- if(byte0 == 0) ++ if(byte0 == 0 && canMakeSlopes) + { + if(BlockRail.isRailBlockAt(worldObj, trackX, trackY + 1, trackZ - 1)) + { +@@ -260,7 +258,7 @@ + byte0 = 5; + } + } +- if(byte0 == 1) ++ if(byte0 == 1 && canMakeSlopes) + { + if(BlockRail.isRailBlockAt(worldObj, trackX + 1, trackY + 1, trackZ)) + { +@@ -381,7 +379,7 @@ + } + } + } +- if(byte0 == 0) ++ if(byte0 == 0 && canMakeSlopes) + { + if(BlockRail.isRailBlockAt(worldObj, trackX, trackY + 1, trackZ - 1)) + { +@@ -392,7 +390,7 @@ + byte0 = 5; + } + } +- if(byte0 == 1) ++ if(byte0 == 1 && canMakeSlopes) + { + if(BlockRail.isRailBlockAt(worldObj, trackX + 1, trackY + 1, trackZ)) + { +@@ -433,7 +431,7 @@ + } + } + +- static int getNAdjacentTracks(RailLogic raillogic) ++ public static int getNAdjacentTracks(RailLogic raillogic) + { + return raillogic.getAdjacentTracks(); + } diff --git a/forge/patches/minecraft_server/net/minecraft/src/BlockRail.java.patch b/forge/patches/minecraft_server/net/minecraft/src/BlockRail.java.patch index 16c10b78d..76b4ad70a 100644 --- a/forge/patches/minecraft_server/net/minecraft/src/BlockRail.java.patch +++ b/forge/patches/minecraft_server/net/minecraft/src/BlockRail.java.patch @@ -1,21 +1,47 @@ --- ../src_base/minecraft_server/net/minecraft/src/BlockRail.java 0000-00-00 00:00:00.000000000 -0000 +++ ../src_work/minecraft_server/net/minecraft/src/BlockRail.java 0000-00-00 00:00:00.000000000 -0000 -@@ -18,12 +18,12 @@ +@@ -14,16 +14,29 @@ + { + + private final boolean isPowered; ++ ++ /** ++ * Forge: Moved render type to a field and a setter. ++ * This allows for a mod to change the render type ++ * for vanilla rails, and any mod rails that extend ++ * this class. ++ */ ++ private int renderType = 9; ++ ++ public void setRenderType(int value) ++ { ++ renderType = value; ++ } + public static final boolean isRailBlockAt(World world, int i, int j, int k) { int l = world.getBlockId(i, j, k); - return l == Block.rail.blockID || l == Block.railPowered.blockID || l == Block.railDetector.blockID; -+ return Block.blocksList[l] instanceof BlockRail; ++ return Block.blocksList[l] instanceof BlockRail; } public static final boolean isRailBlock(int i) { - return i == Block.rail.blockID || i == Block.railPowered.blockID || i == Block.railDetector.blockID; -+ return Block.blocksList[i] instanceof BlockRail; ++ return Block.blocksList[i] instanceof BlockRail; } protected BlockRail(int i, int j, boolean flag) -@@ -99,7 +99,7 @@ +@@ -89,7 +102,7 @@ + + public int getRenderType() + { +- return 9; ++ return renderType; + } + + public int quantityDropped(Random random) +@@ -99,7 +112,7 @@ public boolean canPlaceBlockAt(World world, int i, int j, int k) { @@ -24,7 +50,7 @@ } public void onBlockAdded(World world, int i, int j, int k) -@@ -123,23 +123,23 @@ +@@ -123,23 +136,23 @@ j1 &= 7; } boolean flag = false; @@ -53,3 +79,122 @@ { flag = true; } +@@ -313,8 +326,118 @@ + return 0; + } + ++ /** ++ * This function is no longer called by Minecraft ++ */ + static boolean isPoweredBlockRail(BlockRail blockrail) + { + return blockrail.isPowered; + } ++ ++ /** ++ * Return true if the rail can make corners. ++ * Used by placement logic. ++ * @param world The world. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return True if the rail can make corners. ++ */ ++ public boolean isFlexibleRail(World world, int i, int j, int k) ++ { ++ return !isPowered; ++ } ++ ++ /** ++ * Returns true if the rail can make up and down slopes. ++ * Used by placement logic. ++ * @param world The world. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return True if the rail can make slopes. ++ */ ++ public boolean canMakeSlopes(World world, int i, int j, int k) ++ { ++ return true; ++ } ++ ++ /** ++ * Return the rails metadata (without the power bit if the rail uses one). ++ * Can be used to make the cart think the rail something other than it is, ++ * for example when making diamond junctions or switches. ++ * The cart parameter will often be null unless it it called from EntityMinecart. ++ * ++ * Valid rail metadata is defined as follows: ++ * 0x0: flat track going North-South ++ * 0x1: flat track going West-East ++ * 0x2: track ascending to the East ++ * 0x3: track ascending to the West ++ * 0x4: track ascending to the North ++ * 0x5: track ascending to the South ++ * 0x6: WestNorth corner (connecting East and South) ++ * 0x7: EastNorth corner (connecting West and South) ++ * 0x8: EastSouth corner (connecting West and North) ++ * 0x9: WestSouth corner (connecting East and North) ++ * ++ * All directions are Notch defined. ++ * In MC Beta 1.8.3 the Sun rises in the North. ++ * In MC 1.0.0 the Sun rises in the East. ++ * @param world The world. ++ * @param cart The cart asking for the metadata, null if it is not called by EntityMinecart. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return The metadata. ++ */ ++ public int getBasicRailMetadata(IBlockAccess world, EntityMinecart cart, int i, int j, int k) ++ { ++ int meta = world.getBlockMetadata(i, j, k); ++ if(isPowered) { ++ meta = meta & 7; ++ } ++ return meta; ++ } ++ ++ /** ++ * Returns the max speed of the rail at [i, j, k]. ++ * @param world The world. ++ * @param cart The cart on the rail, may be null. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return The max speed of the current rail. ++ */ ++ public float getRailMaxSpeed(World world, EntityMinecart cart, int i, int j, int k) ++ { ++ return 0.4f; ++ } ++ ++ /** ++ * This function is called by any minecart that passes over this rail. ++ * It is called once per update tick that the minecart is on the rail. ++ * @param world The world. ++ * @param cart The cart on the rail. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ */ ++ public void onMinecartPass(World world, EntityMinecart cart, int i, int j, int k) ++ { ++ } ++ ++ /** ++ * Return true if this rail uses the 4th bit as a power bit. ++ * Avoid using this function when getBasicRailMetadata() can be used instead. ++ * The only reason to use this function is if you wish to change the rails metadata. ++ * @param world The world. ++ * @param i The rail X coordinate. ++ * @param j The rail Y coordinate. ++ * @param k The rail Z coordinate. ++ * @return True if the 4th bit is a power bit. ++ */ ++ public boolean hasPowerBit(World world, int i, int j, int k) ++ { ++ return isPowered; ++ } + } diff --git a/forge/patches/minecraft_server/net/minecraft/src/Entity.java.patch b/forge/patches/minecraft_server/net/minecraft/src/Entity.java.patch index 3fa82ea36..e45ff65d4 100644 --- a/forge/patches/minecraft_server/net/minecraft/src/Entity.java.patch +++ b/forge/patches/minecraft_server/net/minecraft/src/Entity.java.patch @@ -27,19 +27,20 @@ nbttagcompound.setShort("Fire", (short)fire); nbttagcompound.setShort("Air", (short)getAir()); nbttagcompound.setBoolean("OnGround", onGround); -+ if(customEntityData!=null) { -+ nbttagcompound.setCompoundTag("ForgeData", -+ customEntityData); -+ } ++ if (customEntityData != null) ++ { ++ nbttagcompound.setCompoundTag("ForgeEntityData", customEntityData); ++ } writeEntityToNBT(nbttagcompound); } -@@ -907,6 +927,9 @@ +@@ -907,6 +927,10 @@ onGround = nbttagcompound.getBoolean("OnGround"); setPosition(posX, posY, posZ); setRotation(rotationYaw, rotationPitch); -+ if(nbttagcompound.hasKey("ForgeData")) { -+ customEntityData=nbttagcompound.getCompoundTag("ForgeData"); ++ if (nbttagcompound.hasKey("ForgeEntityData")) ++ { ++ customEntityData.getCompoundTag("ForgeEntityData"); + } readEntityFromNBT(nbttagcompound); } diff --git a/forge/patches/minecraft_server/net/minecraft/src/EntityMinecart.java.patch b/forge/patches/minecraft_server/net/minecraft/src/EntityMinecart.java.patch new file mode 100644 index 000000000..34448acee --- /dev/null +++ b/forge/patches/minecraft_server/net/minecraft/src/EntityMinecart.java.patch @@ -0,0 +1,910 @@ +--- ../src_base/minecraft_server/net/minecraft/src/EntityMinecart.java 0000-00-00 00:00:00.000000000 -0000 ++++ ../src_work/minecraft_server/net/minecraft/src/EntityMinecart.java 0000-00-00 00:00:00.000000000 -0000 +@@ -4,9 +4,14 @@ + + package net.minecraft.src; + ++import java.util.ArrayList; + import java.util.List; + import java.util.Random; + ++import net.minecraft.src.forge.ForgeHooks; ++import net.minecraft.src.forge.IMinecartCollisionHandler; ++import net.minecraft.src.forge.MinecraftForge; ++ + // Referenced classes of package net.minecraft.src: + // Entity, IInventory, ItemStack, DataWatcher, + // World, Item, EntityItem, Block, +@@ -18,13 +23,13 @@ + implements IInventory + { + +- private ItemStack cargoItems[]; +- private int fuel; +- private boolean field_469_aj; ++ protected ItemStack cargoItems[]; ++ protected int fuel; ++ protected boolean field_469_aj; + public int minecartType; + public double pushX; + public double pushZ; +- private static final int field_468_ak[][][] = { ++ protected static final int field_468_ak[][][] = { + { + { + 0, 0, -1 +@@ -87,13 +92,36 @@ + } + } + }; +- private int turnProgress; +- private double minecartX; +- private double minecartY; +- private double minecartZ; +- private double field_9159_ar; +- private double minecartPitch; +- ++ protected int turnProgress; ++ protected double minecartX; ++ protected double minecartY; ++ protected double minecartZ; ++ protected double field_9159_ar; ++ protected double minecartPitch; ++ ++ /*Forge: Minecart Compatibility Layer Integration. ++ */ ++ protected double velocityX; ++ protected double velocityY; ++ protected double velocityZ; ++ public static float defaultMaxSpeedRail = 0.4f; ++ public static float defaultMaxSpeedGround = 0.4f; ++ public static float defaultMaxSpeedAirLateral = 0.4f; ++ public static float defaultMaxSpeedAirVertical = -1f; ++ public static double defaultDragAir = 0.94999998807907104D; ++ protected boolean canUseRail = true; ++ protected boolean canBePushed = true; ++ private static IMinecartCollisionHandler collisionHandler = null; ++ ++ /* ++ * Instance versions of the above physics properties ++ */ ++ protected float maxSpeedRail; ++ protected float maxSpeedGround; ++ protected float maxSpeedAirLateral; ++ protected float maxSpeedAirVertical; ++ protected double dragAir; ++ + public EntityMinecart(World world) + { + super(world); +@@ -103,6 +131,18 @@ + preventEntitySpawning = true; + setSize(0.98F, 0.7F); + yOffset = height / 2.0F; ++ ++ maxSpeedRail = defaultMaxSpeedRail; ++ maxSpeedGround = defaultMaxSpeedGround; ++ maxSpeedAirLateral = defaultMaxSpeedAirLateral; ++ maxSpeedAirVertical = defaultMaxSpeedAirVertical; ++ dragAir = defaultDragAir; ++ } ++ ++ public EntityMinecart(World world, int type) ++ { ++ this(world); ++ minecartType = type; + } + + protected boolean canTriggerWalking() +@@ -120,17 +160,27 @@ + + public AxisAlignedBB getCollisionBox(Entity entity) + { ++ if (getCollisionHandler() != null) ++ { ++ return getCollisionHandler().getCollisionBox(this, entity); ++ } ++ + return entity.boundingBox; + } + + public AxisAlignedBB getBoundingBox() + { ++ if (getCollisionHandler() != null) ++ { ++ return getCollisionHandler().getBoundingBox(this); ++ } ++ + return null; + } + + public boolean canBePushed() + { +- return true; ++ return canBePushed; + } + + public EntityMinecart(World world, double d, double d1, double d2, +@@ -169,8 +219,10 @@ + riddenByEntity.mountEntity(this); + } + setEntityDead(); +- dropItemWithOffset(Item.minecartEmpty.shiftedIndex, 1, 0.0F); +- if(minecartType == 1) ++ ++ dropCartAsItem(); ++ ++ if(getSizeInventory() > 0) + { + EntityMinecart entityminecart = this; + label0: +@@ -204,12 +256,6 @@ + worldObj.entityJoinedWorld(entityitem); + } while(true); + } +- +- dropItemWithOffset(Block.chest.blockID, 1, 0.0F); +- } else +- if(minecartType == 2) +- { +- dropItemWithOffset(Block.stoneOvenIdle.blockID, 1, 0.0F); + } + } + return true; +@@ -267,7 +313,7 @@ + { + func_41018_e_(func_41020_o() - 1); + } +- if(isMinecartPowered() && rand.nextInt(4) == 0) ++ if(isMinecartPowered() && rand.nextInt(4) == 0 && minecartType == 2 && getClass() == EntityMinecart.class) + { + worldObj.spawnParticle("largesmoke", posX, posY + 0.80000000000000004D, posZ, 0.0D, 0.0D, 0.0D); + } +@@ -307,22 +353,19 @@ + double d2 = 0.40000000000000002D; + double d4 = 0.0078125D; + int l = worldObj.getBlockId(i, j, k); +- if(BlockRail.isRailBlock(l)) ++ if(canUseRail() && BlockRail.isRailBlock(l)) + { + Vec3D vec3d = func_182_g(posX, posY, posZ); +- int i1 = worldObj.getBlockMetadata(i, j, k); ++ int i1 = ((BlockRail)Block.blocksList[l]).getBasicRailMetadata(worldObj, this, i, j, k);; + posY = j; + boolean flag = false; + boolean flag1 = false; + if(l == Block.railPowered.blockID) + { +- flag = (i1 & 8) != 0; ++ flag = (worldObj.getBlockMetadata(i, j, k) & 8) != 0; + flag1 = !flag; + } +- if(((BlockRail)Block.blocksList[l]).getIsPowered()) +- { +- i1 &= 7; +- } ++ + if(i1 >= 2 && i1 <= 5) + { + posY = j + 1; +@@ -356,7 +399,8 @@ + double d13 = Math.sqrt(motionX * motionX + motionZ * motionZ); + motionX = (d13 * d9) / d11; + motionZ = (d13 * d10) / d11; +- if(flag1) ++ ++ if(flag1 && shouldDoRailFunctions()) + { + double d16 = Math.sqrt(motionX * motionX + motionZ * motionZ); + if(d16 < 0.029999999999999999D) +@@ -397,30 +441,9 @@ + posX = d18 + d9 * d17; + posZ = d19 + d10 * d17; + setPosition(posX, posY + (double)yOffset, posZ); +- double d23 = motionX; +- double d25 = motionZ; +- if(riddenByEntity != null) +- { +- d23 *= 0.75D; +- d25 *= 0.75D; +- } +- if(d23 < -d2) +- { +- d23 = -d2; +- } +- if(d23 > d2) +- { +- d23 = d2; +- } +- if(d25 < -d2) +- { +- d25 = -d2; +- } +- if(d25 > d2) +- { +- d25 = d2; +- } +- moveEntity(d23, 0.0D, d25); ++ ++ moveMinecartOnRail(i, j, k); ++ + if(ai[0][1] != 0 && MathHelper.floor_double(posX) - i == ai[0][0] && MathHelper.floor_double(posZ) - k == ai[0][2]) + { + setPosition(posX, posY + (double)ai[0][1], posZ); +@@ -429,37 +452,9 @@ + { + setPosition(posX, posY + (double)ai[1][1], posZ); + } +- if(riddenByEntity != null) +- { +- motionX *= 0.99699997901916504D; +- motionY *= 0.0D; +- motionZ *= 0.99699997901916504D; +- } else +- { +- if(minecartType == 2) +- { +- double d27 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); +- if(d27 > 0.01D) +- { +- pushX /= d27; +- pushZ /= d27; +- double d29 = 0.040000000000000001D; +- motionX *= 0.80000001192092896D; +- motionY *= 0.0D; +- motionZ *= 0.80000001192092896D; +- motionX += pushX * d29; +- motionZ += pushZ * d29; +- } else +- { +- motionX *= 0.89999997615814209D; +- motionY *= 0.0D; +- motionZ *= 0.89999997615814209D; +- } +- } +- motionX *= 0.95999997854232788D; +- motionY *= 0.0D; +- motionZ *= 0.95999997854232788D; +- } ++ ++ applyDragAndPushForces(); ++ + Vec3D vec3d1 = func_182_g(posX, posY, posZ); + if(vec3d1 != null && vec3d != null) + { +@@ -480,25 +475,15 @@ + motionX = d15 * (double)(k1 - i); + motionZ = d15 * (double)(l1 - k); + } +- if(minecartType == 2) ++ ++ updatePushForces(); ++ ++ if (shouldDoRailFunctions()) + { +- double d30 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); +- if(d30 > 0.01D && motionX * motionX + motionZ * motionZ > 0.001D) +- { +- pushX /= d30; +- pushZ /= d30; +- if(pushX * motionX + pushZ * motionZ < 0.0D) +- { +- pushX = 0.0D; +- pushZ = 0.0D; +- } else +- { +- pushX = motionX; +- pushZ = motionZ; +- } +- } ++ ((BlockRail)Block.blocksList[l]).onMinecartPass(worldObj, this, i, j, k); + } +- if(flag) ++ ++ if(flag && shouldDoRailFunctions()) + { + double d31 = Math.sqrt(motionX * motionX + motionZ * motionZ); + if(d31 > 0.01D) +@@ -530,37 +515,10 @@ + } + } + } +- } else ++ } ++ else + { +- if(motionX < -d2) +- { +- motionX = -d2; +- } +- if(motionX > d2) +- { +- motionX = d2; +- } +- if(motionZ < -d2) +- { +- motionZ = -d2; +- } +- if(motionZ > d2) +- { +- motionZ = d2; +- } +- if(onGround) +- { +- motionX *= 0.5D; +- motionY *= 0.5D; +- motionZ *= 0.5D; +- } +- moveEntity(motionX, motionY, motionZ); +- if(!onGround) +- { +- motionX *= 0.94999998807907104D; +- motionY *= 0.94999998807907104D; +- motionZ *= 0.94999998807907104D; +- } ++ moveMinecartOffRail(i, j, k); + } + rotationPitch = 0.0F; + double d6 = prevPosX - posX; +@@ -582,7 +540,20 @@ + field_469_aj = !field_469_aj; + } + setRotation(rotationYaw, rotationPitch); +- List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D)); ++ ++ AxisAlignedBB box = null; ++ ++ if (getCollisionHandler() != null) ++ { ++ box = getCollisionHandler().getMinecartCollisionBox(this); ++ } ++ else ++ { ++ ++ box = boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D); ++ } ++ ++ List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, box); + if(list != null && list.size() > 0) + { + for(int j1 = 0; j1 < list.size(); j1++) +@@ -603,6 +574,178 @@ + } + riddenByEntity = null; + } ++ updateFuel(); ++ ForgeHooks.onMinecartUpdate(this, i, j, k); ++ } ++ ++ /** ++ * Carts should return their drag factor here ++ * @return The drag rate. ++ */ ++ protected double getDrag() ++ { ++ if(riddenByEntity != null) ++ { ++ return 0.99699997901916504D; ++ } ++ return 0.95999997854232788D; ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code applies drag and updates push forces. ++ */ ++ protected void applyDragAndPushForces() ++ { ++ if(isPoweredCart()) ++ { ++ double d27 = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); ++ if(d27 > 0.01D) ++ { ++ pushX /= d27; ++ pushZ /= d27; ++ double d29 = 0.040000000000000001D; ++ motionX *= 0.80000001192092896D; ++ motionY *= 0.0D; ++ motionZ *= 0.80000001192092896D; ++ motionX += pushX * d29; ++ motionZ += pushZ * d29; ++ } else ++ { ++ motionX *= 0.89999997615814209D; ++ motionY *= 0.0D; ++ motionZ *= 0.89999997615814209D; ++ } ++ } ++ motionX *= getDrag(); ++ motionY *= 0.0D; ++ motionZ *= getDrag(); ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code updates push forces. ++ */ ++ protected void updatePushForces() ++ { ++ if(isPoweredCart()) ++ { ++ double push = MathHelper.sqrt_double(pushX * pushX + pushZ * pushZ); ++ if(push > 0.01D && motionX * motionX + motionZ * motionZ > 0.001D) ++ { ++ pushX /= push; ++ pushZ /= push; ++ if(pushX * motionX + pushZ * motionZ < 0.0D) ++ { ++ pushX = 0.0D; ++ pushZ = 0.0D; ++ } else ++ { ++ pushX = motionX; ++ pushZ = motionZ; ++ } ++ } ++ } ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code handles minecart movement and speed capping when on a rail. ++ */ ++ protected void moveMinecartOnRail(int i, int j, int k) ++ { ++ int id = worldObj.getBlockId(i, j, k); ++ if (!BlockRail.isRailBlock(id)) ++ { ++ return; ++ } ++ float railMaxSpeed = ((BlockRail)Block.blocksList[id]).getRailMaxSpeed(worldObj, this, i, j, k); ++ ++ double maxSpeed = Math.min(railMaxSpeed, getMaxSpeedRail()); ++ double d23 = motionX; ++ double d25 = motionZ; ++ if(riddenByEntity != null) ++ { ++ d23 *= 0.75D; ++ d25 *= 0.75D; ++ } ++ if(d23 < -maxSpeed) ++ { ++ d23 = -maxSpeed; ++ } ++ if(d23 > maxSpeed) ++ { ++ d23 = maxSpeed; ++ } ++ if(d25 < -maxSpeed) ++ { ++ d25 = -maxSpeed; ++ } ++ if(d25 > maxSpeed) ++ { ++ d25 = maxSpeed; ++ } ++ moveEntity(d23, 0.0D, d25); ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code handles minecart movement and speed capping when not on a rail. ++ */ ++ protected void moveMinecartOffRail(int i, int j, int k) ++ { ++ double d2 = getMaxSpeedGround(); ++ if(!onGround) ++ { ++ d2 = getMaxSpeedAirLateral(); ++ } ++ if(motionX < -d2) ++ { ++ motionX = -d2; ++ } ++ if(motionX > d2) ++ { ++ motionX = d2; ++ } ++ if(motionZ < -d2) ++ { ++ motionZ = -d2; ++ } ++ if(motionZ > d2) ++ { ++ motionZ = d2; ++ } ++ double moveY = motionY; ++ if(getMaxSpeedAirVertical() > 0 && motionY > getMaxSpeedAirVertical()) ++ { ++ moveY = getMaxSpeedAirVertical(); ++ if(Math.abs(motionX) < 0.3f && Math.abs(motionZ) < 0.3f) ++ { ++ moveY = 0.15f; ++ motionY = moveY; ++ } ++ } ++ if(onGround) ++ { ++ motionX *= 0.5D; ++ motionY *= 0.5D; ++ motionZ *= 0.5D; ++ } ++ moveEntity(motionX, moveY, motionZ); ++ if(!onGround) ++ { ++ motionX *= getDragAir(); ++ motionY *= getDragAir(); ++ motionZ *= getDragAir(); ++ } ++ } ++ ++ /** ++ * Moved to allow overrides. ++ * This code applies fuel consumption. ++ */ ++ protected void updateFuel() ++ { + if(fuel > 0) + { + fuel--; +@@ -626,12 +769,8 @@ + int l = worldObj.getBlockId(i, j, k); + if(BlockRail.isRailBlock(l)) + { +- int i1 = worldObj.getBlockMetadata(i, j, k); ++ int i1 = ((BlockRail)Block.blocksList[l]).getBasicRailMetadata(worldObj, this, i, j, k); + d1 = j; +- if(((BlockRail)Block.blocksList[l]).getIsPowered()) +- { +- i1 &= 7; +- } + if(i1 >= 2 && i1 <= 5) + { + d1 = j + 1; +@@ -684,13 +823,14 @@ + protected void writeEntityToNBT(NBTTagCompound nbttagcompound) + { + nbttagcompound.setInteger("Type", minecartType); +- if(minecartType == 2) ++ if(isPoweredCart()) + { + nbttagcompound.setDouble("PushX", pushX); + nbttagcompound.setDouble("PushZ", pushZ); +- nbttagcompound.setShort("Fuel", (short)fuel); +- } else +- if(minecartType == 1) ++ nbttagcompound.setInteger("Fuel", fuel); ++ } ++ ++ if(getSizeInventory() > 0) + { + NBTTagList nbttaglist = new NBTTagList(); + for(int i = 0; i < cargoItems.length; i++) +@@ -703,7 +843,6 @@ + nbttaglist.setTag(nbttagcompound1); + } + } +- + nbttagcompound.setTag("Items", nbttaglist); + } + } +@@ -711,13 +850,14 @@ + protected void readEntityFromNBT(NBTTagCompound nbttagcompound) + { + minecartType = nbttagcompound.getInteger("Type"); +- if(minecartType == 2) ++ if(isPoweredCart()) + { + pushX = nbttagcompound.getDouble("PushX"); + pushZ = nbttagcompound.getDouble("PushZ"); +- fuel = nbttagcompound.getShort("Fuel"); +- } else +- if(minecartType == 1) ++ fuel = nbttagcompound.getInteger("Fuel"); ++ } ++ ++ if(getSizeInventory() > 0) + { + NBTTagList nbttaglist = nbttagcompound.getTagList("Items"); + cargoItems = new ItemStack[getSizeInventory()]; +@@ -730,12 +870,19 @@ + cargoItems[j] = ItemStack.loadItemStackFromNBT(nbttagcompound1); + } + } +- + } + } + + public void applyEntityCollision(Entity entity) + { ++ ForgeHooks.onMinecartEntityCollision(this, entity); ++ ++ if (getCollisionHandler() != null) ++ { ++ getCollisionHandler().onEntityCollision(this, entity); ++ return; ++ } ++ + if(worldObj.singleplayerWorld) + { + return; +@@ -744,7 +891,7 @@ + { + return; + } +- if((entity instanceof EntityLiving) && !(entity instanceof EntityPlayer) && minecartType == 0 && motionX * motionX + motionZ * motionZ > 0.01D && riddenByEntity == null && entity.ridingEntity == null) ++ if((entity instanceof EntityLiving) && !(entity instanceof EntityPlayer) && canBeRidden() && motionX * motionX + motionZ * motionZ > 0.01D && riddenByEntity == null && entity.ridingEntity == null) + { + entity.mountEntity(this); + } +@@ -782,7 +929,7 @@ + } + double d7 = entity.motionX + motionX; + double d8 = entity.motionZ + motionZ; +- if(((EntityMinecart)entity).minecartType == 2 && minecartType != 2) ++ if(((EntityMinecart)entity).isPoweredCart() && !isPoweredCart()) + { + motionX *= 0.20000000298023224D; + motionZ *= 0.20000000298023224D; +@@ -790,7 +937,7 @@ + entity.motionX *= 0.94999998807907104D; + entity.motionZ *= 0.94999998807907104D; + } else +- if(((EntityMinecart)entity).minecartType != 2 && minecartType == 2) ++ if(!((EntityMinecart)entity).isPoweredCart() && isPoweredCart()) + { + entity.motionX *= 0.20000000298023224D; + entity.motionZ *= 0.20000000298023224D; +@@ -818,7 +965,7 @@ + + public int getSizeInventory() + { +- return 27; ++ return (minecartType == 1 && getClass() == EntityMinecart.class ? 27 : 0); + } + + public ItemStack getStackInSlot(int i) +@@ -873,7 +1020,12 @@ + + public boolean interact(EntityPlayer entityplayer) + { +- if(minecartType == 0) ++ if (!ForgeHooks.onMinecartInteract(this, entityplayer)) ++ { ++ return true; ++ } ++ ++ if(canBeRidden()) + { + if(riddenByEntity != null && (riddenByEntity instanceof EntityPlayer) && riddenByEntity != entityplayer) + { +@@ -884,14 +1036,14 @@ + entityplayer.mountEntity(this); + } + } else +- if(minecartType == 1) ++ if(getSizeInventory() > 0) + { + if(!worldObj.singleplayerWorld) + { + entityplayer.displayGUIChest(this); + } + } else +- if(minecartType == 2) ++ if(minecartType == 2 && getClass() == EntityMinecart.class) + { + ItemStack itemstack = entityplayer.inventory.getCurrentItem(); + if(itemstack != null && itemstack.itemID == Item.coal.shiftedIndex) +@@ -917,7 +1069,7 @@ + return entityplayer.getDistanceSqToEntity(this) <= 64D; + } + +- protected boolean isMinecartPowered() ++ public boolean isMinecartPowered() + { + return (dataWatcher.getWatchableObjectByte(16) & 1) != 0; + } +@@ -970,5 +1122,203 @@ + { + return dataWatcher.getWatchableObjectInt(18); + } ++ ++ /** ++ * Drops the cart as a item. The exact item dropped is defined by getItemDropped(). ++ */ ++ public void dropCartAsItem() ++ { ++ for(ItemStack item : getItemsDropped()) ++ { ++ entityDropItem(item, 0); ++ } ++ } ++ ++ /** ++ * Override this to define which items your cart drops when broken. ++ * This does not include items contained in the inventory, ++ * that is handled elsewhere. ++ * @return A list of items dropped. ++ */ ++ public List getItemsDropped() ++ { ++ List items = new ArrayList(); ++ items.add(new ItemStack(Item.minecartEmpty)); ++ ++ switch(minecartType) ++ { ++ case 1: ++ items.add(new ItemStack(Block.chest)); ++ break; ++ case 2: ++ items.add(new ItemStack(Block.stoneOvenIdle)); ++ break; ++ } ++ return items; ++ } ++ ++ /** ++ * This function returns an ItemStack that represents this cart. ++ * This should be an ItemStack that can be used by the player to place the cart. ++ * This is the item that was registered with the cart via the registerMinecart function, ++ * but is not necessary the item the cart drops when destroyed. ++ * @return An ItemStack that can be used to place the cart. ++ */ ++ public ItemStack getCartItem() ++ { ++ return MinecraftForge.getItemForCart(this); ++ } ++ ++ /** ++ * Returns true if this cart is self propelled. ++ * @return True if powered. ++ */ ++ public boolean isPoweredCart() ++ { ++ return minecartType == 2 && getClass() == EntityMinecart.class; ++ } ++ ++ /** ++ * Returns true if this cart is a storage cart ++ * Some carts may have inventories but not be storage carts ++ * and some carts without inventories may be storage carts. ++ * @return True if this cart should be classified as a storage cart. ++ */ ++ public boolean isStorageCart() ++ { ++ return minecartType == 1 && getClass() == EntityMinecart.class; ++ } ++ ++ /** ++ * Returns true if this cart can be ridden by an Entity. ++ * @return True if this cart can be ridden. ++ */ ++ public boolean canBeRidden() ++ { ++ if(minecartType == 0 && getClass() == EntityMinecart.class) ++ { ++ return true; ++ } ++ return false; ++ } ++ ++ /** ++ * Returns true if this cart can currently use rails. ++ * This function is mainly used to gracefully detach a minecart from a rail. ++ * @return True if the minecart can use rails. ++ */ ++ public boolean canUseRail() ++ { ++ return canUseRail; ++ } ++ ++ /** ++ * Set whether the minecart can use rails. ++ * This function is mainly used to gracefully detach a minecart from a rail. ++ * @param use Whether the minecart can currently use rails. ++ */ ++ public void setCanUseRail(boolean use) ++ { ++ canUseRail = use; ++ } ++ ++ /** ++ * Return false if this cart should not call IRail.onMinecartPass() and should ignore Powered Rails. ++ * @return True if this cart should call IRail.onMinecartPass(). ++ */ ++ public boolean shouldDoRailFunctions() ++ { ++ return true; ++ } ++ ++ /** ++ * Simply returns the minecartType variable. ++ * @return minecartType ++ */ ++ public int getMinecartType() ++ { ++ return minecartType; ++ } ++ ++ /** ++ * Gets the current global Minecart Collision handler if none ++ * is registered, returns null ++ * @return The collision handler or null ++ */ ++ public static IMinecartCollisionHandler getCollisionHandler() ++ { ++ return collisionHandler; ++ } ++ ++ /** ++ * Sets the global Minecart Collision handler, overwrites any ++ * that is currently set. ++ * @param handler The new handler ++ */ ++ public static void setCollisionHandler(IMinecartCollisionHandler handler) ++ { ++ collisionHandler = handler; ++ } ++ ++ /** ++ * Getters/setters for physics variables ++ */ ++ ++ /** ++ * Returns the carts max speed. ++ * Carts going faster than 1.1 cause issues with chunk loading. ++ * Carts cant traverse slopes or corners at greater than 0.5 - 0.6. ++ * This value is compared with the rails max speed to determine ++ * the carts current max speed. A normal rails max speed is 0.4. ++ * @return Carts max speed. ++ */ ++ public float getMaxSpeedRail() ++ { ++ return maxSpeedRail; ++ } + ++ public void setMaxSpeedRail(float value) ++ { ++ maxSpeedRail = value; ++ } ++ ++ public float getMaxSpeedGround() ++ { ++ return maxSpeedGround; ++ } ++ ++ public void setMaxSpeedGround(float value) ++ { ++ maxSpeedGround = value; ++ } ++ ++ public float getMaxSpeedAirLateral() ++ { ++ return maxSpeedAirLateral; ++ } ++ ++ public void setMaxSpeedAirLateral(float value) ++ { ++ maxSpeedAirLateral = value; ++ } ++ ++ public float getMaxSpeedAirVertical() ++ { ++ return maxSpeedAirVertical; ++ } ++ ++ public void setMaxSpeedAirVertical(float value) ++ { ++ maxSpeedAirVertical = value; ++ } ++ ++ public double getDragAir() ++ { ++ return dragAir; ++ } ++ ++ public void setDragAir(double value) ++ { ++ dragAir = value; ++ } + } diff --git a/forge/patches/minecraft_server/net/minecraft/src/RailLogic.java.patch b/forge/patches/minecraft_server/net/minecraft/src/RailLogic.java.patch new file mode 100644 index 000000000..4428dd8a4 --- /dev/null +++ b/forge/patches/minecraft_server/net/minecraft/src/RailLogic.java.patch @@ -0,0 +1,77 @@ +--- ../src_base/minecraft_server/net/minecraft/src/RailLogic.java 0000-00-00 00:00:00.000000000 -0000 ++++ ../src_work/minecraft_server/net/minecraft/src/RailLogic.java 0000-00-00 00:00:00.000000000 -0000 +@@ -10,7 +10,7 @@ + // Referenced classes of package net.minecraft.src: + // World, Block, BlockRail, ChunkPosition + +-class RailLogic ++public class RailLogic + { + + private World worldObj; +@@ -20,6 +20,7 @@ + private final boolean isPoweredRail; + private List connectedTracks; + final BlockRail rail; /* synthetic field */ ++ private final boolean canMakeSlopes; + + public RailLogic(BlockRail blockrail, World world, int i, int j, int k) + { +@@ -31,15 +32,12 @@ + trackY = j; + trackZ = k; + int l = world.getBlockId(i, j, k); +- int i1 = world.getBlockMetadata(i, j, k); +- if(BlockRail.isPoweredBlockRail((BlockRail)Block.blocksList[l])) +- { +- isPoweredRail = true; +- i1 &= -9; +- } else +- { +- isPoweredRail = false; +- } ++ ++ BlockRail target = (BlockRail)Block.blocksList[l]; ++ int i1 = target.getBasicRailMetadata(world, null, i, j, k); ++ isPoweredRail = !target.isFlexibleRail(world, i, j, k); ++ canMakeSlopes = target.canMakeSlopes(world, i, j, k); ++ + setConnections(i1); + } + +@@ -249,7 +247,7 @@ + byte0 = 9; + } + } +- if(byte0 == 0) ++ if(byte0 == 0 && canMakeSlopes) + { + if(BlockRail.isRailBlockAt(worldObj, trackX, trackY + 1, trackZ - 1)) + { +@@ -260,7 +258,7 @@ + byte0 = 5; + } + } +- if(byte0 == 1) ++ if(byte0 == 1 && canMakeSlopes) + { + if(BlockRail.isRailBlockAt(worldObj, trackX + 1, trackY + 1, trackZ)) + { +@@ -381,7 +379,7 @@ + } + } + } +- if(byte0 == 0) ++ if(byte0 == 0 && canMakeSlopes) + { + if(BlockRail.isRailBlockAt(worldObj, trackX, trackY + 1, trackZ - 1)) + { +@@ -392,7 +390,7 @@ + byte0 = 5; + } + } +- if(byte0 == 1) ++ if(byte0 == 1 && canMakeSlopes) + { + if(BlockRail.isRailBlockAt(worldObj, trackX + 1, trackY + 1, trackZ)) + {