Merge remote-tracking branch 'origin/1.8'

This commit is contained in:
Lex Manos committed 2015-01-31 18:56:00 -08:00
commit c374ba5463
458 files changed
+13442 -14297

No files matched your search

@@ -3,7 +3,7 @@ package net.minecraftforge.classloading;
import java.io.File;
import java.util.Map;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
public class FMLForgePlugin implements IFMLLoadingPlugin
{
@@ -12,17 +12,17 @@ import net.minecraft.command.WrongUsageException;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.CommandEvent;
import cpw.mods.fml.client.FMLClientHandler;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraft.util.EnumChatFormatting;
import static net.minecraft.util.EnumChatFormatting.*;
/**
* The class that handles client-side chat commands. You should register any
* commands that you want handled on the client with this command handler.
*
*
* If there is a command with the same name registered both on the server and
* client, the client takes precedence!
*
*
*/
public class ClientCommandHandler extends CommandHandler
{
@@ -57,7 +57,7 @@ public class ClientCommandHandler extends CommandHandler
return 0;
}
if (icommand.canCommandSenderUseCommand(sender))
if (icommand.canCommandSenderUse(sender))
{
CommandEvent event = new CommandEvent(icommand, sender, args);
if (MinecraftForge.EVENT_BUS.post(event))
@@ -69,7 +69,7 @@ public class ClientCommandHandler extends CommandHandler
return 0;
}
icommand.processCommand(sender, args);
icommand.execute(sender, args);
return 1;
}
else
@@ -79,11 +79,11 @@ public class ClientCommandHandler extends CommandHandler
}
catch (WrongUsageException wue)
{
sender.addChatMessage(format(RED, "commands.generic.usage", format(RED, wue.getMessage(), wue.getErrorOjbects())));
sender.addChatMessage(format(RED, "commands.generic.usage", format(RED, wue.getMessage(), wue.getErrorObjects())));
}
catch (CommandException ce)
{
sender.addChatMessage(format(RED, ce.getMessage(), ce.getErrorOjbects()));
sender.addChatMessage(format(RED, ce.getMessage(), ce.getErrorObjects()));
}
catch (Throwable t)
{
@@ -114,7 +114,7 @@ public class ClientCommandHandler extends CommandHandler
if (mc.currentScreen instanceof GuiChat)
{
@SuppressWarnings("unchecked")
List<String> commands = getPossibleCommands(mc.thePlayer, leftOfCursor);
List<String> commands = getTabCompletionOptions(mc.thePlayer, leftOfCursor, mc.thePlayer.getPosition());
if (commands != null && !commands.isEmpty())
{
if (leftOfCursor.indexOf(' ') == -1)
@@ -1,70 +1,77 @@
package net.minecraftforge.client;
import java.util.Random;
import static net.minecraftforge.common.ForgeVersion.Status.BETA;
import static net.minecraftforge.common.ForgeVersion.Status.BETA_OUTDATED;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import javax.imageio.ImageIO;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import net.minecraftforge.client.event.MouseEvent;
import javax.vecmath.Matrix4f;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.ISound;
import net.minecraft.client.audio.SoundEventAccessorComposite;
import net.minecraft.client.audio.SoundManager;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraftforge.client.event.FOVUpdateEvent;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.PixelFormat;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.FMLLog;
import net.minecraft.client.Minecraft;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.ChunkCache;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemTransformVec3f;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.client.renderer.vertex.VertexFormatElement.EnumUsage;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.settings.GameSettings;
import net.minecraftforge.client.IItemRenderer.ItemRenderType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.EnumWorldBlockLayer;
import net.minecraft.util.IRegistry;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.client.event.EntityViewRenderEvent;
import net.minecraftforge.client.event.FOVUpdateEvent;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.MouseEvent;
import net.minecraftforge.client.event.RenderHandEvent;
import net.minecraftforge.client.event.RenderWorldEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.event.sound.PlaySoundEvent17;
import net.minecraftforge.client.event.sound.PlaySoundEvent;
import net.minecraftforge.client.model.IPerspectiveAwareModel;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.ForgeVersion.Status;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.RenderBlockFluid;
import static net.minecraftforge.client.IItemRenderer.ItemRenderType.*;
import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.*;
import static net.minecraftforge.common.ForgeVersion.Status.*;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
//import static net.minecraftforge.client.IItemRenderer.ItemRenderType.*;
//import static net.minecraftforge.client.IItemRenderer.ItemRendererHelper.*;
public class ForgeHooksClient
{
@@ -81,6 +88,8 @@ public class ForgeHooksClient
return result != null ? result : _default;
}
/*
* Removed, Modders let me know if this is needed anymore.
public static boolean renderEntityItem(EntityItem entity, ItemStack item, float bobing, float rotation, Random random, TextureManager engine, RenderBlocks renderBlocks, int count)
{
IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(item, ENTITY);
@@ -147,9 +156,12 @@ public class ForgeHooksClient
GL11.glScalef(0.5F, 0.5F, 0.5F);
customRenderer.renderItem(ENTITY, item, renderBlocks, entity);
}
return true;
}
*/
/*
public static boolean renderInventoryItem(RenderBlocks renderBlocks, TextureManager engine, ItemStack item, boolean inColor, float zLevel, float x, float y)
{
IItemRenderer customRenderer = MinecraftForgeClient.getItemRenderer(item, INVENTORY);
@@ -233,21 +245,18 @@ public class ForgeHooksClient
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
GL11.glPopMatrix();
}
}
}*/
//Optifine Helper Functions u.u, these are here specifically for Optifine
//Note: When using Optfine, these methods are invoked using reflection, which
//incurs a major performance penalty.
public static void orientBedCamera(Minecraft mc, EntityLivingBase entity)
public static void orientBedCamera(IBlockAccess world, BlockPos pos, IBlockState state, Entity entity)
{
int x = MathHelper.floor_double(entity.posX);
int y = MathHelper.floor_double(entity.posY);
int z = MathHelper.floor_double(entity.posZ);
Block block = mc.theWorld.getBlock(x, y, z);
Block block = state.getBlock();
if (block != null && block.isBed(mc.theWorld, x, y, z, entity))
if (block != null && block.isBed(world, pos, entity))
{
GL11.glRotatef((float)(block.getBedDirection(mc.theWorld, x, y, z) * 90), 0.0F, 1.0F, 0.0F);
GL11.glRotatef((float)(block.getBedDirection(world, pos).getHorizontalIndex() * 90), 0.0F, 1.0F, 0.0F);
}
}
@@ -275,31 +284,8 @@ public class ForgeHooksClient
{
MinecraftForge.EVENT_BUS.post(new TextureStitchEvent.Post(map));
FluidRegistry.WATER.setIcons(BlockLiquid.getLiquidIcon("water_still"), BlockLiquid.getLiquidIcon("water_flow"));
FluidRegistry.LAVA.setIcons(BlockLiquid.getLiquidIcon("lava_still"), BlockLiquid.getLiquidIcon("lava_flow"));
}
/**
* This is added for Optifine's convenience. And to explode if a ModMaker is developing.
* @param texture
*/
public static void onTextureLoadPre(String texture)
{
if (Tessellator.renderingWorldRenderer)
{
FMLLog.warning("Warning: Texture %s not preloaded, will cause render glitches!", texture);
if (Tessellator.class.getPackage() != null)
{
if (Tessellator.class.getPackage().getName().startsWith("net.minecraft."))
{
Minecraft mc = FMLClientHandler.instance().getClient();
if (mc.ingameGUI != null)
{
mc.ingameGUI.getChatGUI().printChatMessage(new ChatComponentTranslation("forge.texture.preload.warning", texture));
}
}
}
}
FluidRegistry.WATER.setIcons(map.getAtlasSprite("minecraft:blocks/water_still"), map.getAtlasSprite("minecraft:blocks/water_flow"));
FluidRegistry.LAVA.setIcons(map.getAtlasSprite("minecraft:blocks/lava_still"), map.getAtlasSprite("minecraft:blocks/lava_flow"));
}
static int renderPass = -1;
@@ -308,37 +294,16 @@ public class ForgeHooksClient
renderPass = pass;
}
public static ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, int slotID, ModelBiped _default)
static EnumWorldBlockLayer renderLayer = EnumWorldBlockLayer.SOLID;
public static void setRenderLayer(EnumWorldBlockLayer layer)
{
ModelBiped modelbiped = itemStack.getItem().getArmorModel(entityLiving, itemStack, slotID);
return modelbiped == null ? _default : modelbiped;
renderLayer = layer;
}
static int stencilBits = 0;
public static void createDisplay() throws LWJGLException
public static ModelBase getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, int slotID, ModelBase _default)
{
ImageIO.setUseCache(false); //Disable on-disc stream cache should speed up texture pack reloading.
PixelFormat format = new PixelFormat().withDepthBits(24);
if (!Boolean.parseBoolean(System.getProperty("forge.forceDisplayStencil", "false")))
{
//Creating the display with Stencil bits causes issues on some displays.
//According to ChickenBones, Mumfrey and Pig The only real use is in the FBO.
//So lets default to normal init to fix the issues yet add the bits to the FBO.
Display.create(format);
stencilBits = 0;
return;
}
try
{
//TODO: Figure out how to determine the max bits.
Display.create(format.withStencilBits(8));
stencilBits = 8;
}
catch(LWJGLException e)
{
Display.create(format);
stencilBits = 0;
}
ModelBase modelbase = itemStack.getItem().getArmorModel(entityLiving, itemStack, slotID);
return modelbase == null ? _default : modelbase;
}
//This properly moves the domain, if provided, to the front of the string before concatenating
@@ -367,7 +332,7 @@ public class ForgeHooksClient
return MinecraftForge.EVENT_BUS.post(new MouseEvent());
}
public static float getOffsetFOV(EntityPlayerSP entity, float fov)
public static float getOffsetFOV(EntityPlayer entity, float fov)
{
FOVUpdateEvent fovUpdateEvent = new FOVUpdateEvent(entity, fov);
MinecraftForge.EVENT_BUS.post(fovUpdateEvent);
@@ -379,9 +344,9 @@ public class ForgeHooksClient
private static boolean skyInit;
private static int skyRGBMultiplier;
public static int getSkyBlendColour(World world, int playerX, int playerY, int playerZ)
public static int getSkyBlendColour(World world, BlockPos center)
{
if (playerX == skyX && playerZ == skyZ && skyInit)
if (center.getX() == skyX && center.getZ() == skyZ && skyInit)
{
return skyRGBMultiplier;
}
@@ -404,8 +369,9 @@ public class ForgeHooksClient
{
for (int z = -distance; z <= distance; ++z)
{
BiomeGenBase biome = world.getBiomeGenForCoords(playerX + x, playerZ + z);
int colour = biome.getSkyColorByTemp(biome.getFloatTemperature(playerX + x, playerY, playerZ + z));
BlockPos pos = center.add(x, 0, z);
BiomeGenBase biome = world.getBiomeGenForCoords(pos);
int colour = biome.getSkyColorByTemp(biome.getFloatTemperature(pos));
r += (colour & 0xFF0000) >> 16;
g += (colour & 0x00FF00) >> 8;
b += colour & 0x0000FF;
@@ -415,8 +381,8 @@ public class ForgeHooksClient
int multiplier = (r / divider & 255) << 16 | (g / divider & 255) << 8 | b / divider & 255;
skyX = playerX;
skyZ = playerZ;
skyX = center.getX();
skyZ = center.getY();
skyRGBMultiplier = multiplier;
return skyRGBMultiplier;
}
@@ -425,8 +391,8 @@ public class ForgeHooksClient
*/
static
{
FluidRegistry.renderIdFluid = RenderingRegistry.getNextAvailableRenderId();
RenderingRegistry.registerBlockHandler(RenderBlockFluid.instance);
//FluidRegistry.renderIdFluid = RenderingRegistry.getNextAvailableRenderId();
//RenderingRegistry.registerBlockHandler(RenderBlockFluid.instance);
}
public static void renderMainMenu(GuiMainMenu gui, FontRenderer font, int width, int height)
@@ -461,13 +427,13 @@ public class ForgeHooksClient
public static ISound playSound(SoundManager manager, ISound sound)
{
SoundEventAccessorComposite accessor = manager.sndHandler.getSound(sound.getPositionedSoundLocation());
PlaySoundEvent17 e = new PlaySoundEvent17(manager, sound, (accessor == null ? null : accessor.getSoundCategory()));
SoundEventAccessorComposite accessor = manager.sndHandler.getSound(sound.getSoundLocation());
PlaySoundEvent e = new PlaySoundEvent(manager, sound, (accessor == null ? null : accessor.getSoundCategory()));
MinecraftForge.EVENT_BUS.post(e);
return e.result;
}
static RenderBlocks worldRendererRB;
//static RenderBlocks worldRendererRB;
static int worldRenderPass;
public static int getWorldRenderPass()
@@ -475,6 +441,26 @@ public class ForgeHooksClient
return worldRenderPass;
}
public static void drawScreen(GuiScreen screen, int mouseX, int mouseY, float partialTicks)
{
if (!MinecraftForge.EVENT_BUS.post(new GuiScreenEvent.DrawScreenEvent.Pre(screen, mouseX, mouseY, partialTicks)))
screen.drawScreen(mouseX, mouseY, partialTicks);
MinecraftForge.EVENT_BUS.post(new GuiScreenEvent.DrawScreenEvent.Post(screen, mouseX, mouseY, partialTicks));
}
public static float getFogDensity(EntityRenderer renderer, Entity entity, Block block, float partial, float density)
{
EntityViewRenderEvent.FogDensity event = new EntityViewRenderEvent.FogDensity(renderer, entity, block, partial, density);
if (MinecraftForge.EVENT_BUS.post(event)) return event.density;
return -1;
}
public static void onFogRender(EntityRenderer renderer, Entity entity, Block block, float partial, int mode, float distance)
{
MinecraftForge.EVENT_BUS.post(new EntityViewRenderEvent.RenderFogEvent(renderer, entity, block, partial, mode, distance));
}
/*
public static void setWorldRendererRB(RenderBlocks renderBlocks)
{
worldRendererRB = renderBlocks;
@@ -497,4 +483,144 @@ public class ForgeHooksClient
worldRenderPass = -1;
}
}
*/
public static void onModelBake(ModelManager modelManager, IRegistry modelRegistry, ModelBakery modelBakery)
{
MinecraftForge.EVENT_BUS.post(new ModelBakeEvent(modelManager, modelRegistry, modelBakery));
}
public static Matrix4f getMatrix(ItemTransformVec3f transform)
{
javax.vecmath.Matrix4f m = new javax.vecmath.Matrix4f(), t = new javax.vecmath.Matrix4f();
m.setIdentity();
m.setTranslation(transform.translation);
t.setIdentity();
t.rotY(transform.rotation.y);
m.mul(t);
t.setIdentity();
t.rotX(transform.rotation.x);
m.mul(t);
t.setIdentity();
t.rotZ(transform.rotation.z);
m.mul(t);
t.setIdentity();
t.m00 = transform.scale.x;
t.m11 = transform.scale.y;
t.m22 = transform.scale.z;
m.mul(t);
return m;
}
public static IBakedModel handleCameraTransforms(IBakedModel model, ItemCameraTransforms.TransformType cameraTransformType)
{
if(model instanceof IPerspectiveAwareModel)
{
Pair<IBakedModel, Matrix4f> pair = ((IPerspectiveAwareModel)model).handlePerspective(cameraTransformType);
if(pair.getRight() != null) multiplyCurrentGlMatrix(pair.getRight());
return pair.getLeft();
}
switch(cameraTransformType)
{
case FIRST_PERSON:
RenderItem.applyVanillaTransform(model.getItemCameraTransforms().firstPerson);
break;
case GUI:
RenderItem.applyVanillaTransform(model.getItemCameraTransforms().gui);
break;
case HEAD:
RenderItem.applyVanillaTransform(model.getItemCameraTransforms().head);
break;
case THIRD_PERSON:
RenderItem.applyVanillaTransform(model.getItemCameraTransforms().thirdPerson);
break;
default:
break;
}
return model;
}
private static final FloatBuffer matrixBuf = BufferUtils.createFloatBuffer(16);
public static void multiplyCurrentGlMatrix(Matrix4f matrix)
{
matrixBuf.clear();
float[] t = new float[4];
for(int i = 0; i < 4; i++)
{
matrix.getColumn(i, t);
matrixBuf.put(t);
}
matrixBuf.flip();
GL11.glMultMatrix(matrixBuf);
}
// moved and expanded from WorldVertexBufferUploader.draw
public static void preDraw(EnumUsage attrType, VertexFormatElement attr, int stride, ByteBuffer buffer)
{
buffer.position(attr.getOffset());
switch(attrType)
{
case POSITION:
glVertexPointer(attr.getElementCount(), attr.getType().getGlConstant(), stride, buffer);
glEnableClientState(GL_VERTEX_ARRAY);
break;
case NORMAL:
if(attr.getElementCount() != 3)
{
throw new IllegalArgumentException("Normal attribute should have the size 3: " + attr);
}
glNormalPointer(attr.getType().getGlConstant(), stride, buffer);
glEnableClientState(GL_NORMAL_ARRAY);
break;
case COLOR:
glColorPointer(attr.getElementCount(), attr.getType().getGlConstant(), stride, buffer);
glEnableClientState(GL_COLOR_ARRAY);
break;
case UV:
OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit + attr.getIndex());
glTexCoordPointer(attr.getElementCount(), attr.getType().getGlConstant(), stride, buffer);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit);
break;
case PADDING:
break;
case GENERIC:
glEnableVertexAttribArray(attr.getIndex());
glVertexAttribPointer(attr.getIndex(), attr.getElementCount(), attr.getType().getGlConstant(), false, stride, buffer);
default:
FMLLog.severe("Unimplemented vanilla attribute upload: %s", attrType.getDisplayName());
}
}
public static void postDraw(EnumUsage attrType, VertexFormatElement attr, int stride, ByteBuffer buffer)
{
switch(attrType)
{
case POSITION:
glDisableClientState(GL_VERTEX_ARRAY);
break;
case NORMAL:
glDisableClientState(GL_NORMAL_ARRAY);
break;
case COLOR:
glDisableClientState(GL_COLOR_ARRAY);
// is this really needed?
GlStateManager.resetColor();
break;
case UV:
OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit + attr.getIndex());
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
OpenGlHelper.setClientActiveTexture(OpenGlHelper.defaultTexUnit);
break;
case PADDING:
break;
case GENERIC:
glDisableVertexAttribArray(attr.getIndex());
default:
FMLLog.severe("Unimplemented vanilla attribute upload: %s", attrType.getDisplayName());
}
}
}
@@ -11,9 +11,10 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiIngame;
import net.minecraft.client.gui.GuiPlayerInfo;
import net.minecraft.client.gui.GuiOverlayDebug;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.resources.I18n;
@@ -21,6 +22,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
@@ -29,7 +31,7 @@ import net.minecraft.potion.Potion;
import net.minecraft.scoreboard.Score;
import net.minecraft.scoreboard.ScoreObjective;
import net.minecraft.scoreboard.ScorePlayerTeam;
import net.minecraft.util.Direction;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.FoodStats;
import net.minecraft.util.MathHelper;
@@ -45,7 +47,9 @@ import net.minecraftforge.common.MinecraftForge;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import cpw.mods.fml.common.FMLCommonHandler;
import com.google.common.base.Strings;
import net.minecraftforge.fml.common.FMLCommonHandler;
public class GuiIngameForge extends GuiIngame
{
@@ -79,17 +83,19 @@ public class GuiIngameForge extends GuiIngame
private FontRenderer fontrenderer = null;
private RenderGameOverlayEvent eventParent;
private static final String MC_VERSION = MinecraftForge.MC_VERSION;
private GuiOverlayDebugForge debugOverlay;
public GuiIngameForge(Minecraft mc)
{
super(mc);
debugOverlay = new GuiOverlayDebugForge(mc);
}
@Override
public void renderGameOverlay(float partialTicks, boolean hasScreen, int mouseX, int mouseY)
public void renderGameOverlay(float partialTicks)
{
res = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
eventParent = new RenderGameOverlayEvent(partialTicks, res, mouseX, mouseY);
eventParent = new RenderGameOverlayEvent(partialTicks, res);
int width = res.getScaledWidth();
int height = res.getScaledHeight();
renderHealthMount = mc.thePlayer.ridingEntity instanceof EntityLivingBase;
@@ -101,45 +107,44 @@ public class GuiIngameForge extends GuiIngame
if (pre(ALL)) return;
fontrenderer = mc.fontRenderer;
fontrenderer = mc.fontRendererObj;
mc.entityRenderer.setupOverlayRendering();
GL11.glEnable(GL11.GL_BLEND);
GlStateManager.enableBlend();
if (Minecraft.isFancyGraphicsEnabled())
{
renderVignette(mc.thePlayer.getBrightness(partialTicks), width, height);
func_180480_a(mc.thePlayer.getBrightness(partialTicks), res);
}
else
{
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
}
if (renderHelmet) renderHelmet(res, partialTicks, hasScreen, mouseX, mouseY);
if (renderHelmet) renderHelmet(res, partialTicks);
if (renderPortal && !mc.thePlayer.isPotionActive(Potion.confusion))
{
renderPortal(width, height, partialTicks);
renderPortal(res, partialTicks);
}
if (!mc.playerController.enableEverythingIsScrewedUpMode())
if (renderHotbar) renderTooltip(res, partialTicks);
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
zLevel = -90.0F;
rand.setSeed((long)(updateCounter * 312871));
if (renderCrosshairs) renderCrosshairs(width, height);
if (renderBossHealth) renderBossHealth();
if (this.mc.playerController.shouldDrawHUD() && this.mc.getRenderViewEntity() instanceof EntityPlayer)
{
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
zLevel = -90.0F;
rand.setSeed((long)(updateCounter * 312871));
if (renderCrosshairs) renderCrosshairs(width, height);
if (renderBossHealth) renderBossHealth();
if (this.mc.playerController.shouldDrawHUD())
{
if (renderHealth) renderHealth(width, height);
if (renderArmor) renderArmor(width, height);
if (renderFood) renderFood(width, height);
if (renderHealthMount) renderHealthMount(width, height);
if (renderAir) renderAir(width, height);
}
if (renderHotbar) renderHotbar(width, height, partialTicks);
if (renderHealth) renderHealth(width, height);
if (renderArmor) renderArmor(width, height);
if (renderFood) renderFood(width, height);
if (renderHealthMount) renderHealthMount(width, height);
if (renderAir) renderAir(width, height);
}
renderSleepFade(width, height);
if (renderJumpBar)
{
@@ -150,28 +155,37 @@ public class GuiIngameForge extends GuiIngame
renderExperience(width, height);
}
renderSleepFade(width, height);
renderToolHightlight(width, height);
renderToolHightlight(res);
renderHUDText(width, height);
renderRecordOverlay(width, height, partialTicks);
renderTitle(width, height, partialTicks);
ScoreObjective objective = mc.theWorld.getScoreboard().func_96539_a(1);
if (renderObjective && objective != null)
Scoreboard scoreboard = this.mc.theWorld.getScoreboard();
ScoreObjective objective = null;
ScorePlayerTeam scoreplayerteam = scoreboard.getPlayersTeam(mc.thePlayer.getName());
if (scoreplayerteam != null)
{
this.func_96136_a(objective, height, width, fontrenderer);
int slot = scoreplayerteam.func_178775_l().getColorIndex();
if (slot >= 0) objective = scoreboard.getObjectiveInDisplaySlot(3 + slot);
}
ScoreObjective scoreobjective1 = objective != null ? objective : scoreboard.getObjectiveInDisplaySlot(1);
if (renderObjective && scoreobjective1 != null)
{
this.func_180475_a(scoreobjective1, res);
}
GL11.glEnable(GL11.GL_BLEND);
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GL11.glDisable(GL11.GL_ALPHA_TEST);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GlStateManager.disableAlpha();
renderChat(width, height);
renderPlayerList(width, height);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_ALPHA_TEST);
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableLighting();
GlStateManager.enableAlpha();
post(ALL);
}
@@ -181,46 +195,19 @@ public class GuiIngameForge extends GuiIngame
return res;
}
protected void renderHotbar(int width, int height, float partialTicks)
{
if (pre(HOTBAR)) return;
mc.mcProfiler.startSection("actionBar");
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
mc.renderEngine.bindTexture(WIDGITS);
InventoryPlayer inv = mc.thePlayer.inventory;
drawTexturedModalRect(width / 2 - 91, height - 22, 0, 0, 182, 22);
drawTexturedModalRect(width / 2 - 91 - 1 + inv.currentItem * 20, height - 22 - 1, 0, 22, 24, 22);
GL11.glDisable(GL11.GL_BLEND);
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
RenderHelper.enableGUIStandardItemLighting();
for (int i = 0; i < 9; ++i)
{
int x = width / 2 - 90 + i * 20 + 2;
int z = height - 16 - 3;
renderInventorySlot(i, x, z, partialTicks);
}
RenderHelper.disableStandardItemLighting();
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
mc.mcProfiler.endSection();
post(HOTBAR);
}
protected void renderCrosshairs(int width, int height)
{
if (pre(CROSSHAIRS)) return;
bind(Gui.icons);
GL11.glEnable(GL11.GL_BLEND);
OpenGlHelper.glBlendFunc(GL11.GL_ONE_MINUS_DST_COLOR, GL11.GL_ONE_MINUS_SRC_COLOR, 1, 0);
drawTexturedModalRect(width / 2 - 7, height / 2 - 7, 0, 0, 16, 16);
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GL11.glDisable(GL11.GL_BLEND);
if (this.showCrosshair())
{
bind(Gui.icons);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GL11.GL_ONE_MINUS_DST_COLOR, GL11.GL_ONE_MINUS_SRC_COLOR, 1, 0);
GlStateManager.enableAlpha();
drawTexturedModalRect(width / 2 - 7, height / 2 - 7, 0, 0, 16, 16);
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GL11.glDisable(GL11.GL_BLEND);
}
post(CROSSHAIRS);
}
@@ -228,15 +215,16 @@ public class GuiIngameForge extends GuiIngame
protected void renderBossHealth()
{
if (pre(BOSSHEALTH)) return;
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
mc.mcProfiler.startSection("bossHealth");
GL11.glEnable(GL11.GL_BLEND);
GlStateManager.enableBlend();
super.renderBossHealth();
GL11.glDisable(GL11.GL_BLEND);
GlStateManager.disableBlend();
mc.mcProfiler.endSection();
post(BOSSHEALTH);
}
private void renderHelmet(ScaledResolution res, float partialTicks, boolean hasScreen, int mouseX, int mouseY)
private void renderHelmet(ScaledResolution res, float partialTicks)
{
if (pre(HELMET)) return;
@@ -246,11 +234,11 @@ public class GuiIngameForge extends GuiIngame
{
if (itemstack.getItem() == Item.getItemFromBlock(Blocks.pumpkin))
{
renderPumpkinBlur(res.getScaledWidth(), res.getScaledHeight());
func_180476_e(res);
}
else
{
itemstack.getItem().renderHelmetOverlay(itemstack, mc.thePlayer, res, partialTicks, hasScreen, mouseX, mouseY);
itemstack.getItem().renderHelmetOverlay(itemstack, mc.thePlayer, res, partialTicks);
}
}
@@ -262,7 +250,7 @@ public class GuiIngameForge extends GuiIngame
if (pre(ARMOR)) return;
mc.mcProfiler.startSection("armor");
GL11.glEnable(GL11.GL_BLEND);
GlStateManager.enableBlend();
int left = width / 2 - 91;
int top = height - left_height;
@@ -285,12 +273,12 @@ public class GuiIngameForge extends GuiIngame
}
left_height += 10;
GL11.glDisable(GL11.GL_BLEND);
GlStateManager.disableBlend();
mc.mcProfiler.endSection();
post(ARMOR);
}
protected void renderPortal(int width, int height, float partialTicks)
protected void renderPortal(ScaledResolution res, float partialTicks)
{
if (pre(PORTAL)) return;
@@ -298,23 +286,41 @@ public class GuiIngameForge extends GuiIngame
if (f1 > 0.0F)
{
func_130015_b(f1, width, height);
func_180474_b(f1, res);
}
post(PORTAL);
}
@Override
protected void renderTooltip(ScaledResolution res, float partialTicks)
{
if (pre(HOTBAR)) return;
if (mc.playerController.isSpectator())
{
this.spectatorGui.renderTooltip(res, partialTicks);
}
else
{
super.renderTooltip(res, partialTicks);
}
post(HOTBAR);
}
protected void renderAir(int width, int height)
{
if (pre(AIR)) return;
mc.mcProfiler.startSection("air");
GL11.glEnable(GL11.GL_BLEND);
EntityPlayer player = (EntityPlayer)this.mc.getRenderViewEntity();
GlStateManager.enableBlend();
int left = width / 2 + 91;
int top = height - right_height;
if (mc.thePlayer.isInsideOfMaterial(Material.water))
if (player.isInsideOfMaterial(Material.water))
{
int air = mc.thePlayer.getAir();
int air = player.getAir();
int full = MathHelper.ceiling_double_int((double)(air - 2) * 10.0D / 300.0D);
int partial = MathHelper.ceiling_double_int((double)air * 10.0D / 300.0D) - full;
@@ -325,7 +331,7 @@ public class GuiIngameForge extends GuiIngame
right_height += 10;
}
GL11.glDisable(GL11.GL_BLEND);
GlStateManager.disableBlend();
mc.mcProfiler.endSection();
post(AIR);
}
@@ -335,20 +341,36 @@ public class GuiIngameForge extends GuiIngame
bind(icons);
if (pre(HEALTH)) return;
mc.mcProfiler.startSection("health");
GL11.glEnable(GL11.GL_BLEND);
GlStateManager.enableBlend();
boolean highlight = mc.thePlayer.hurtResistantTime / 3 % 2 == 1;
EntityPlayer player = (EntityPlayer)this.mc.getRenderViewEntity();
int health = MathHelper.ceiling_float_int(player.getHealth());
boolean highlight = field_175191_F > (long)updateCounter && (field_175191_F - (long)updateCounter) / 3L %2L == 1L;
if (mc.thePlayer.hurtResistantTime < 10)
if (health < this.field_175194_C && player.hurtResistantTime > 0)
{
highlight = false;
this.lastSystemTime = Minecraft.getSystemTime();
this.field_175191_F = (long)(this.updateCounter + 20);
}
else if (health > this.field_175194_C && player.hurtResistantTime > 0)
{
this.lastSystemTime = Minecraft.getSystemTime();
this.field_175191_F = (long)(this.updateCounter + 10);
}
IAttributeInstance attrMaxHealth = this.mc.thePlayer.getEntityAttribute(SharedMonsterAttributes.maxHealth);
int health = MathHelper.ceiling_float_int(mc.thePlayer.getHealth());
int healthLast = MathHelper.ceiling_float_int(mc.thePlayer.prevHealth);
if (Minecraft.getSystemTime() - this.lastSystemTime > 1000L)
{
this.field_175194_C = health;
this.field_175189_D = health;
this.lastSystemTime = Minecraft.getSystemTime();
}
this.field_175194_C = health;
int healthLast = this.field_175189_D;
IAttributeInstance attrMaxHealth = player.getEntityAttribute(SharedMonsterAttributes.maxHealth);
float healthMax = (float)attrMaxHealth.getAttributeValue();
float absorb = this.mc.thePlayer.getAbsorptionAmount();
float absorb = player.getAbsorptionAmount();
int healthRows = MathHelper.ceiling_float_int((healthMax + absorb) / 2.0F / 10.0F);
int rowHeight = Math.max(10 - (healthRows - 2), 3);
@@ -361,7 +383,7 @@ public class GuiIngameForge extends GuiIngame
if (rowHeight != 10) left_height += 10 - rowHeight;
int regen = -1;
if (mc.thePlayer.isPotionActive(Potion.regeneration))
if (player.isPotionActive(Potion.regeneration))
{
regen = updateCounter % 25;
}
@@ -369,8 +391,8 @@ public class GuiIngameForge extends GuiIngame
final int TOP = 9 * (mc.theWorld.getWorldInfo().isHardcoreModeEnabled() ? 5 : 0);
final int BACKGROUND = (highlight ? 25 : 16);
int MARGIN = 16;
if (mc.thePlayer.isPotionActive(Potion.poison)) MARGIN += 36;
else if (mc.thePlayer.isPotionActive(Potion.wither)) MARGIN += 72;
if (player.isPotionActive(Potion.poison)) MARGIN += 36;
else if (player.isPotionActive(Potion.wither)) MARGIN += 72;
float absorbRemaining = absorb;
for (int i = MathHelper.ceiling_float_int((healthMax + absorb) / 2.0F) - 1; i >= 0; --i)
@@ -410,7 +432,7 @@ public class GuiIngameForge extends GuiIngame
}
}
GL11.glDisable(GL11.GL_BLEND);
GlStateManager.disableBlend();
mc.mcProfiler.endSection();
post(HEALTH);
}
@@ -420,7 +442,8 @@ public class GuiIngameForge extends GuiIngame
if (pre(FOOD)) return;
mc.mcProfiler.startSection("food");
GL11.glEnable(GL11.GL_BLEND);
EntityPlayer player = (EntityPlayer)this.mc.getRenderViewEntity();
GlStateManager.enableBlend();
int left = width / 2 + 91;
int top = height - right_height;
right_height += 10;
@@ -445,7 +468,7 @@ public class GuiIngameForge extends GuiIngame
}
if (unused) backgound = 1; //Probably should be a += 1 but vanilla never uses this
if (mc.thePlayer.getFoodStats().getSaturationLevel() <= 0.0F && updateCounter % (level * 3 + 1) == 0)
if (player.getFoodStats().getSaturationLevel() <= 0.0F && updateCounter % (level * 3 + 1) == 0)
{
y = top + (rand.nextInt(3) - 1);
}
@@ -465,7 +488,7 @@ public class GuiIngameForge extends GuiIngame
else if (idx == level)
drawTexturedModalRect(x, y, icon + 45, 27, 9, 9);
}
GL11.glDisable(GL11.GL_BLEND);
GlStateManager.disableBlend();
mc.mcProfiler.endSection();
post(FOOD);
}
@@ -475,8 +498,8 @@ public class GuiIngameForge extends GuiIngame
if (mc.thePlayer.getSleepTimer() > 0)
{
mc.mcProfiler.startSection("sleep");
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glDisable(GL11.GL_ALPHA_TEST);
GlStateManager.disableDepth();
GlStateManager.disableAlpha();
int sleepTime = mc.thePlayer.getSleepTimer();
float opacity = (float)sleepTime / 100.0F;
@@ -487,8 +510,8 @@ public class GuiIngameForge extends GuiIngame
int color = (int)(220.0F * opacity) << 24 | 1052704;
drawRect(0, 0, width, height, color);
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.enableAlpha();
GlStateManager.enableDepth();
mc.mcProfiler.endSection();
}
}
@@ -497,8 +520,8 @@ public class GuiIngameForge extends GuiIngame
{
bind(icons);
if (pre(EXPERIENCE)) return;
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glDisable(GL11.GL_BLEND);
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableBlend();
if (mc.playerController.gameIsSurvivalOrAdventure())
{
@@ -538,8 +561,8 @@ public class GuiIngameForge extends GuiIngame
mc.mcProfiler.endSection();
}
}
GL11.glEnable(GL11.GL_BLEND);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.enableBlend();
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
post(EXPERIENCE);
}
@@ -549,7 +572,7 @@ public class GuiIngameForge extends GuiIngame
bind(icons);
if (pre(JUMPBAR)) return;
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glDisable(GL11.GL_BLEND);
GlStateManager.disableBlend();
mc.mcProfiler.startSection("jumpBar");
float charge = mc.thePlayer.getHorseJumpPower();
@@ -565,152 +588,108 @@ public class GuiIngameForge extends GuiIngame
this.drawTexturedModalRect(x, top, 0, 89, filled, 5);
}
GL11.glEnable(GL11.GL_BLEND);
GlStateManager.enableBlend();
mc.mcProfiler.endSection();
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
post(JUMPBAR);
}
protected void renderToolHightlight(int width, int height)
protected void renderToolHightlight(ScaledResolution res)
{
if (this.mc.gameSettings.heldItemTooltips)
if (this.mc.gameSettings.heldItemTooltips && !this.mc.playerController.isSpectator())
{
mc.mcProfiler.startSection("toolHighlight");
if (this.remainingHighlightTicks > 0 && this.highlightingItemStack != null)
{
String name = this.highlightingItemStack.getDisplayName();
if (this.highlightingItemStack.hasDisplayName())
name = EnumChatFormatting.ITALIC + name;
int opacity = (int)((float)this.remainingHighlightTicks * 256.0F / 10.0F);
if (opacity > 255) opacity = 255;
if (opacity > 0)
{
int y = height - 59;
int y = res.getScaledHeight() - 59;
if (!mc.playerController.shouldDrawHUD()) y += 14;
GL11.glPushMatrix();
GL11.glEnable(GL11.GL_BLEND);
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GlStateManager.pushMatrix();
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
FontRenderer font = highlightingItemStack.getItem().getFontRenderer(highlightingItemStack);
if (font != null)
{
int x = (width - font.getStringWidth(name)) / 2;
int x = (res.getScaledWidth() - font.getStringWidth(name)) / 2;
font.drawStringWithShadow(name, x, y, WHITE | (opacity << 24));
}
else
{
int x = (width - fontrenderer.getStringWidth(name)) / 2;
int x = (res.getScaledWidth() - fontrenderer.getStringWidth(name)) / 2;
fontrenderer.drawStringWithShadow(name, x, y, WHITE | (opacity << 24));
}
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
GlStateManager.disableBlend();
GlStateManager.popMatrix();
}
}
mc.mcProfiler.endSection();
}
else if (this.mc.thePlayer.isSpectator())
{
this.spectatorGui.func_175263_a(res);
}
}
protected void renderHUDText(int width, int height)
{
mc.mcProfiler.startSection("forgeHudText");
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
ArrayList<String> left = new ArrayList<String>();
ArrayList<String> right = new ArrayList<String>();
ArrayList<String> listL = new ArrayList<String>();
ArrayList<String> listR = new ArrayList<String>();
if (mc.isDemo())
{
long time = mc.theWorld.getTotalWorldTime();
if (time >= 120500L)
{
right.add(I18n.format("demo.demoExpired"));
listR.add(I18n.format("demo.demoExpired"));
}
else
{
right.add(I18n.format("demo.remainingTime", StringUtils.ticksToElapsedTime((int)(120500L - time))));
listR.add(I18n.format("demo.remainingTime", StringUtils.ticksToElapsedTime((int)(120500L - time))));
}
}
if (this.mc.gameSettings.showDebugInfo && !pre(DEBUG))
{
mc.mcProfiler.startSection("debug");
GL11.glPushMatrix();
left.add("Minecraft " + MC_VERSION + " (" + this.mc.debug + ")");
left.add(mc.debugInfoRenders());
left.add(mc.getEntityDebug());
left.add(mc.debugInfoEntities());
left.add(mc.getWorldProviderName());
left.add(null); //Spacer
long max = Runtime.getRuntime().maxMemory();
long total = Runtime.getRuntime().totalMemory();
long free = Runtime.getRuntime().freeMemory();
long used = total - free;
right.add("Used memory: " + used * 100L / max + "% (" + used / 1024L / 1024L + "MB) of " + max / 1024L / 1024L + "MB");
right.add("Allocated memory: " + total * 100L / max + "% (" + total / 1024L / 1024L + "MB)");
int x = MathHelper.floor_double(mc.thePlayer.posX);
int y = MathHelper.floor_double(mc.thePlayer.posY);
int z = MathHelper.floor_double(mc.thePlayer.posZ);
float yaw = mc.thePlayer.rotationYaw;
int heading = MathHelper.floor_double((double)(mc.thePlayer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
left.add(String.format("x: %.5f (%d) // c: %d (%d)", mc.thePlayer.posX, x, x >> 4, x & 15));
left.add(String.format("y: %.3f (feet pos, %.3f eyes pos)", mc.thePlayer.boundingBox.minY, mc.thePlayer.posY));
left.add(String.format("z: %.5f (%d) // c: %d (%d)", mc.thePlayer.posZ, z, z >> 4, z & 15));
left.add(String.format("f: %d (%s) / %f", heading, Direction.directions[heading], MathHelper.wrapAngleTo180_float(yaw)));
if (mc.theWorld != null && mc.theWorld.blockExists(x, y, z))
{
Chunk chunk = this.mc.theWorld.getChunkFromBlockCoords(x, z);
left.add(String.format("lc: %d b: %s bl: %d sl: %d rl: %d",
chunk.getTopFilledSegment() + 15,
chunk.getBiomeGenForWorldCoords(x & 15, z & 15, mc.theWorld.getWorldChunkManager()).biomeName,
chunk.getSavedLightValue(EnumSkyBlock.Block, x & 15, y, z & 15),
chunk.getSavedLightValue(EnumSkyBlock.Sky, x & 15, y, z & 15),
chunk.getBlockLightValue(x & 15, y, z & 15, 0)));
}
else
{
left.add(null);
}
left.add(String.format("ws: %.3f, fs: %.3f, g: %b, fl: %d", mc.thePlayer.capabilities.getWalkSpeed(), mc.thePlayer.capabilities.getFlySpeed(), mc.thePlayer.onGround, mc.theWorld.getHeightValue(x, z)));
if (mc.entityRenderer != null && mc.entityRenderer.isShaderActive())
{
left.add(String.format("shader: %s", mc.entityRenderer.getShaderGroup().getShaderGroupName()));
}
right.add(null);
for (String brand : FMLCommonHandler.instance().getBrandings(false))
{
right.add(brand);
}
GL11.glPopMatrix();
mc.mcProfiler.endSection();
listL.addAll(debugOverlay.getLeft());
listR.addAll(debugOverlay.getRight());
post(DEBUG);
}
RenderGameOverlayEvent.Text event = new RenderGameOverlayEvent.Text(eventParent, left, right);
RenderGameOverlayEvent.Text event = new RenderGameOverlayEvent.Text(eventParent, listL, listR);
if (!MinecraftForge.EVENT_BUS.post(event))
{
for (int x = 0; x < left.size(); x++)
int top = 2;
for (String msg : listL)
{
String msg = left.get(x);
if (msg == null) continue;
fontrenderer.drawStringWithShadow(msg, 2, 2 + x * 10, WHITE);
drawRect(1, top - 1, 2 + fontrenderer.getStringWidth(msg) + 1, top + fontrenderer.FONT_HEIGHT - 1, -1873784752);
fontrenderer.drawString(msg, 2, top, 14737632);
top += fontrenderer.FONT_HEIGHT;
}
for (int x = 0; x < right.size(); x++)
top = 2;
for (String msg : listR)
{
String msg = right.get(x);
if (msg == null) continue;
int w = fontrenderer.getStringWidth(msg);
fontrenderer.drawStringWithShadow(msg, width - w - 10, 2 + x * 10, WHITE);
int left = width - 2 - w;
drawRect(left - 1, top - 1, left + w + 1, top + fontrenderer.FONT_HEIGHT - 1, -1873784752);
fontrenderer.drawString(msg, left, top, 14737632);
top += fontrenderer.FONT_HEIGHT;
}
}
@@ -729,20 +708,60 @@ public class GuiIngameForge extends GuiIngame
if (opacity > 0)
{
GL11.glPushMatrix();
GL11.glTranslatef((float)(width / 2), (float)(height - 48), 0.0F);
GL11.glEnable(GL11.GL_BLEND);
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GlStateManager.pushMatrix();
GlStateManager.translate((float)(width / 2), (float)(height - 48), 0.0F);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
int color = (recordIsPlaying ? Color.HSBtoRGB(hue / 50.0F, 0.7F, 0.6F) & WHITE : WHITE);
fontrenderer.drawString(recordPlaying, -fontrenderer.getStringWidth(recordPlaying) / 2, -4, color | (opacity << 24));
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
GlStateManager.disableBlend();
GlStateManager.popMatrix();
}
mc.mcProfiler.endSection();
}
}
protected void renderTitle(int width, int height, float partialTicks)
{
if (field_175195_w > 0)
{
mc.mcProfiler.startSection("titleAndSubtitle");
float age = (float)this.field_175195_w - partialTicks;
int opacity = 255;
if (field_175195_w > field_175193_B + field_175192_A)
{
float f3 = (float)(field_175199_z + field_175192_A + field_175193_B) - age;
opacity = (int)(f3 * 255.0F / (float)field_175199_z);
}
if (field_175195_w <= field_175193_B) opacity = (int)(age * 255.0F / (float)this.field_175193_B);
opacity = MathHelper.clamp_int(opacity, 0, 255);
if (opacity > 8)
{
GlStateManager.pushMatrix();
GlStateManager.translate((float)(width / 2), (float)(height / 2), 0.0F);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
GlStateManager.pushMatrix();
GlStateManager.scale(4.0F, 4.0F, 4.0F);
int l = opacity << 24 & -16777216;
this.func_175179_f().drawString(this.field_175201_x, (float)(-this.func_175179_f().getStringWidth(this.field_175201_x) / 2), -10.0F, 16777215 | l, true);
GlStateManager.popMatrix();
GlStateManager.pushMatrix();
GlStateManager.scale(2.0F, 2.0F, 2.0F);
this.func_175179_f().drawString(this.field_175200_y, (float)(-this.func_175179_f().getStringWidth(this.field_175200_y) / 2), 5.0F, 16777215 | l, true);
GlStateManager.popMatrix();
GlStateManager.disableBlend();
GlStateManager.popMatrix();
}
this.mc.mcProfiler.endSection();
}
}
protected void renderChat(int width, int height)
{
mc.mcProfiler.startSection("chat");
@@ -750,98 +769,38 @@ public class GuiIngameForge extends GuiIngame
RenderGameOverlayEvent.Chat event = new RenderGameOverlayEvent.Chat(eventParent, 0, height - 48);
if (MinecraftForge.EVENT_BUS.post(event)) return;
GL11.glPushMatrix();
GL11.glTranslatef((float)event.posX, (float)event.posY, 0.0F);
GlStateManager.pushMatrix();
GlStateManager.translate((float)event.posX, (float)event.posY, 0.0F);
persistantChatGUI.drawChat(updateCounter);
GL11.glPopMatrix();
GlStateManager.popMatrix();
post(CHAT);
mc.mcProfiler.endSection();
}
@SuppressWarnings("unchecked")
protected void renderPlayerList(int width, int height)
{
ScoreObjective scoreobjective = this.mc.theWorld.getScoreboard().func_96539_a(0);
ScoreObjective scoreobjective = this.mc.theWorld.getScoreboard().getObjectiveInDisplaySlot(0);
NetHandlerPlayClient handler = mc.thePlayer.sendQueue;
if (mc.gameSettings.keyBindPlayerList.getIsKeyPressed() && (!mc.isIntegratedServerRunning() || handler.playerInfoList.size() > 1 || scoreobjective != null))
if (mc.gameSettings.keyBindPlayerList.isKeyDown() && (!mc.isIntegratedServerRunning() || handler.func_175106_d().size() > 1 || scoreobjective != null))
{
this.overlayPlayerList.func_175246_a(true);
if (pre(PLAYER_LIST)) return;
this.mc.mcProfiler.startSection("playerList");
List<GuiPlayerInfo> players = (List<GuiPlayerInfo>)handler.playerInfoList;
int maxPlayers = handler.currentServerMaxPlayers;
int rows = maxPlayers;
int columns = 1;
for (columns = 1; rows > 20; rows = (maxPlayers + columns - 1) / columns)
{
columns++;
}
int columnWidth = 300 / columns;
if (columnWidth > 150)
{
columnWidth = 150;
}
int left = (width - columns * columnWidth) / 2;
byte border = 10;
drawRect(left - 1, border - 1, left + columnWidth * columns, border + 9 * rows, Integer.MIN_VALUE);
for (int i = 0; i < maxPlayers; i++)
{
int xPos = left + i % columns * columnWidth;
int yPos = border + i / columns * 9;
drawRect(xPos, yPos, xPos + columnWidth - 1, yPos + 8, 553648127);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glEnable(GL11.GL_ALPHA_TEST);
if (i < players.size())
{
GuiPlayerInfo player = (GuiPlayerInfo)players.get(i);
ScorePlayerTeam team = mc.theWorld.getScoreboard().getPlayersTeam(player.name);
String displayName = ScorePlayerTeam.formatPlayerName(team, player.name);
fontrenderer.drawStringWithShadow(displayName, xPos, yPos, 16777215);
if (scoreobjective != null)
{
int endX = xPos + fontrenderer.getStringWidth(displayName) + 5;
int maxX = xPos + columnWidth - 12 - 5;
if (maxX - endX > 5)
{
Score score = scoreobjective.getScoreboard().func_96529_a(player.name, scoreobjective);
String scoreDisplay = EnumChatFormatting.YELLOW + "" + score.getScorePoints();
fontrenderer.drawStringWithShadow(scoreDisplay, maxX - fontrenderer.getStringWidth(scoreDisplay), yPos, 16777215);
}
}
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(Gui.icons);
int pingIndex = 4;
int ping = player.responseTime;
if (ping < 0) pingIndex = 5;
else if (ping < 150) pingIndex = 0;
else if (ping < 300) pingIndex = 1;
else if (ping < 600) pingIndex = 2;
else if (ping < 1000) pingIndex = 3;
zLevel += 100.0F;
drawTexturedModalRect(xPos + columnWidth - 12, yPos, 0, 176 + pingIndex * 8, 10, 8);
zLevel -= 100.0F;
}
}
this.overlayPlayerList.func_175249_a(width, this.mc.theWorld.getScoreboard(), scoreobjective);
post(PLAYER_LIST);
}
else
{
this.overlayPlayerList.func_175246_a(false);
}
}
protected void renderHealthMount(int width, int height)
{
Entity tmp = mc.thePlayer.ridingEntity;
EntityPlayer player = (EntityPlayer)mc.getRenderViewEntity();
Entity tmp = player.ridingEntity;
if (!(tmp instanceof EntityLivingBase)) return;
bind(icons);
@@ -852,7 +811,7 @@ public class GuiIngameForge extends GuiIngame
int left_align = width / 2 + 91;
mc.mcProfiler.endStartSection("mountHealth");
GL11.glEnable(GL11.GL_BLEND);
GlStateManager.enableBlend();
EntityLivingBase mount = (EntityLivingBase)tmp;
int health = (int)Math.ceil((double)mount.getHealth());
float healthMax = mount.getMaxHealth();
@@ -885,7 +844,7 @@ public class GuiIngameForge extends GuiIngame
right_height += 10;
}
GL11.glDisable(GL11.GL_BLEND);
GlStateManager.disableBlend();
post(HEALTHMOUNT);
}
@@ -902,4 +861,13 @@ public class GuiIngameForge extends GuiIngame
{
mc.getTextureManager().bindTexture(res);
}
private class GuiOverlayDebugForge extends GuiOverlayDebug
{
private GuiOverlayDebugForge(Minecraft mc){ super(mc); }
@Override protected void renderDebugInfoLeft(){}
@Override protected void renderDebugInfoRight(ScaledResolution res){}
private List<String> getLeft(){ return this.call(); }
private List<String> getRight(){ return this.getDebugInfoRight(); }
}
}
@@ -2,65 +2,68 @@ package net.minecraftforge.client;
import net.minecraft.item.ItemStack;
@Deprecated //Unused, for now. Rendering emensely changed in 1.8, Is this even needed at all anymore?
//Modders should speak up if needed.
public interface IItemRenderer
{
@Deprecated
public enum ItemRenderType
{
/**
/**
* Called to render an in-world item, e.g. one that has been thrown or
* dropped. The appropriate OpenGL transformations and scaling have already
* been applied, so Tessellator location (0,0,0) is the center of the
* EntityItem.
*
*
* Data parameters:
* RenderBlocks render - The RenderBlocks instance
* EntityItem entity - The in-world item to be rendered
*/
ENTITY,
/**
ENTITY,
/**
* Called to render an item currently held in-hand by a living entity. If
* rendering as a 3D block, the item will be rotated to a 45-degree angle.
* To render a 2D texture with some thickness (like default items), see
* net.minecraft.src.ItemRenderer. In either case, rendering should be done
* in local coordinates from (0,0,0)-(1,1,1).
*
*
* Data parameters:
* RenderBlocks render - The RenderBlocks instance
* EntityLiving entity - The entity holding this item
*/
EQUIPPED,
/**
EQUIPPED,
/**
* Called to render an item currently held in-hand by a living entity in
* first person. If rendering as a 3D block, the item will be rotated to a
* 45-degree angle. To render a 2D texture with some thickness, see
* net.minecraft.src.ItemRenderer. In either case, rendering should be done
* in local coordinates from (0,0,0)-(1,1,1).
*
*
* Data parameters:
* RenderBlocks render - The RenderBlocks instance
* EntityLiving entity - The entity holding this item
*/
EQUIPPED_FIRST_PERSON,
/**
EQUIPPED_FIRST_PERSON,
/**
* Called to render an item in a GUI inventory slot. If rendering as a 3D
* block, the appropriate OpenGL translations and scaling have already been
* applied, and the rendering should be done in local coordinates from
* (0,0,0)-(1,1,1). If rendering as a 2D texture, the rendering should be in
* GUI pixel coordinates from (0, 0, 0)-(16, 16, 0).
*
*
* Data parameters:
* RenderBlocks render - The RenderBlocks instance
*/
INVENTORY,
/**
* The render type used for when a ItemMap is rendered in first person,
* All appropriate rotations have been applied, and the player's hands,
* The render type used for when a ItemMap is rendered in first person,
* All appropriate rotations have been applied, and the player's hands,
* and the map BG are already rendered.
*
*
* Data Parameters:
* EntityPlayer player - The player holding the map
* RenderEngine engine - The RenderEngine instance
@@ -68,67 +71,71 @@ public interface IItemRenderer
*/
FIRST_PERSON_MAP
}
@Deprecated
public enum ItemRendererHelper
{
/**
/**
* Determines if a rotation effect should be used when rendering an
* EntityItem, like most default blocks do.
*/
ENTITY_ROTATION,
/**
/**
* Determines if an up-and-down bobbing effect should be used when
* rendering an EntityItem, like most default items do.
*/
ENTITY_BOBBING,
/**
/**
* Determines if the currently equipped item should be rendered as a 3D
* block or as a 2D texture.
*/
EQUIPPED_BLOCK,
/**
* Determines if the item should equate to a block that has
* Determines if the item should equate to a block that has
* RenderBlocks.renderItemIn3d return true
*/
BLOCK_3D,
/**
/**
* Determines if the item should be rendered in GUI inventory slots as a 3D
* block or as a 2D texture.
*/
INVENTORY_BLOCK
}
/**
/**
* Checks if this renderer should handle a specific item's render type
* @param item The item we are trying to render
* @param type A render type to check if this renderer handles
* @return true if this renderer should handle the given render type,
* otherwise false
*/
@Deprecated
public boolean handleRenderType(ItemStack item, ItemRenderType type);
/**
* Checks if certain helper functionality should be executed for this renderer.
* See ItemRendererHelper for more info
*
*
* @param type The render type
* @param item The ItemStack being rendered
* @param helper The type of helper functionality to be ran
* @return True to run the helper functionality, false to not.
*/
@Deprecated
public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper);
/**
* Called to do the actual rendering, see ItemRenderType for details on when specific
* Called to do the actual rendering, see ItemRenderType for details on when specific
* types are run, and what extra data is passed into the data parameter.
*
*
* @param type The render type
* @param item The ItemStack being rendered
* @param data Extra Type specific data
*/
@Deprecated
public void renderItem(ItemRenderType type, ItemStack item, Object... data);
}
@@ -1,7 +1,7 @@
package net.minecraftforge.client;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
@@ -0,0 +1,82 @@
package net.minecraftforge.client;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.Maps;
import gnu.trove.map.hash.TIntObjectHashMap;
import gnu.trove.procedure.TIntObjectProcedure;
import net.minecraft.client.renderer.ItemModelMesher;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.item.Item;
/**
* Wrapper around ItemModeMesher that cleans up the internal maps to respect ID remapping.
*/
public class ItemModelMesherForge extends ItemModelMesher
{
IdentityHashMap<Item, TIntObjectHashMap<ModelResourceLocation>> locations = Maps.newIdentityHashMap();
IdentityHashMap<Item, TIntObjectHashMap<IBakedModel>> models = Maps.newIdentityHashMap();
public ItemModelMesherForge(ModelManager manager)
{
super(manager);
}
protected IBakedModel getItemModel(Item item, int meta)
{
TIntObjectHashMap<IBakedModel> map = models.get(item);
return map == null ? null : map.get(meta);
}
public void register(Item item, int meta, ModelResourceLocation location)
{
TIntObjectHashMap<ModelResourceLocation> locs = locations.get(item);
TIntObjectHashMap<IBakedModel> mods = models.get(item);
if (locs == null)
{
locs = new TIntObjectHashMap();
locations.put(item, locs);
}
if (mods == null)
{
mods = new TIntObjectHashMap();
models.put(item, mods);
}
locs.put(meta, location);
mods.put(meta, getModelManager().getModel(location));
}
public void rebuildCache()
{
final ModelManager manager = this.getModelManager();
for (Map.Entry<Item, TIntObjectHashMap<ModelResourceLocation>> e : locations.entrySet())
{
TIntObjectHashMap<IBakedModel> mods = models.get(e.getKey());
if (mods != null)
{
mods.clear();
}
else
{
mods = new TIntObjectHashMap();
models.put(e.getKey(), mods);
}
final TIntObjectHashMap<IBakedModel> map = mods;
e.getValue().forEachEntry(new TIntObjectProcedure<ModelResourceLocation>()
{
@Override
public boolean execute(int meta, ModelResourceLocation location)
{
map.put(meta, manager.getModel(location));
return true;
}
});
}
}
}
@@ -12,6 +12,7 @@ import com.google.common.collect.Maps;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumWorldBlockLayer;
import net.minecraftforge.client.IItemRenderer.ItemRenderType;
public class MinecraftForgeClient
@@ -46,21 +47,23 @@ public class MinecraftForgeClient
return ForgeHooksClient.renderPass;
}
public static int getStencilBits()
public static EnumWorldBlockLayer getRenderLayer()
{
return ForgeHooksClient.stencilBits;
return ForgeHooksClient.renderLayer;
}
private static BitSet stencilBits = new BitSet(getStencilBits());
private static BitSet stencilBits = new BitSet(8);
static
{
stencilBits.set(0,getStencilBits());
stencilBits.set(0,8);
}
/**
* Reserve a stencil bit for use in rendering
*
* Note: you must check the Framebuffer you are working with to
* determine if stencil bits are enabled on it before use.
*
* @return A bit or -1 if no further stencil bits are available
*/
public static int reserveStencilBit()
@@ -80,7 +83,7 @@ public class MinecraftForgeClient
*/
public static void releaseStencilBit(int bit)
{
if (bit >= 0 && bit < getStencilBits())
if (bit >= 0 && bit < stencilBits.length())
{
stencilBits.set(bit);
}
@@ -1,15 +1,23 @@
package net.minecraftforge.client.event;
import net.minecraft.util.IChatComponent;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
@Cancelable
public class ClientChatReceivedEvent extends Event
{
public IChatComponent message;
public ClientChatReceivedEvent(IChatComponent message)
/**
* Introduced in 1.8:
* 0 : Standard Text Message
* 1 : 'System' message, displayed as standard text.
* 2 : 'Status' message, displayed above action bar, where song notifications are.
*/
public final byte type;
public ClientChatReceivedEvent(byte type, IChatComponent message)
{
this.type = type;
this.message = message;
}
}
@@ -1,7 +1,7 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MovingObjectPosition;
@@ -2,10 +2,11 @@ package net.minecraftforge.client.event;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import cpw.mods.fml.common.eventhandler.Event.Result;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Event.Result;
/**
* Event that hooks into EntityRenderer, allowing any feature to customize visual attributes of
@@ -14,11 +15,11 @@ import cpw.mods.fml.common.eventhandler.Event.Result;
public abstract class EntityViewRenderEvent extends Event
{
public final EntityRenderer renderer;
public final EntityLivingBase entity;
public final Entity entity;
public final Block block;
public final double renderPartialTicks;
public EntityViewRenderEvent(EntityRenderer renderer, EntityLivingBase entity, Block block, double renderPartialTicks)
public EntityViewRenderEvent(EntityRenderer renderer, Entity entity, Block block, double renderPartialTicks)
{
this.renderer = renderer;
this.entity = entity;
@@ -35,13 +36,13 @@ public abstract class EntityViewRenderEvent extends Event
{
public float density;
public FogDensity(EntityRenderer renderer, EntityLivingBase entity, Block block, double renderPartialTicks, float density)
public FogDensity(EntityRenderer renderer, Entity entity, Block block, double renderPartialTicks, float density)
{
super(renderer, entity, block, renderPartialTicks);
this.density = density;
}
}
/**
* Event that allows any feature to customize the rendering of fog.
*/
@@ -50,8 +51,8 @@ public abstract class EntityViewRenderEvent extends Event
{
public final int fogMode;
public final float farPlaneDistance;
public RenderFogEvent(EntityRenderer renderer, EntityLivingBase entity, Block block, double renderPartialTicks, int fogMode, float farPlaneDistance)
public RenderFogEvent(EntityRenderer renderer, Entity entity, Block block, double renderPartialTicks, int fogMode, float farPlaneDistance)
{
super(renderer, entity, block, renderPartialTicks);
this.fogMode = fogMode;
@@ -69,7 +70,7 @@ public abstract class EntityViewRenderEvent extends Event
public float green;
public float blue;
public FogColors(EntityRenderer renderer, EntityLivingBase entity, Block block, double renderPartialTicks, float red, float green, float blue)
public FogColors(EntityRenderer renderer, Entity entity, Block block, double renderPartialTicks, float red, float green, float blue)
{
super(renderer, entity, block, renderPartialTicks);
this.red = red;
@@ -1,7 +1,7 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.common.eventhandler.Event;
/**
* Author: MachineMuse (Claire Semple)
@@ -9,11 +9,11 @@ import net.minecraft.client.entity.EntityPlayerSP;
*/
public class FOVUpdateEvent extends Event
{
public final EntityPlayerSP entity;
public final EntityPlayer entity;
public final float fov;
public float newfov;
public FOVUpdateEvent(EntityPlayerSP entity, float fov)
public FOVUpdateEvent(EntityPlayer entity, float fov)
{
this.entity = entity;
this.fov = fov;
@@ -1,7 +1,7 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.client.gui.GuiScreen;
/**
@@ -5,10 +5,10 @@ import java.util.List;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
/**
* Event classes for GuiScreen events.
@@ -0,0 +1,24 @@
package net.minecraftforge.client.event;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelManager;
import net.minecraft.util.IRegistry;
/**
* Fired when the ModelManager is notified of the resource manager reloading.
* Called after model registry is setup, but before it's passed to BlockModelShapes.
*/
public class ModelBakeEvent extends Event
{
public final ModelManager modelManager;
public final IRegistry modelRegistry;
public final ModelBakery modelBakery;
public ModelBakeEvent(ModelManager modelManager, IRegistry modelRegistry, ModelBakery modelBakery)
{
this.modelManager = modelManager;
this.modelRegistry = modelRegistry;
this.modelBakery = modelBakery;
}
}
@@ -2,8 +2,8 @@ package net.minecraftforge.client.event;
import org.lwjgl.input.Mouse;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
/**
* Author: MachineMuse (Claire Semple)
@@ -3,8 +3,8 @@ package net.minecraftforge.client.event;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
/**
* Called when a block's texture is going to be overlaid on the player's HUD. Cancel this event to prevent the overlay.
@@ -2,8 +2,8 @@ package net.minecraftforge.client.event;
import java.util.ArrayList;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.client.gui.ScaledResolution;
@@ -33,16 +33,12 @@ public class RenderGameOverlayEvent extends Event
public final float partialTicks;
public final ScaledResolution resolution;
public final int mouseX;
public final int mouseY;
public final ElementType type;
public RenderGameOverlayEvent(float partialTicks, ScaledResolution resolution, int mouseX, int mouseY)
public RenderGameOverlayEvent(float partialTicks, ScaledResolution resolution)
{
this.partialTicks = partialTicks;
this.resolution = resolution;
this.mouseX = mouseX;
this.mouseY = mouseY;
this.type = null;
}
@@ -50,8 +46,6 @@ public class RenderGameOverlayEvent extends Event
{
this.partialTicks = parent.partialTicks;
this.resolution = parent.resolution;
this.mouseX = parent.mouseX;
this.mouseY = parent.mouseY;
this.type = type;
}
@@ -1,7 +1,7 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.client.renderer.RenderGlobal;
@Cancelable
@@ -3,8 +3,8 @@ package net.minecraftforge.client.event;
import net.minecraft.client.renderer.tileentity.RenderItemFrame;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.item.ItemStack;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
/**
* This event is called when an item is rendered in an item frame.
@@ -1,7 +1,7 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.client.renderer.entity.RendererLivingEntity;
import net.minecraft.entity.EntityLivingBase;
@@ -1,6 +1,6 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraft.client.renderer.entity.RenderPlayer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
@@ -1,7 +1,7 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraft.client.renderer.RenderBlocks;
import net.minecraftforge.fml.common.eventhandler.Event;
//import net.minecraft.client.renderer.RenderBlocks;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.world.ChunkCache;
@@ -9,14 +9,14 @@ public abstract class RenderWorldEvent extends Event
{
public final WorldRenderer renderer;
public final ChunkCache chunkCache;
public final RenderBlocks renderBlocks;
//public final RenderBlocks renderBlocks;
public final int pass;
public RenderWorldEvent(WorldRenderer renderer, ChunkCache chunkCache, RenderBlocks renderBlocks, int pass)
public RenderWorldEvent(WorldRenderer renderer, ChunkCache chunkCache, /*RenderBlocks renderBlocks,*/ int pass)
{
this.renderer = renderer;
this.chunkCache = chunkCache;
this.renderBlocks = renderBlocks;
//this.renderBlocks = renderBlocks;
this.pass = pass;
}
@@ -26,7 +26,7 @@ public abstract class RenderWorldEvent extends Event
*/
public static class Pre extends RenderWorldEvent
{
public Pre(WorldRenderer renderer, ChunkCache chunkCache, RenderBlocks renderBlocks, int pass){ super(renderer, chunkCache, renderBlocks, pass); }
public Pre(WorldRenderer renderer, ChunkCache chunkCache, /*RenderBlocks renderBlocks,*/ int pass){ super(renderer, chunkCache, /*renderBlocks,*/ pass); }
}
/**
@@ -34,6 +34,6 @@ public abstract class RenderWorldEvent extends Event
*/
public static class Post extends RenderWorldEvent
{
public Post(WorldRenderer renderer, ChunkCache chunkCache, RenderBlocks renderBlocks, int pass){ super(renderer, chunkCache, renderBlocks, pass); }
public Post(WorldRenderer renderer, ChunkCache chunkCache, /*RenderBlocks renderBlocks,*/ int pass){ super(renderer, chunkCache, /*renderBlocks,*/ pass); }
}
}
@@ -1,6 +1,6 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.client.renderer.RenderGlobal;
public class RenderWorldLastEvent extends Event
@@ -1,6 +1,6 @@
package net.minecraftforge.client.event;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.client.renderer.texture.TextureMap;
@@ -1,25 +1,29 @@
package net.minecraftforge.client.event.sound;
import net.minecraft.client.audio.ISound;
import net.minecraft.client.audio.SoundCategory;
import net.minecraft.client.audio.SoundManager;
import net.minecraft.client.audio.SoundPoolEntry;
/***
* Raised when the SoundManager tries to play a normal sound.
*
*
* If you return null from this function it will prevent the sound from being played,
* you can return a different entry if you want to change the sound being played.
*/
@Deprecated // Switch with PlaySoundEvent17 in 1.8
public class PlaySoundEvent extends SoundResultEvent
public class PlaySoundEvent extends SoundEvent
{
public final float x;
public final float y;
public final float z;
public PlaySoundEvent(SoundManager manager, SoundPoolEntry source, String name, float x, float y, float z, float volume, float pitch)
{
super(manager, source, name, volume, pitch);
this.x = x;
this.y = y;
this.z = z;
public final String name;
public final ISound sound;
public final SoundCategory category;
public ISound result;
public PlaySoundEvent(SoundManager manager, ISound sound, SoundCategory category)
{
super(manager);
this.sound = sound;
this.category = category;
this.name = sound.getSoundLocation().getResourcePath();
this.result = sound;
}
}
@@ -1,30 +0,0 @@
package net.minecraftforge.client.event.sound;
import net.minecraft.client.audio.ISound;
import net.minecraft.client.audio.SoundCategory;
import net.minecraft.client.audio.SoundManager;
import net.minecraft.client.audio.SoundPoolEntry;
/***
* Raised when the SoundManager tries to play a normal sound.
*
* If you return null from this function it will prevent the sound from being played,
* you can return a different entry if you want to change the sound being played.
*/
//TODO: Replace PlaySoundEvent in 1.8
public class PlaySoundEvent17 extends SoundEvent
{
public final String name;
public final ISound sound;
public final SoundCategory category;
public ISound result;
public PlaySoundEvent17(SoundManager manager, ISound sound, SoundCategory category)
{
super(manager);
this.sound = sound;
this.category = category;
this.name = sound.getPositionedSoundLocation().getResourcePath();
this.result = sound;
}
}
@@ -6,33 +6,8 @@ import net.minecraftforge.client.event.sound.SoundEvent.SoundSourceEvent;
public class PlaySoundSourceEvent extends SoundSourceEvent
{
@Deprecated
public final SoundManager manager;
@Deprecated
public final String name;
@Deprecated
public final float x;
@Deprecated
public final float y;
@Deprecated
public final float z;
@Deprecated
public PlaySoundSourceEvent(SoundManager manager, String name, float x, float y, float z)
{
super(manager, null, null);
this.manager = manager;
this.name = name;
this.x = x;
this.y = y;
this.z = z;
}
public PlaySoundSourceEvent(SoundManager manager, ISound sound, String uuid)
{
super(manager, sound, uuid);
this.name = sound.getPositionedSoundLocation().getResourcePath();
this.manager = manager;
this.x = this.y = this.z = 0;
}
}
@@ -6,33 +6,8 @@ import net.minecraftforge.client.event.sound.SoundEvent.SoundSourceEvent;
public class PlayStreamingSourceEvent extends SoundSourceEvent
{
@Deprecated
public final SoundManager manager;
@Deprecated
public final String name;
@Deprecated
public final float x;
@Deprecated
public final float y;
@Deprecated
public final float z;
@Deprecated
public PlayStreamingSourceEvent(SoundManager manager, String name, float x, float y, float z)
{
super(manager, null, null);
this.manager = manager;
this.name = name;
this.x = x;
this.y = y;
this.z = z;
}
public PlayStreamingSourceEvent(SoundManager manager, ISound sound, String uuid)
{
super(manager, sound, uuid);
this.x = this.y = this.z = 0;
this.manager = null;
this.name = sound.getPositionedSoundLocation().getResourcePath();
}
}
@@ -1,6 +1,6 @@
package net.minecraftforge.client.event.sound;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.client.audio.ISound;
import net.minecraft.client.audio.SoundManager;
import net.minecraft.client.audio.SoundPoolEntry;
@@ -13,7 +13,7 @@ public class SoundEvent extends Event
{
this.manager = manager;
}
@Deprecated
public static SoundPoolEntry getResult(SoundResultEvent event)
{
@@ -30,7 +30,7 @@ public class SoundEvent extends Event
public SoundSourceEvent(SoundManager manager, ISound sound, String uuid)
{
super(manager);
this.name = sound.getPositionedSoundLocation().getResourcePath();
this.name = sound.getSoundLocation().getResourcePath();
this.sound = sound;
this.uuid = uuid;
}
@@ -22,33 +22,33 @@ import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.ConfigElement;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import cpw.mods.fml.client.IModGuiFactory;
import cpw.mods.fml.client.IModGuiFactory.RuntimeOptionCategoryElement;
import cpw.mods.fml.client.IModGuiFactory.RuntimeOptionGuiHandler;
import cpw.mods.fml.client.config.ConfigGuiType;
import cpw.mods.fml.client.config.DummyConfigElement;
import cpw.mods.fml.client.config.DummyConfigElement.DummyCategoryElement;
import cpw.mods.fml.client.config.GuiButtonExt;
import cpw.mods.fml.client.config.GuiConfig;
import cpw.mods.fml.client.config.GuiConfigEntries;
import cpw.mods.fml.client.config.GuiConfigEntries.CategoryEntry;
import cpw.mods.fml.client.config.GuiConfigEntries.IConfigEntry;
import cpw.mods.fml.client.config.GuiConfigEntries.SelectValueEntry;
import cpw.mods.fml.client.config.GuiConfigEntries.BooleanEntry;
import cpw.mods.fml.client.config.HoverChecker;
import cpw.mods.fml.client.config.IConfigElement;
import cpw.mods.fml.client.config.GuiConfigEntries.ListEntryBase;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraftforge.fml.client.IModGuiFactory;
import net.minecraftforge.fml.client.IModGuiFactory.RuntimeOptionCategoryElement;
import net.minecraftforge.fml.client.IModGuiFactory.RuntimeOptionGuiHandler;
import net.minecraftforge.fml.client.config.ConfigGuiType;
import net.minecraftforge.fml.client.config.DummyConfigElement;
import net.minecraftforge.fml.client.config.DummyConfigElement.DummyCategoryElement;
import net.minecraftforge.fml.client.config.GuiButtonExt;
import net.minecraftforge.fml.client.config.GuiConfig;
import net.minecraftforge.fml.client.config.GuiConfigEntries;
import net.minecraftforge.fml.client.config.GuiConfigEntries.CategoryEntry;
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
import net.minecraftforge.fml.client.config.GuiConfigEntries.SelectValueEntry;
import net.minecraftforge.fml.client.config.GuiConfigEntries.BooleanEntry;
import net.minecraftforge.fml.client.config.HoverChecker;
import net.minecraftforge.fml.client.config.IConfigElement;
import net.minecraftforge.fml.client.config.GuiConfigEntries.ListEntryBase;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
/**
* This is the base GuiConfig screen class that all the other Forge-specific config screens will be called from.
* Since Forge has multiple config files I thought I would use that opportunity to show some of the ways
* that the config GUI system can be extended to create custom config GUIs that have additional features
* over the base functionality of just displaying Properties and ConfigCategories.
*
*
* The concepts implemented here are:
* - using custom IConfigEntry objects to define child-screens that have specific Properties listed
* - using custom IConfigEntry objects to define a dummy property that can be used to generate new ConfigCategory objects
@@ -58,25 +58,25 @@ import cpw.mods.fml.relauncher.SideOnly;
* - overriding the IConfigEntry.enabled() method to control the enabled state of one list entry based on the value of another entry
* - overriding the IConfigEntry.onGuiClosed() method to perform custom actions when the screen that owns the entry is closed (in this
* case a new ConfigCategory is added to the Configuration object)
*
*
* The config file structure looks like this:
* forge.cfg (general settings all in one category)
* forgeChunkLoading.cfg
* - Forge (category)
* - defaults (category)
* - [optional mod override categories]...
*
*
* The GUI structure is this:
* Base Screen
* - General Settings (from forge.cfg)
* - Chunk Loader Settings (from forgeChunkLoading.cfg)
* - Chunk Loader Settings (from forgeChunkLoading.cfg)
* - Defaults (these elements are listed directly on this screen)
* - Mod Overrides
* - Add New Mod Override
* - Mod1
* - Mod2
* - etc.
*
*
* Other things to check out:
* ForgeModContainer.syncConfig()
* ForgeModContainer.onConfigChanged()
@@ -87,23 +87,23 @@ public class ForgeGuiFactory implements IModGuiFactory
{
@Override
public void initialize(Minecraft minecraftInstance) {}
@Override
public Class<? extends GuiScreen> mainConfigGuiClass() { return ForgeConfigGui.class; }
@Override
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() { return null; }
@Override
public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { return null; }
public static class ForgeConfigGui extends GuiConfig
public static class ForgeConfigGui extends GuiConfig
{
public ForgeConfigGui(GuiScreen parentScreen)
{
super(parentScreen, getConfigElements(), "Forge", false, false, I18n.format("forge.configgui.forgeConfigTitle"));
}
private static List<IConfigElement> getConfigElements()
{
List<IConfigElement> list = new ArrayList<IConfigElement>();
@@ -111,9 +111,9 @@ public class ForgeGuiFactory implements IModGuiFactory
list.add(new DummyCategoryElement("forgeChunkLoadingCfg", "forge.configgui.ctgy.forgeChunkLoadingConfig", ChunkLoaderEntry.class));
return list;
}
/**
* This custom list entry provides the General Settings entry on the Minecraft Forge Configuration screen.
* This custom list entry provides the General Settings entry on the Minecraft Forge Configuration screen.
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
*/
public static class GeneralEntry extends CategoryEntry
@@ -122,20 +122,20 @@ public class ForgeGuiFactory implements IModGuiFactory
{
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen()
{
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed. The parent
// GuiConfig object's entryList will also be refreshed to reflect the changes.
return new GuiConfig(this.owningScreen,
(new ConfigElement(ForgeModContainer.getConfig().getCategory(Configuration.CATEGORY_GENERAL))).getChildElements(),
this.owningScreen.modID, Configuration.CATEGORY_GENERAL, this.configElement.requiresWorldRestart() || this.owningScreen.allRequireWorldRestart,
return new GuiConfig(this.owningScreen,
(new ConfigElement(ForgeModContainer.getConfig().getCategory(Configuration.CATEGORY_GENERAL))).getChildElements(),
this.owningScreen.modID, Configuration.CATEGORY_GENERAL, this.configElement.requiresWorldRestart() || this.owningScreen.allRequireWorldRestart,
this.configElement.requiresMcRestart() || this.owningScreen.allRequireMcRestart,
GuiConfig.getAbridgedConfigPath(ForgeModContainer.getConfig().toString()));
}
}
/**
* This custom list entry provides the Forge Chunk Manager Config entry on the Minecraft Forge Configuration screen.
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
@@ -146,38 +146,38 @@ public class ForgeGuiFactory implements IModGuiFactory
{
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen()
{
List<IConfigElement> list = new ArrayList<IConfigElement>();
list.add(new DummyCategoryElement("forgeChunkLoadingModCfg", "forge.configgui.ctgy.forgeChunkLoadingModConfig",
list.add(new DummyCategoryElement("forgeChunkLoadingModCfg", "forge.configgui.ctgy.forgeChunkLoadingModConfig",
ModOverridesEntry.class));
list.addAll((new ConfigElement(ForgeChunkManager.getDefaultsCategory())).getChildElements());
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed. The parent
// GuiConfig object's propertyList will also be refreshed to reflect the changes.
return new GuiConfig(this.owningScreen, list, this.owningScreen.modID, "chunkLoader",
this.configElement.requiresWorldRestart() || this.owningScreen.allRequireWorldRestart,
return new GuiConfig(this.owningScreen, list, this.owningScreen.modID, "chunkLoader",
this.configElement.requiresWorldRestart() || this.owningScreen.allRequireWorldRestart,
this.configElement.requiresMcRestart() || this.owningScreen.allRequireMcRestart,
GuiConfig.getAbridgedConfigPath(ForgeChunkManager.getConfig().toString()),
I18n.format("forge.configgui.ctgy.forgeChunkLoadingConfig"));
}
}
/**
* This custom list entry provides the Mod Overrides entry on the Forge Chunk Loading config screen.
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
* In this case it adds the custom entry for adding a new mod override and lists the existing mod overrides.
*/
public static class ModOverridesEntry extends CategoryEntry
{
{
public ModOverridesEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
{
super(owningScreen, owningEntryList, prop);
}
/**
* This method is called in the constructor and is used to set the childScreen field.
*/
@@ -185,21 +185,21 @@ public class ForgeGuiFactory implements IModGuiFactory
protected GuiScreen buildChildScreen()
{
List<IConfigElement> list = new ArrayList<IConfigElement>();
list.add(new DummyCategoryElement("addForgeChunkLoadingModCfg", "forge.configgui.ctgy.forgeChunkLoadingAddModConfig",
list.add(new DummyCategoryElement("addForgeChunkLoadingModCfg", "forge.configgui.ctgy.forgeChunkLoadingAddModConfig",
AddModOverrideEntry.class));
for (ConfigCategory cc : ForgeChunkManager.getModCategories())
list.add(new ConfigElement(cc));
return new GuiConfig(this.owningScreen, list, this.owningScreen.modID,
this.configElement.requiresWorldRestart() || this.owningScreen.allRequireWorldRestart,
this.configElement.requiresMcRestart() || this.owningScreen.allRequireMcRestart, this.owningScreen.title,
this.configElement.requiresMcRestart() || this.owningScreen.allRequireMcRestart, this.owningScreen.title,
I18n.format("forge.configgui.ctgy.forgeChunkLoadingModConfig"));
}
/**
* By overriding the enabled() method and checking the value of the "enabled" entry this entry is enabled/disabled based on the value of
* the other entry.
* the other entry.
*/
@Override
public boolean enabled()
@@ -211,10 +211,10 @@ public class ForgeGuiFactory implements IModGuiFactory
return Boolean.valueOf(entry.getCurrentValue().toString());
}
}
return true;
}
/**
* Check to see if the child screen's entry list has changed.
*/
@@ -228,7 +228,7 @@ public class ForgeGuiFactory implements IModGuiFactory
}
return false;
}
/**
* Since adding a new entry to the child screen is what constitutes a change here, reset the child
* screen listEntries to the saved list.
@@ -242,12 +242,12 @@ public class ForgeGuiFactory implements IModGuiFactory
for (IConfigEntry ice : child.entryList.listEntries)
if (!child.initEntries.contains(ice) && ForgeChunkManager.getConfig().hasCategory(ice.getName()))
ForgeChunkManager.getConfig().removeCategory(ForgeChunkManager.getConfig().getCategory(ice.getName()));
child.entryList.listEntries = new ArrayList<IConfigEntry>(child.initEntries);
}
}
}
/**
* This custom list entry provides a button that will open to a screen that will allow a user to define a new mod override.
*/
@@ -257,29 +257,29 @@ public class ForgeGuiFactory implements IModGuiFactory
{
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen()
{
List<IConfigElement> list = new ArrayList<IConfigElement>();
list.add(new DummyConfigElement("modID", "", ConfigGuiType.STRING, "forge.configgui.modID").setCustomListEntryClass(ModIDEntry.class));
list.add(new ConfigElement<Integer>(new Property("maximumTicketCount", "200", Property.Type.INTEGER, "forge.configgui.maximumTicketCount")));
list.add(new ConfigElement<Integer>(new Property("maximumChunksPerTicket", "25", Property.Type.INTEGER, "forge.configgui.maximumChunksPerTicket")));
list.add(new ConfigElement(new Property("maximumTicketCount", "200", Property.Type.INTEGER, "forge.configgui.maximumTicketCount")));
list.add(new ConfigElement(new Property("maximumChunksPerTicket", "25", Property.Type.INTEGER, "forge.configgui.maximumChunksPerTicket")));
return new GuiConfig(this.owningScreen, list, this.owningScreen.modID,
this.configElement.requiresWorldRestart() || this.owningScreen.allRequireWorldRestart,
this.configElement.requiresMcRestart() || this.owningScreen.allRequireMcRestart, this.owningScreen.title,
I18n.format("forge.configgui.ctgy.forgeChunkLoadingAddModConfig"));
}
@Override
public boolean isChanged()
{
return false;
}
}
/**
* This custom list entry provides a Mod ID selector. The control is a button that opens a list of values to select from.
* This entry also overrides onGuiClosed() to run code to save the data to a new ConfigCategory when the user is done.
@@ -287,26 +287,26 @@ public class ForgeGuiFactory implements IModGuiFactory
public static class ModIDEntry extends SelectValueEntry
{
public ModIDEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
{
{
super(owningScreen, owningEntryList, prop, getSelectableValues());
if (this.selectableValues.size() == 0)
this.btnValue.enabled = false;
}
private static Map<Object, String> getSelectableValues()
{
Map<Object, String> selectableValues = new TreeMap<Object, String>();
for (ModContainer mod : Loader.instance().getActiveModList())
// only add mods to the list that have a non-immutable ModContainer
if (!mod.isImmutable() && mod.getMod() != null)
selectableValues.put(mod.getModId(), mod.getName());
return selectableValues;
}
/**
* By overriding onGuiClosed() for this entry we can perform additional actions when the user is done such as saving
* By overriding onGuiClosed() for this entry we can perform additional actions when the user is done such as saving
* a new ConfigCategory object to the Configuration object.
*/
@Override
@@ -323,25 +323,25 @@ public class ForgeGuiFactory implements IModGuiFactory
maxTickets = Integer.valueOf(ice.get().toString());
else if ("maximumChunksPerTicket".equals(ice.getName()))
maxChunks = Integer.valueOf(ice.get().toString());
ForgeChunkManager.addConfigProperty(modObject, "maximumTicketCount", String.valueOf(maxTickets), Property.Type.INTEGER);
ForgeChunkManager.addConfigProperty(modObject, "maximumChunksPerTicket", String.valueOf(maxChunks), Property.Type.INTEGER);
if (this.owningScreen.parentScreen instanceof GuiConfig)
{
GuiConfig superParent = (GuiConfig) this.owningScreen.parentScreen;
ConfigCategory modCtgy = ForgeChunkManager.getConfigFor(modObject);
modCtgy.setPropertyOrder(ForgeChunkManager.MOD_PROP_ORDER);
ConfigElement modConfig = new ConfigElement(modCtgy);
boolean found = false;
for (IConfigElement ice : superParent.configElements)
if (ice.getName().equals(currentValue))
found = true;
if (!found)
superParent.configElements.add(modConfig);
superParent.needsRefresh = true;
superParent.initGui();
}
@@ -1,79 +0,0 @@
package net.minecraftforge.client.model;
// TODO: Move this package to net.minecraftforge.model in 1.8
import java.util.Collection;
import java.util.Map;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.obj.ObjModelLoader;
import net.minecraftforge.client.model.techne.TechneModelLoader;
import com.google.common.collect.Maps;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
/**
* Common interface for advanced model loading from files, based on file suffix
* Model support can be queried through the {@link #getSupportedSuffixes()} method.
* Instances can be created by calling {@link #loadModel(String)} with a class-loadable-path
*
* @author cpw
*
*/
@SideOnly(Side.CLIENT)
public class AdvancedModelLoader {
private static Map<String, IModelCustomLoader> instances = Maps.newHashMap();
/**
* Register a new model handler
* @param modelHandler The model handler to register
*/
public static void registerModelHandler(IModelCustomLoader modelHandler)
{
for (String suffix : modelHandler.getSuffixes())
{
instances.put(suffix, modelHandler);
}
}
/**
* Load the model from the supplied classpath resolvable resource name
* @param resource The resource name
* @return A model
* @throws IllegalArgumentException if the resource name cannot be understood
* @throws ModelFormatException if the underlying model handler cannot parse the model format
*/
public static IModelCustom loadModel(ResourceLocation resource) throws IllegalArgumentException, ModelFormatException
{
String name = resource.getResourcePath();
int i = name.lastIndexOf('.');
if (i == -1)
{
FMLLog.severe("The resource name %s is not valid", resource);
throw new IllegalArgumentException("The resource name is not valid");
}
String suffix = name.substring(i+1);
IModelCustomLoader loader = instances.get(suffix);
if (loader == null)
{
FMLLog.severe("The resource name %s is not supported", resource);
throw new IllegalArgumentException("The resource name is not supported");
}
return loader.loadInstance(resource);
}
public static Collection<String> getSupportedSuffixes()
{
return instances.keySet();
}
static
{
registerModelHandler(new ObjModelLoader());
registerModelHandler(new TechneModelLoader());
}
}
@@ -0,0 +1,107 @@
package net.minecraftforge.client.model;
import java.nio.ByteBuffer;
import java.util.List;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.client.renderer.vertex.VertexFormatElement.EnumType;
import net.minecraft.client.renderer.vertex.VertexFormatElement.EnumUsage;
public class Attributes
{
/*
* Default format of the data in IBakedModel
*/
public static final VertexFormat DEFAULT_BAKED_FORMAT;
static
{
DEFAULT_BAKED_FORMAT = new VertexFormat();
DEFAULT_BAKED_FORMAT.setElement(new VertexFormatElement(0, EnumType.FLOAT, EnumUsage.POSITION, 3));
DEFAULT_BAKED_FORMAT.setElement(new VertexFormatElement(0, EnumType.UBYTE, EnumUsage.COLOR, 4));
DEFAULT_BAKED_FORMAT.setElement(new VertexFormatElement(0, EnumType.FLOAT, EnumUsage.UV, 2));
DEFAULT_BAKED_FORMAT.setElement(new VertexFormatElement(0, EnumType.BYTE, EnumUsage.PADDING, 4));
}
/*
* Can first format be used where second is expected
*/
public static boolean moreSpecific(VertexFormat first, VertexFormat second)
{
int size = first.getNextOffset();
if(size != second.getNextOffset()) return false;
int padding = 0;
int j = 0;
for(VertexFormatElement firstAttr : (List<VertexFormatElement>)first.getElements())
{
while(j < second.getElementCount() && second.getElement(j).getUsage() == EnumUsage.PADDING)
{
padding += second.getElement(j++).getSize();
}
if(j >= second.getElementCount() && padding == 0)
{
// if no padding is left, but there are still elements in first (we're processing one) - it doesn't fit
return false;
}
if(padding == 0)
{
// no padding - attributes have to match
VertexFormatElement secondAttr = second.getElement(j++);
if(
firstAttr.getIndex() != secondAttr.getIndex() ||
firstAttr.getElementCount() != secondAttr.getElementCount() ||
firstAttr.getType() != secondAttr.getType() ||
firstAttr.getUsage() != secondAttr.getUsage())
{
return false;
}
}
else
{
// padding - attribute should fit in it
padding -= firstAttr.getSize();
if(padding < 0) return false;
}
}
if(padding != 0 || j != second.getElementCount()) return false;
return true;
}
public static void put(ByteBuffer buf, VertexFormatElement e, boolean normalize, Number fill, Number... ns)
{
if(e.getElementCount() > ns.length && fill == null) throw new IllegalArgumentException("not enough elements");
Number n;
for(int i = 0; i < e.getElementCount(); i++)
{
if(i < ns.length) n = ns[i];
else n = fill;
switch(e.getType())
{
case BYTE:
buf.put(normalize ? (byte)(n.floatValue() / (Byte.MAX_VALUE - 1)) : n.byteValue());
break;
case UBYTE:
buf.put(normalize ? (byte)(n.floatValue() / ((byte) -1)) : n.byteValue());
break;
case SHORT:
buf.putShort(normalize ? (short)(n.floatValue() / (Short.MAX_VALUE - 1)) : n.shortValue());
break;
case USHORT:
buf.putShort(normalize ? (short)(n.floatValue() / ((short) -1)) : n.shortValue());
break;
case INT:
buf.putInt(normalize ? (int)(n.doubleValue() / (Integer.MAX_VALUE - 1)) : n.intValue());
break;
case UINT:
buf.putInt(normalize ? (int)(n.doubleValue() / ((int) - 1)) : n.intValue());
break;
case FLOAT:
buf.putFloat(n.floatValue());
break;
}
}
}
}
@@ -0,0 +1,18 @@
package net.minecraftforge.client.model;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.util.ResourceLocation;
public interface ICustomModelLoader extends IResourceManagerReloadListener
{
/*
* Checks if given model should be loaded by this loader.
* Reading file contents is inadvisable, if possible decision should be made based on the location alone.
*/
public boolean accepts(ResourceLocation modelLocation);
/*
* loads (or reloads) specified model
*/
public IModel loadModel(ResourceLocation modelLocation);
}
@@ -0,0 +1,82 @@
package net.minecraftforge.client.model;
import java.util.List;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.util.EnumFacing;
/*
* Version of IBakedModel with less restriction on camera transformations and with explicit format of the baked array.
*/
public interface IFlexibleBakedModel extends IBakedModel
{
// non-erased versions of the IBakedModel methods
List<BakedQuad> getFaceQuads(EnumFacing side);
List<BakedQuad> getGeneralQuads();
/*
* Specifies the format which BakedQuads' getVertexData will have.
*/
VertexFormat getFormat();
/*
* Default implementation of IFlexibleBakedModel that should be useful in most cases
*/
public static class Wrapper implements IFlexibleBakedModel
{
private final IBakedModel parent;
VertexFormat format;
public Wrapper(IBakedModel parent, VertexFormat format)
{
this.parent = parent;
this.format = format;
}
@SuppressWarnings("unchecked")
public List<BakedQuad> getFaceQuads(EnumFacing side)
{
return parent.getFaceQuads(side);
}
@SuppressWarnings("unchecked")
public List<BakedQuad> getGeneralQuads()
{
return parent.getGeneralQuads();
}
public boolean isAmbientOcclusion()
{
return parent.isAmbientOcclusion();
}
public boolean isGui3d()
{
return parent.isGui3d();
}
public boolean isBuiltInRenderer()
{
return parent.isBuiltInRenderer();
}
public TextureAtlasSprite getTexture()
{
return parent.getTexture();
}
@Deprecated
public ItemCameraTransforms getItemCameraTransforms()
{
return parent.getItemCameraTransforms();
}
public VertexFormat getFormat()
{
return new VertexFormat(format);
}
}
}
@@ -0,0 +1,45 @@
package net.minecraftforge.client.model;
import java.util.Collection;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.ResourceLocation;
import com.google.common.base.Function;
/*
* Interface for models that can be baked
* (possibly to different vertex formats and with different state).
*/
public interface IModel extends IModelPart
{
/*
* Returns all model locations that this model depends on.
* Assume that returned collection is immutable.
*/
Collection<ResourceLocation> getDependencies();
/*
* Returns all texture locations that this model depends on.
* Assume that returned collection is immutable.
*/
Collection<ResourceLocation> getTextures();
/*
* All model texture coordinates should be resolved at this method.
* Returned model should be in the simplest form possible, for performance
* reasons (if it's not ISmartBlock/ItemModel - then it should be
* represented by List<BakedQuad> internally).
* Returned model's getFormat() can me less specific than the passed
* format argument (some attributes can be replaced with padding),
* if there's no such info in this model.
*/
IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter);
/*
* Default state this model will be baked with.
* See IModelState.
*/
IModelState getDefaultState();
}
@@ -1,17 +0,0 @@
package net.minecraftforge.client.model;
import static cpw.mods.fml.relauncher.Side.CLIENT;
import cpw.mods.fml.relauncher.SideOnly;
public interface IModelCustom
{
String getType();
@SideOnly(CLIENT)
void renderAll();
@SideOnly(CLIENT)
void renderOnly(String... groupNames);
@SideOnly(CLIENT)
void renderPart(String partName);
@SideOnly(CLIENT)
void renderAllExcept(String... excludedGroupNames);
}
@@ -1,29 +0,0 @@
package net.minecraftforge.client.model;
import net.minecraft.util.ResourceLocation;
/**
* Instances of this class act as factories for their model type
*
* @author cpw
*
*/
public interface IModelCustomLoader {
/**
* Get the main type name for this loader
* @return the type name
*/
String getType();
/**
* Get resource suffixes this model loader recognizes
* @return a list of suffixes
*/
String[] getSuffixes();
/**
* Load a model instance from the supplied path
* @param resource The ResourceLocation of the model
* @return A model instance
* @throws ModelFormatException if the model format is not correct
*/
IModelCustom loadInstance(ResourceLocation resource) throws ModelFormatException;
}
@@ -0,0 +1,8 @@
package net.minecraftforge.client.model;
/*
* Represents the part of the model you can refer to, for example: mesh,
* skeleton, bone or some separately animated submodel.
* Primary function of this interface is the argument type of IModelState.apply.
*/
public interface IModelPart {}
@@ -0,0 +1,18 @@
package net.minecraftforge.client.model;
import javax.vecmath.Matrix4f;
import com.google.common.base.Function;
/*
* Represents the dynamic information associated with the model.
* Common use case is (possibly interpolated) animation frame.
*/
public interface IModelState extends Function<IModelPart, TRSRTransformation>
{
/*
* returns the transformation (in the local coordinates) that needs to be applied to the specific part of the model.
*/
@Override
TRSRTransformation apply(IModelPart part);
}
@@ -0,0 +1,22 @@
package net.minecraftforge.client.model;
import javax.vecmath.Matrix4f;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.item.ItemStack;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.resources.model.IBakedModel;
/*
* Model that changes based on the rendering perspective
* (first-person, GUI, e.t.c - see TransformType)
*/
public interface IPerspectiveAwareModel extends IBakedModel
{
/*
* Returns the pair of the model for the given perspective, and the matrix
* that should be applied to the GL state before rendering it (matrix may be null).
*/
Pair<IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType);
}
@@ -0,0 +1,9 @@
package net.minecraftforge.client.model;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.resources.model.IBakedModel;
public interface ISmartBlockModel extends IBakedModel
{
IBakedModel handleBlockState(IBlockState state);
}
@@ -0,0 +1,9 @@
package net.minecraftforge.client.model;
import net.minecraft.item.ItemStack;
import net.minecraft.client.resources.model.IBakedModel;
public interface ISmartItemModel extends IBakedModel
{
IBakedModel handleItemState(ItemStack stack);
}
@@ -0,0 +1,18 @@
package net.minecraftforge.client.model;
import javax.vecmath.Matrix4f;
import net.minecraft.util.EnumFacing;
/*
* Replacement interface for ModelRotation to allow custom transformations of vanilla models.
* You should probably use TRSRTransformation directly.
*/
public interface ITransformation
{
public Matrix4f getMatrix();
public EnumFacing rotate(EnumFacing facing);
public int rotate(EnumFacing facing, int vertexIndex);
}
@@ -0,0 +1,31 @@
package net.minecraftforge.client.model;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
/*
* Simple implementation of IModelState via a map and a default value.
*/
public class MapModelState implements IModelState
{
private final ImmutableMap<IModelPart, TRSRTransformation> map;
private final TRSRTransformation def;
public MapModelState(Map<IModelPart, TRSRTransformation> map)
{
this(map, TRSRTransformation.identity());
}
public MapModelState(Map<IModelPart, TRSRTransformation> map, TRSRTransformation def)
{
this.map = ImmutableMap.copyOf(map);
this.def = def;
}
public TRSRTransformation apply(IModelPart part)
{
if(!map.containsKey(part)) return def;
return map.get(part);
}
}
@@ -1,33 +0,0 @@
package net.minecraftforge.client.model;
/**
* Thrown if there is a problem parsing the model
*
* @author cpw
*
*/
public class ModelFormatException extends RuntimeException {
private static final long serialVersionUID = 2023547503969671835L;
public ModelFormatException()
{
super();
}
public ModelFormatException(String message, Throwable cause)
{
super(message, cause);
}
public ModelFormatException(String message)
{
super(message);
}
public ModelFormatException(Throwable cause)
{
super(cause);
}
}
@@ -0,0 +1,399 @@
package net.minecraftforge.client.model;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.BlockModelShapes;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.model.ItemModelGenerator;
import net.minecraft.client.renderer.block.model.ModelBlock;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition.MissingVariantException;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition.Variant;
import net.minecraft.client.renderer.block.model.ModelBlockDefinition.Variants;
import net.minecraft.client.renderer.texture.IIconCreator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.model.BuiltInModel;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.client.resources.model.ModelRotation;
import net.minecraft.client.resources.model.WeightedBakedModel;
import net.minecraft.item.Item;
import net.minecraft.util.IRegistry;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.registry.GameData;
import org.apache.logging.log4j.Level;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
public class ModelLoader extends ModelBakery
{
private final Map<ModelResourceLocation, IModel> stateModels = new HashMap<ModelResourceLocation, IModel>();
private final Set<ResourceLocation> resolveTextures = new HashSet<ResourceLocation>();
private final Set<ResourceLocation> uvLocked = new HashSet<ResourceLocation>();
private final Set<ResourceLocation> textures = new HashSet<ResourceLocation>();
private final Set<ResourceLocation> loadingModels = new HashSet<ResourceLocation>();
public ModelLoader(IResourceManager manager, TextureMap map, BlockModelShapes shapes)
{
super(manager, map, shapes);
VanillaLoader.instance.setLoader(this);
ModelLoaderRegistry.clearModelCache();
}
@Override
public IRegistry setupModelRegistry()
{
loadBlocks();
loadItems();
stateModels.put(MODEL_MISSING, getModel(new ResourceLocation(MODEL_MISSING.getResourceDomain(), MODEL_MISSING.getResourcePath())));
textures.remove(TextureMap.LOCATION_MISSING_TEXTURE);
textures.addAll(LOCATIONS_BUILTIN_TEXTURES);
textureMap.loadSprites(resourceManager, new IIconCreator()
{
public void registerSprites(TextureMap map)
{
for(ResourceLocation t : textures)
{
sprites.put(t, map.registerSprite(t));
}
}
});
sprites.put(new ResourceLocation("missingno"), textureMap.getMissingSprite());
Function<ResourceLocation, TextureAtlasSprite> textureGetter = Functions.forMap(sprites, textureMap.getMissingSprite());
for(Entry<ModelResourceLocation, IModel> e : stateModels.entrySet())
{
bakedRegistry.putObject(e.getKey(), e.getValue().bake(e.getValue().getDefaultState(), Attributes.DEFAULT_BAKED_FORMAT, textureGetter));
}
return bakedRegistry;
}
private void loadBlocks()
{
Map<IBlockState, ModelResourceLocation> stateMap = blockModelShapes.getBlockStateMapper().putAllStateModelLocations();
loadVariants(stateMap.values());
}
@Override
protected void registerVariant(ModelBlockDefinition definition, ModelResourceLocation location)
{
Variants variants = null;
try
{
variants = definition.getVariants(location.getVariant());
}
catch(MissingVariantException e) {}
if(variants == null)
{
// adding default variant for simple blocks
ResourceLocation loc = new ResourceLocation(location.getResourceDomain(), "block/" + location.getResourcePath());
variants = new Variants("normal", Lists.newArrayList(new Variant(loc, ModelRotation.X0_Y0, false, 1)));
}
if(!variants.getVariants().isEmpty())
{
try
{
stateModels.put(location, new WeightedRandomModel(variants));
}
catch(Throwable e)
{
throw new RuntimeException(e);
}
}
}
private void loadItems()
{
registerVariantNames();
for(Item item : GameData.getItemRegistry().typeSafeIterable())
{
for(String s : (List<String>)getVariantNames(item))
{
ResourceLocation file = getItemLocation(s);
ModelResourceLocation memory = new ModelResourceLocation(s, "inventory");
resolveTextures.add(ModelLoaderRegistry.getActualLocation(file));
IModel model = getModel(file);
if(model != null) stateModels.put(memory, model);
}
}
}
public IModel getModel(ResourceLocation location)
{
if(!ModelLoaderRegistry.loaded(location)) loadAnyModel(location);
return ModelLoaderRegistry.getModel(location);
}
@Override
protected ResourceLocation getModelLocation(ResourceLocation model)
{
return new ResourceLocation(model.getResourceDomain(), model.getResourcePath() + ".json");
}
private void loadAnyModel(ResourceLocation location)
{
if(loadingModels.contains(location))
{
throw new IllegalStateException("circular model dependencies involving model " + location);
}
loadingModels.add(location);
IModel model = ModelLoaderRegistry.getModel(location);
for(ResourceLocation dep : model.getDependencies())
{
getModel(dep);
}
textures.addAll(model.getTextures());
loadingModels.remove(location);
}
private class VanillaModelWrapper implements IModel
{
private final ResourceLocation location;
private final ModelBlock model;
public VanillaModelWrapper(ResourceLocation location, ModelBlock model)
{
this.location = location;
this.model = model;
}
public Collection<ResourceLocation> getDependencies()
{
if(model.getParentLocation() == null || model.getParentLocation().getResourcePath().startsWith("builtin/")) return Collections.emptyList();
return Collections.singletonList(model.getParentLocation());
}
public Collection<ResourceLocation> getTextures()
{
// setting parent here to make textures resolve properly
if(model.getParentLocation() != null)
{
IModel parent = getModel(model.getParentLocation());
if(parent instanceof VanillaModelWrapper)
{
model.parent = ((VanillaModelWrapper) parent).model;
}
else
{
throw new IllegalStateException("vanilla model" + model + "can't have non-vanilla parent");
}
}
if(!resolveTextures.contains(location)) return Collections.emptyList();
ImmutableSet.Builder<ResourceLocation> builder = ImmutableSet.builder();
builder.add(new ResourceLocation(model.resolveTextureName("particle")));
if(hasItemModel(model))
{
for(String s : (List<String>)ItemModelGenerator.LAYERS)
{
String r = model.resolveTextureName(s);
ResourceLocation loc = new ResourceLocation(r);
if(!r.equals(s))
{
builder.add(loc);
}
// mojang hardcode
if(model.getRootModel() == MODEL_COMPASS && !loc.equals(TextureMap.LOCATION_MISSING_TEXTURE))
{
TextureAtlasSprite.setLocationNameCompass(loc.toString());
}
else if(model.getRootModel() == MODEL_CLOCK && !loc.equals(TextureMap.LOCATION_MISSING_TEXTURE))
{
TextureAtlasSprite.setLocationNameClock(loc.toString());
}
}
}
if(location.getResourcePath().startsWith("models/block/") || !ModelLoader.this.isBuiltinModel(model.getRootModel()))
{
builder.addAll(ModelLoader.this.getTextureLocations(model));
}
return builder.build();
}
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
{
if(!Attributes.moreSpecific(format, Attributes.DEFAULT_BAKED_FORMAT))
{
throw new IllegalArgumentException("can't bake vanilla models to the format that doesn't fit into the default one: " + format);
}
ModelBlock model = this.model;
if(hasItemModel(model)) model = makeItemModel(model);
if(isCustomRenderer(model)) return new IFlexibleBakedModel.Wrapper(new BuiltInModel(new ItemCameraTransforms(model.getThirdPersonTransform(), model.getFirstPersonTransform(), model.getHeadTransform(), model.getInGuiTransform())), Attributes.DEFAULT_BAKED_FORMAT);
return new IFlexibleBakedModel.Wrapper(bakeModel(model, state.apply(this), uvLocked.contains(location)), Attributes.DEFAULT_BAKED_FORMAT);
}
public IModelState getDefaultState()
{
return ModelRotation.X0_Y0;
}
}
// Weighted models can contain multiple copies of 1 model with different rotations - this is to make it work with IModelState (different copies will be different objects).
private static class WeightedPartWrapper implements IModel
{
private final IModel model;
public WeightedPartWrapper(IModel model)
{
this.model = model;
}
public Collection<ResourceLocation> getDependencies()
{
return model.getDependencies();
}
public Collection<ResourceLocation> getTextures()
{
return model.getTextures();
}
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
{
return model.bake(state, format, bakedTextureGetter);
}
public IModelState getDefaultState()
{
return model.getDefaultState();
}
}
private class WeightedRandomModel implements IModel
{
private final List<Variant> variants;
private final List<ResourceLocation> locations = new ArrayList<ResourceLocation>();
private final List<IModel> models = new ArrayList<IModel>();
private final IModelState defaultState;
public WeightedRandomModel(Variants variants)
{
this.variants = variants.getVariants();
ImmutableMap.Builder<IModelPart, TRSRTransformation> builder = ImmutableMap.builder();
for(Variant v : (List<Variant>)variants.getVariants())
{
ResourceLocation loc = v.getModelLocation();
resolveTextures.add(ModelLoaderRegistry.getActualLocation(loc));
locations.add(loc);
IModel model = new WeightedPartWrapper(getModel(loc));
models.add(model);
builder.put(model, new TRSRTransformation(v.getRotation()));
if(v.isUvLocked()) uvLocked.add(ModelLoaderRegistry.getActualLocation(loc));
}
defaultState = new MapModelState(builder.build());
}
public Collection<ResourceLocation> getDependencies()
{
return ImmutableList.copyOf(locations);
}
public Collection<ResourceLocation> getTextures()
{
/*ImmutableSet.Builder<ResourceLocation> builder = ImmutableSet.builder();
for(ResourceLocation loc : locations)
{
builder.addAll(getModel(loc).getTextures());
}
return builder.build();*/
return Collections.emptyList();
}
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
{
if(!Attributes.moreSpecific(format, Attributes.DEFAULT_BAKED_FORMAT))
{
throw new IllegalArgumentException("can't bake vanilla weighted models to the format that doesn't fit into the default one: " + format);
}
if(variants.size() == 1)
{
Variant v = variants.get(0);
IModel model = models.get(0);
return model.bake(state.apply(model), format, bakedTextureGetter);
}
WeightedBakedModel.Builder builder = new WeightedBakedModel.Builder();
for(int i = 0; i < variants.size(); i++)
{
IModel model = models.get(i);
builder.add(model.bake(state.apply(model), format, bakedTextureGetter), variants.get(i).getWeight());
}
return new IFlexibleBakedModel.Wrapper(builder.build(), Attributes.DEFAULT_BAKED_FORMAT);
}
public IModelState getDefaultState()
{
return defaultState;
}
}
private boolean isBuiltinModel(ModelBlock model)
{
return model == MODEL_GENERATED || model == MODEL_COMPASS || model == MODEL_CLOCK || model == MODEL_ENTITY;
}
public IModel getMissingModel()
{
return getModel(new ResourceLocation(MODEL_MISSING.getResourceDomain(), MODEL_MISSING.getResourcePath()));
}
static enum VanillaLoader implements ICustomModelLoader
{
instance;
private ModelLoader loader;
void setLoader(ModelLoader loader)
{
this.loader = loader;
}
ModelLoader getLoader()
{
return loader;
}
public void onResourceManagerReload(IResourceManager resourceManager)
{
// do nothing, cause loader will store the reference to the resourceManager
}
public boolean accepts(ResourceLocation modelLocation)
{
return true;
}
public IModel loadModel(ResourceLocation modelLocation)
{
try
{
return loader.new VanillaModelWrapper(modelLocation, loader.loadModel(modelLocation));
}
catch(IOException e)
{
FMLLog.log(Level.ERROR, e, "Exception loading model %s with vanilla loader, skipping", modelLocation);
return loader.getMissingModel();
}
}
}
}
@@ -0,0 +1,112 @@
package net.minecraftforge.client.model;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ModelLoader.VanillaLoader;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.logging.log4j.Level;
/*
* Central hub for custom model loaders.
*/
public class ModelLoaderRegistry
{
private static final Set<ICustomModelLoader> loaders = new HashSet<ICustomModelLoader>();
private static final Map<ResourceLocation, IModel> cache = new HashMap<ResourceLocation, IModel>();
/*
* Makes system aware of your loader.
*/
public static void registerLoader(ICustomModelLoader loader)
{
loaders.add(loader);
((IReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).registerReloadListener(new IResourceManagerReloadListener()
{
public void onResourceManagerReload(IResourceManager manager)
{
for(ICustomModelLoader loader : loaders) loader.onResourceManagerReload(manager);
}
});
}
public static boolean loaded(ResourceLocation location)
{
return cache.containsKey(location);
}
public static ResourceLocation getActualLocation(ResourceLocation location)
{
if(location.getResourcePath().startsWith("builtin/")) return location;
return new ResourceLocation(location.getResourceDomain(), "models/" + location.getResourcePath());
}
public static IModel getModel(ResourceLocation location)
{
ResourceLocation actual = getActualLocation(location);
if(cache.containsKey(location)) return cache.get(location);
ICustomModelLoader accepted = null;
for(ICustomModelLoader loader : loaders)
{
try
{
if(loader.accepts(actual))
{
if(accepted != null)
{
FMLLog.severe("2 loaders (%s and %s) want to load the same model %s", accepted, loader, location);
throw new IllegalStateException("2 loaders want to load the same model");
}
accepted = loader;
}
}
catch(Exception e)
{
FMLLog.log(Level.ERROR, e, "Exception checking if model %s can be loaded with loader %s, skipping", location, loader);
}
}
// no custom loaders found, try vanilla one
if(accepted == null)
{
if(VanillaLoader.instance.accepts(actual)) accepted = VanillaLoader.instance;
}
IModel model;
if(accepted == null)
{
FMLLog.severe("no suitable loader found for the model %s, skipping", location);
model = getMissingModel();
}
else try
{
model = accepted.loadModel(actual);
}
catch(Exception e)
{
FMLLog.log(Level.ERROR, e, "Exception loading model %s with loader %s, skipping", location, accepted);
model = getMissingModel();
}
cache.put(location, model);
return model;
}
public static IModel getMissingModel()
{
return ModelLoader.VanillaLoader.instance.getLoader().getMissingModel();
}
public static void clearModelCache()
{
cache.clear();
}
}
@@ -0,0 +1,445 @@
package net.minecraftforge.client.model;
import javax.vecmath.Matrix3f;
import javax.vecmath.Matrix4f;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4f;
import net.minecraft.client.renderer.block.model.ItemTransformVec3f;
import net.minecraft.client.resources.model.ModelRotation;
import net.minecraft.util.EnumFacing;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
/*
* Interpolation-friendly affine transformation.
* If created with matrix, should successfully decompose it to a composition
* of easily interpolatable transformations (translation, first rotation, scale
* (with generally speaking different factors for each axis) and second rotation.
* If the inpit matrix is a composition of translation, rotation and scale (in
* any order), then the interpolation of the derived primitive transformations
* should result in the same transformation as the interpolation of the originals.
* Decomposition happens lazily (and is hopefully fast enough), so performance
* should be comparable to using Matrix4f directly.
* Immutable.
*/
public class TRSRTransformation implements IModelState, ITransformation
{
private final Matrix4f matrix;
private boolean full;
private Vector3f translation;
private Quat4f leftRot;
private Vector3f scale;
private Quat4f rightRot;
public TRSRTransformation(Matrix4f matrix)
{
this.matrix = matrix;
}
public TRSRTransformation(Vector3f translation, Quat4f leftRot, Vector3f scale, Quat4f rightRot)
{
this.matrix = mul(translation, leftRot, scale, rightRot);
this.translation = translation != null ? translation : new Vector3f();
this.leftRot = leftRot != null ? leftRot : new Quat4f(0, 0, 0, 1);
this.scale = scale != null ? scale : new Vector3f(1, 1, 1);
this.rightRot = rightRot!= null ? rightRot : new Quat4f(0, 0, 0, 1);
full = true;
}
public TRSRTransformation(ItemTransformVec3f transform)
{
this(transform.translation, quatFromYXZ(transform.rotation), transform.scale, null);
}
public TRSRTransformation(ModelRotation rotation)
{
this(new Matrix4f(rotation.getMatrix4d()));
}
private static final TRSRTransformation identity;
static
{
Matrix4f m = new Matrix4f();
m.setIdentity();
identity = new TRSRTransformation(m);
identity.getLeftRot();
}
public static TRSRTransformation identity()
{
return identity;
}
public TRSRTransformation compose(TRSRTransformation b)
{
Matrix4f m = getMatrix();
m.mul(b.getMatrix());
return new TRSRTransformation(m);
}
private void genCheck()
{
if(!full)
{
Pair<Matrix3f, Vector3f> pair = toAffine(matrix);
Triple<Quat4f, Vector3f, Quat4f> triple = svdDecompose(pair.getLeft());
this.translation = pair.getRight();
this.leftRot = triple.getLeft();
this.scale = triple.getMiddle();
this.rightRot = triple.getRight();
full = true;
}
}
public static Quat4f quatFromYXZ(Vector3f yxz)
{
return quatFromYXZ(yxz.y, yxz.x, yxz.z);
}
public static Quat4f quatFromYXZ(float y, float x, float z)
{
Quat4f ret = new Quat4f(0, 0, 0, 1), t = new Quat4f();
t.set(0, (float)Math.sin(y/2), 0, (float)Math.cos(y/2));
ret.mul(t);
t.set((float)Math.sin(x/2), 0, 0, (float)Math.cos(x/2));
ret.mul(t);
t.set(0, 0, (float)Math.sin(z/2), (float)Math.cos(z/2));
ret.mul(t);
return ret;
}
public static Vector3f toYXZ(Quat4f q)
{
float w2 = q.w * q.w;
float x2 = q.x * q.x;
float y2 = q.y * q.y;
float z2 = q.z * q.z;
float l = w2 + x2 + y2 + z2;
float sx = 2 * q.y * q.z - 2 * q.w * q.x;
float x = (float)Math.asin(sx / l);
if(Math.abs(sx) > .999f * l)
{
return new Vector3f(
2 * (float)Math.atan2(q.y, q.w),
x,
0
);
}
return new Vector3f(
(float)Math.atan2(2 * q.x * q.z + 2 * q.y * q.w, w2 - x2 - y2 + z2),
x,
(float)Math.atan2(2 * q.x * q.y + 2 * q.w * q.z, w2 - x2 + y2 - z2)
);
}
public static Matrix4f mul(Vector3f translation, Quat4f leftRot, Vector3f scale, Quat4f rightRot)
{
Matrix4f res = new Matrix4f(), t = new Matrix4f();
res.setIdentity();
if(translation != null) res.setTranslation(translation);
if(leftRot != null)
{
t.set(leftRot);
res.mul(t);
}
if(scale != null)
{
t.setIdentity();
t.m00 = scale.x;
t.m11 = scale.y;
t.m22 = scale.z;
res.mul(t);
}
if(rightRot != null)
{
t.set(rightRot);
res.mul(t);
}
return res;
}
/*
* Performs SVD decomposition of m, accumulating reflection in the scale (U and V are pure rotations).
*/
public static Triple<Quat4f, Vector3f, Quat4f> svdDecompose(Matrix3f m)
{
// determine V by doing 5 steps of Jacobi iteration on MT * M
Quat4f u = new Quat4f(0, 0, 0, 1), v = new Quat4f(0, 0, 0, 1), qt = new Quat4f();
Matrix3f b = new Matrix3f(m), t = new Matrix3f();
t.transpose(m);
b.mul(t, b);
for(int i = 0; i < 5; i++) v.mul(stepJacobi(b));
v.normalize();
t.set(v);
b.set(m);
b.mul(t);
sortSingularValues(b, v);
Pair<Float, Float> p;
float ul = 1f;
p = qrGivensQuat(b.m00, b.m10);
qt.set(0, 0, p.getLeft(), p.getRight());
u.mul(qt);
t.setIdentity();
t.m00 = qt.w * qt.w - qt.z * qt.z;
t.m11 = t.m00;
t.m10 = -2 * qt.z * qt.w;
t.m01 = -t.m10;
t.m22 = qt.w * qt.w + qt.z * qt.z;
ul *= t.m22;
b.mul(t, b);
p = qrGivensQuat(b.m00, b.m20);
qt.set(0, -p.getLeft(), 0, p.getRight());
u.mul(qt);
t.setIdentity();
t.m00 = qt.w * qt.w - qt.y * qt.y;
t.m22 = t.m00;
t.m20 = 2 * qt.y * qt.w;
t.m02 = -t.m20;
t.m11 = qt.w * qt.w + qt.y * qt.y;
ul *= t.m11;
b.mul(t, b);
p = qrGivensQuat(b.m11, b.m21);
qt.set(p.getLeft(), 0, 0, p.getRight());
u.mul(qt);
t.setIdentity();
t.m11 = qt.w * qt.w - qt.x * qt.x;
t.m22 = t.m11;
t.m21 = -2 * qt.x * qt.w;
t.m12 = -t.m21;
t.m00 = qt.w * qt.w + qt.x * qt.x;
ul *= t.m00;
b.mul(t, b);
ul = 1f / ul;
u.scale((float)Math.sqrt(ul));
Vector3f s = new Vector3f(b.m00 * ul, b.m11 * ul, b.m22 * ul);
return Triple.of(u, s, v);
}
private static float rsqrt(float f)
{
float f2 = .5f * f;
int i = Float.floatToIntBits(f);
i = 0x5f3759df - (i >> 1);
f = Float.intBitsToFloat(i);
f *= 1.5f - f2 * f * f;
return f;
}
private static final float eps = 1e-7f;
private static final float g = 3f + 2f * (float)Math.sqrt(2);
private static final float cs = (float)Math.cos(Math.PI / 8);
private static final float ss = (float)Math.sin(Math.PI / 8);
private static final float sq2 = 1f / (float)Math.sqrt(2);
private static Pair<Float, Float> approxGivensQuat(float a11, float a12, float a22)
{
float ch = 2f * (a11 - a22);
float sh = a12;
boolean b = g * sh * sh < ch * ch;
float w = rsqrt(sh * sh + ch * ch);
ch = b ? w * ch : cs;
sh = b ? w * sh : ss;
return Pair.of(sh, ch);
}
private static final void swapNeg(Matrix3f m, int i, int j)
{
float[] t = new float[3];
m.getColumn(j, t);
for(int k = 0; k < 3; k++)
{
m.setElement(k, j, -m.getElement(k, i));
}
m.setColumn(i, t);
}
private static void sortSingularValues(Matrix3f b, Quat4f v)
{
float p0 = b.m00 * b.m00 + b.m10 * b.m10 + b.m20 * b.m20;
float p1 = b.m01 * b.m01 + b.m11 * b.m11 + b.m21 * b.m21;
float p2 = b.m02 * b.m02 + b.m12 * b.m12 + b.m22 * b.m22;
Quat4f t = new Quat4f();
if(p0 < p1)
{
swapNeg(b, 0, 1);
t.set(0, 0, sq2, sq2);
v.mul(t);
float f = p0;
p0 = p1;
p1 = f;
}
if(p0 < p2)
{
swapNeg(b, 0, 2);
t.set(0, sq2, 0, sq2);
v.mul(t);
float f = p0;
p0 = p2;
p2 = f;
}
if(p1 < p2)
{
swapNeg(b, 1, 2);
t.set(sq2, 0, 0, sq2);
v.mul(t);
}
}
private static Pair<Float, Float> qrGivensQuat(float a1, float a2)
{
float p = (float)Math.sqrt(a1 * a1 + a2 * a2);
float sh = p > eps ? a2 : 0;
float ch = Math.abs(a1) + Math.max(p, eps);
if(a1 < 0)
{
float f = sh;
sh = ch;
ch = f;
}
//float w = 1.f / (float)Math.sqrt(ch * ch + sh * sh);
float w = rsqrt(ch * ch + sh * sh);
ch *= w;
sh *= w;
return Pair.of(sh, ch);
}
private static Quat4f stepJacobi(Matrix3f m)
{
Matrix3f t = new Matrix3f();
Quat4f qt = new Quat4f(), ret = new Quat4f(0, 0, 0, 1);
Pair<Float, Float> p;
// 01
p = approxGivensQuat(m.m00, .5f * (m.m01 + m.m10), m.m11);
qt.set(0, 0, p.getLeft(), p.getRight());
//qt.normalize();
ret.mul(qt);
//t.set(qt);
t.setIdentity();
t.m00 = qt.w * qt.w - qt.z * qt.z;
t.m11 = t.m00;
t.m10 = 2 * qt.z * qt.w;
t.m01 = -t.m10;
t.m22 = qt.w * qt.w + qt.z * qt.z;
m.mul(m, t);
t.transpose();
m.mul(t, m);
// 02
p = approxGivensQuat(m.m00, .5f * (m.m02 + m.m20), m.m22);
qt.set(0, -p.getLeft(), 0, p.getRight());
//qt.normalize();
ret.mul(qt);
//t.set(qt);
t.setIdentity();
t.m00 = qt.w * qt.w - qt.y * qt.y;
t.m22 = t.m00;
t.m20 = -2 * qt.y * qt.w;
t.m02 = -t.m20;
t.m11 = qt.w * qt.w + qt.y * qt.y;
m.mul(m, t);
t.transpose();
m.mul(t, m);
// 12
p = approxGivensQuat(m.m11, .5f * (m.m12 + m.m21), m.m22);
qt.set(p.getLeft(), 0, 0, p.getRight());
//qt.normalize();
ret.mul(qt);
//t.set(qt);
t.setIdentity();
t.m11 = qt.w * qt.w - qt.x * qt.x;
t.m22 = t.m11;
t.m21 = 2 * qt.x * qt.w;
t.m12 = -t.m21;
t.m00 = qt.w * qt.w + qt.x * qt.x;
m.mul(m, t);
t.transpose();
m.mul(t, m);
return ret;
}
/*
* Divides m by m33, sets last row to (0, 0, 0, 1), extracts linear and translation parts
*/
public static Pair<Matrix3f, Vector3f> toAffine(Matrix4f m)
{
m.mul(1.f / m.m33);
Vector3f trans = new Vector3f(m.m03, m.m13, m.m23);
Matrix3f linear = new Matrix3f(m.m00, m.m01, m.m02, m.m10, m.m11, m.m12, m.m20, m.m21, m.m22);
return Pair.of(linear, trans);
}
/*
* Don't use this if you don't need to, conversion is lossy (second rotation component is lost).
*/
public ItemTransformVec3f toItemTransform()
{
return new ItemTransformVec3f(getTranslation(), toYXZ(getLeftRot()), getScale());
}
public Matrix4f getMatrix()
{
return (Matrix4f)matrix.clone();
}
public Vector3f getTranslation()
{
genCheck();
return (Vector3f)translation.clone();
}
public Quat4f getLeftRot()
{
genCheck();
return (Quat4f)leftRot.clone();
}
public Vector3f getScale()
{
genCheck();
return (Vector3f)scale.clone();
}
public Quat4f getRightRot()
{
genCheck();
return (Quat4f)rightRot.clone();
}
public TRSRTransformation apply(IModelPart part)
{
return this;
}
public EnumFacing rotate(EnumFacing facing)
{
return rotate(matrix, facing);
}
public static EnumFacing rotate(Matrix4f matrix, EnumFacing facing)
{
Vector4f vec = new Vector4f(facing.getDirectionVec().getX(), facing.getDirectionVec().getY(), facing.getDirectionVec().getZ(), 1);
matrix.transform(vec);
return EnumFacing.getFacingFromVector(vec.x / vec.w, vec.y / vec.w, vec.z / vec.w);
}
public int rotate(EnumFacing facing, int vertexIndex)
{
// FIXME check if this is good enough
return vertexIndex;
}
}
@@ -0,0 +1,601 @@
package net.minecraftforge.client.model.b3d;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.vecmath.Matrix4f;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.client.resources.IResource;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.Attributes;
import net.minecraftforge.client.model.ICustomModelLoader;
import net.minecraftforge.client.model.IFlexibleBakedModel;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.IModelPart;
import net.minecraftforge.client.model.IModelState;
import net.minecraftforge.client.model.ISmartBlockModel;
import net.minecraftforge.client.model.ISmartItemModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.model.TRSRTransformation;
import net.minecraftforge.client.model.b3d.B3DModel.Animation;
import net.minecraftforge.client.model.b3d.B3DModel.Bone;
import net.minecraftforge.client.model.b3d.B3DModel.Face;
import net.minecraftforge.client.model.b3d.B3DModel.IKind;
import net.minecraftforge.client.model.b3d.B3DModel.Key;
import net.minecraftforge.client.model.b3d.B3DModel.Mesh;
import net.minecraftforge.client.model.b3d.B3DModel.Node;
import net.minecraftforge.client.model.b3d.B3DModel.Texture;
import net.minecraftforge.client.model.b3d.B3DModel.Vertex;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.IUnlistedProperty;
import net.minecraftforge.fml.common.FMLLog;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.logging.log4j.Level;
import org.lwjgl.BufferUtils;
import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
/*
* Loader for Blitz3D models.
* To enable for your mod call instance.addDomain(modid).
* If you need more control over accepted resources - extend the class, and register a new instance with ModelLoaderRegistry.
*/
public class B3DLoader implements ICustomModelLoader
{
public static final B3DLoader instance = new B3DLoader();
private IResourceManager manager;
private final Set<String> enabledDomains = new HashSet<String>();
private final Map<ResourceLocation, B3DModel> cache = new HashMap<ResourceLocation, B3DModel>();
public B3DLoader()
{
ModelLoaderRegistry.registerLoader(this);
}
public void addDomain(String domain)
{
enabledDomains.add(domain.toLowerCase());
}
public void onResourceManagerReload(IResourceManager manager)
{
this.manager = manager;
cache.clear();
}
public boolean accepts(ResourceLocation modelLocation)
{
return enabledDomains.contains(modelLocation.getResourceDomain()) && modelLocation.getResourcePath().endsWith(".b3d");
}
@SuppressWarnings("unchecked")
public IModel loadModel(ResourceLocation modelLocation)
{
ResourceLocation file = new ResourceLocation(modelLocation.getResourceDomain(), modelLocation.getResourcePath());
if(!cache.containsKey(file))
{
try
{
IResource resource = null;
try
{
resource = manager.getResource(file);
}
catch(FileNotFoundException e)
{
if(modelLocation.getResourcePath().startsWith("models/block/"))
resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/item/" + file.getResourcePath().substring("models/block/".length())));
else if(modelLocation.getResourcePath().startsWith("models/item/"))
resource = manager.getResource(new ResourceLocation(file.getResourceDomain(), "models/block/" + file.getResourcePath().substring("models/item/".length())));
else throw e;
}
B3DModel.Parser parser = new B3DModel.Parser(resource.getInputStream());
B3DModel model = parser.parse();
cache.put(modelLocation, model);
}
catch(IOException e)
{
FMLLog.log(Level.ERROR, e, "Exception loading model %s with B3D loader, skipping", modelLocation);
cache.put(modelLocation, null);
}
}
B3DModel model = cache.get(file);
if(model == null) return ModelLoaderRegistry.getMissingModel();
if(modelLocation instanceof B3DMeshLocation)
{
String mesh = ((B3DMeshLocation)modelLocation).getMesh();
if(!model.getMeshes().containsKey(mesh))
{
FMLLog.severe("No mesh named %s in model %s, skipping", mesh, modelLocation);
return ModelLoaderRegistry.getMissingModel();
}
return new Wrapper(modelLocation, model.getTextures(), model.getMeshes().get(mesh));
}
if(!(model.getRoot().getKind() instanceof Mesh))
{
FMLLog.severe("No root mesh in model %s and no mesh name in location, skipping", modelLocation);
return ModelLoaderRegistry.getMissingModel();
}
return new Wrapper(modelLocation, model.getTextures(), (Node<Mesh>)model.getRoot());
}
public static class B3DMeshLocation extends ResourceLocation
{
public final String mesh;
public B3DMeshLocation(String domain, String path, String mesh)
{
super(domain, path);
this.mesh = mesh;
}
public String getMesh()
{
return mesh;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((mesh == null) ? 0 : mesh.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (!super.equals(obj)) return false;
if (getClass() != obj.getClass()) return false;
B3DMeshLocation other = (B3DMeshLocation) obj;
if (mesh == null)
{
if (other.mesh != null) return false;
}
else if (!mesh.equals(other.mesh)) return false;
return true;
}
}
public static class B3DState implements IModelState
{
private final Animation animation;
private final int frame;
public B3DState(Animation animation, int frame)
{
this.animation = animation;
this.frame = frame;
}
public Animation getAnimation()
{
return animation;
}
public int getFrame()
{
return frame;
}
public TRSRTransformation apply(IModelPart part)
{
if(!(part instanceof PartWrapper<?>))
{
throw new IllegalArgumentException("B3DState can only be applied to b3d models");
}
return getNodeMatrix(((PartWrapper<?>)part).getNode());
}
private static LoadingCache<Triple<Animation, Node<?>, Integer>, TRSRTransformation> cache = CacheBuilder.newBuilder()
.maximumSize(16384)
.expireAfterAccess(2, TimeUnit.MINUTES)
.build(new CacheLoader<Triple<Animation, Node<?>, Integer>, TRSRTransformation>()
{
public TRSRTransformation load(Triple<Animation, Node<?>, Integer> key) throws Exception
{
return getNodeMatrix(key.getLeft(), key.getMiddle(), key.getRight());
}
});
public TRSRTransformation getNodeMatrix(Node<?> node)
{
return cache.getUnchecked(Triple.<Animation, Node<?>, Integer>of(animation, node, frame));
}
public static TRSRTransformation getNodeMatrix(Animation animation, Node<?> node, int frame)
{
TRSRTransformation ret = TRSRTransformation.identity();
Key key = null;
if(animation != null) key = animation.getKeys().get(frame, node);
else if(key == null && node.getAnimation() != null && node.getAnimation() != animation) key = node.getAnimation().getKeys().get(frame, node);
if(key == null)
{
FMLLog.severe("invalid key index: " + frame);
}
else
{
ret = ret.compose(new TRSRTransformation(key.getPos(), key.getRot(), key.getScale(), null));
Matrix4f rm = new TRSRTransformation(node.getPos(), node.getRot(), node.getScale(), null).getMatrix();
rm.invert();
ret = ret.compose(new TRSRTransformation(rm));
}
return ret;
}
}
public static enum B3DFrameProperty implements IUnlistedProperty<B3DState>
{
instance;
public String getName()
{
return "B3DFrame";
}
public boolean isValid(B3DState value)
{
return value instanceof B3DState;
}
public Class<B3DState> getType()
{
return B3DState.class;
}
public String valueToString(B3DState value)
{
return value.toString();
}
}
public static class PartWrapper<K extends IKind<K>> implements IModelPart
{
private final Node<K> node;
public static <K extends IKind<K>> PartWrapper<K> create(Node<K> node)
{
return new PartWrapper<K>(node);
}
public PartWrapper(Node<K> node)
{
this.node = node;
}
public Node<K> getNode()
{
return node;
}
}
public static class Wrapper extends PartWrapper<Mesh> implements IModel
{
private final ResourceLocation location;
private final ImmutableMap<String, ResourceLocation> textures;
public Wrapper(ResourceLocation location, List<Texture> textures, B3DModel.Node<Mesh> mesh)
{
this(location, buildTextures(location, textures), mesh);
}
public Wrapper(ResourceLocation location, ImmutableMap<String, ResourceLocation> textures, B3DModel.Node<Mesh> mesh)
{
super(mesh);
this.location = location;
this.textures = textures;
}
private static ImmutableMap<String, ResourceLocation> buildTextures(ResourceLocation location, List<Texture> textures)
{
ImmutableMap.Builder<String, ResourceLocation> builder = ImmutableMap.builder();
for(Texture t : textures)
{
String path = t.getPath();
if(path.endsWith(".png")) path = path.substring(0, path.length() - ".png".length());
builder.put(t.getPath(), new ResourceLocation(location.getResourceDomain(), path));
}
return builder.build();
}
public Collection<ResourceLocation> getDependencies()
{
// no dependencies for in-file models
// FIXME maybe add child meshes
return Collections.emptyList();
}
public Collection<ResourceLocation> getTextures()
{
return textures.values();
}
public IFlexibleBakedModel bake(IModelState state, VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter)
{
ImmutableMap.Builder<String, TextureAtlasSprite> builder = ImmutableMap.builder();
for(String path : textures.keySet())
{
builder.put(path, bakedTextureGetter.apply(textures.get(path)));
}
builder.put("missingno", bakedTextureGetter.apply(new ResourceLocation("missingno")));
return new BakedWrapper(this, state, format, builder.build());
}
public B3DState getDefaultState()
{
return new B3DState(getNode().getAnimation(), 1);
}
public ResourceLocation getLocation()
{
return location;
}
public ImmutableMap<String, ResourceLocation> getTextureMap()
{
return textures;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((location == null) ? 0 : location.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Wrapper other = (Wrapper) obj;
if (location == null)
{
if (other.location != null) return false;
}
else if (!location.equals(other.location)) return false;
return true;
}
}
private static class BakedWrapper implements IFlexibleBakedModel, ISmartBlockModel, ISmartItemModel
{
private final B3DLoader.Wrapper model;
private final IModelState state;
private final VertexFormat format;
private final ImmutableMap<String, TextureAtlasSprite> textures;
private final ByteBuffer buf;
private ImmutableList<BakedQuad> quads;
private static final int BYTES_IN_INT = Integer.SIZE / Byte.SIZE;
private static final int VERTICES_IN_QUAD = 4;
public BakedWrapper(B3DLoader.Wrapper model, IModelState state, VertexFormat format, ImmutableMap<String, TextureAtlasSprite> textures)
{
this.model = model;
this.state = state;
this.format = format;
this.textures = textures;
buf = BufferUtils.createByteBuffer(VERTICES_IN_QUAD * format.getNextOffset());
}
public List<BakedQuad> getFaceQuads(EnumFacing side)
{
return Collections.emptyList();
}
@SuppressWarnings("unchecked")
public List<BakedQuad> getGeneralQuads()
{
if(quads == null)
{
Node<Mesh> mesh = model.getNode();
ImmutableList.Builder<BakedQuad> builder = ImmutableList.builder();
for(Node<?> child : mesh.getNodes().values())
{
if(child.getKind() instanceof Mesh)
{
Node<Mesh> childMesh = (Node<Mesh>)child;
builder.addAll(new BakedWrapper(new B3DLoader.Wrapper(model.getLocation(), model.getTextureMap(), childMesh), state, format, textures).getGeneralQuads());
}
}
Multimap<Vertex, Pair<Float, Node<Bone>>> weightMap = mesh.getKind().getWeightMap();
Collection<Face> faces = mesh.getKind().getFaces();
faces = mesh.getKind().bake(new Function<Node<?>, Matrix4f>()
{
// gets transformation in global space
public Matrix4f apply(Node<?> node)
{
TRSRTransformation ret = TRSRTransformation.identity(), pm = null;
if(node.getParent() != null) pm = new TRSRTransformation(apply(node.getParent()));
if(pm != null)
{
ret = ret.compose(pm);
}
ret = ret.compose(state.apply(PartWrapper.create(node)));
return ret.getMatrix();
}
});
for(Face f : faces)
{
buf.clear();
List<Texture> textures = f.getBrush().getTextures();
TextureAtlasSprite sprite;
if(textures.isEmpty()) sprite = this.textures.get("missingno");
else sprite = this.textures.get(textures.get(0).getPath());
putVertexData(f.getV1(), sprite);
putVertexData(f.getV2(), sprite);
putVertexData(f.getV3(), sprite);
putVertexData(f.getV3(), sprite);
buf.flip();
int[] data = new int[VERTICES_IN_QUAD * format.getNextOffset() / BYTES_IN_INT];
buf.asIntBuffer().get(data);
builder.add(new BakedQuad(data, -1, EnumFacing.getFacingFromVector(f.getNormal().x, f.getNormal().y, f.getNormal().z)));
}
quads = builder.build();
}
return quads;
}
private void put(VertexFormatElement e, Number... ns)
{
Attributes.put(buf, e, true, 0, ns);
}
@SuppressWarnings("unchecked")
private final void putVertexData(Vertex v, TextureAtlasSprite sprite)
{
// TODO handle everything not handled (texture transformations, bones, transformations, normals, e.t.c)
int oldPos = buf.position();
Number[] ns = new Number[16];
for(int i = 0; i < ns.length; i++) ns[i] = 0f;
for(VertexFormatElement e : (List<VertexFormatElement>)format.getElements())
{
switch(e.getUsage())
{
case POSITION:
put(e, v.getPos().x, v.getPos().y, v.getPos().z, 1);
break;
case COLOR:
if(v.getColor() != null)
{
put(e, v.getColor().x, v.getColor().y, v.getColor().z, v.getColor().w);
}
else
{
put(e, 1, 1, 1, 0);
}
break;
case UV:
// TODO handle more brushes
if(e.getIndex() < v.getTexCoords().length)
{
put(e,
sprite.getInterpolatedU(v.getTexCoords()[0].x * 16),
sprite.getInterpolatedV(v.getTexCoords()[0].y * 16),
0,
1
);
}
else
{
put(e, 0, 0, 0, 1);
}
break;
case NORMAL:
// TODO
put(e, 0, 1, 0, 1);
break;
case GENERIC:
// TODO
put(e, 0, 0, 0, 1);
break;
default:
break;
}
}
buf.position(oldPos + format.getNextOffset());
}
public boolean isAmbientOcclusion()
{
return true;
}
public boolean isGui3d()
{
return true;
}
public boolean isBuiltInRenderer()
{
return false;
}
public TextureAtlasSprite getTexture()
{
// FIXME somehow specify particle texture in the model
return textures.values().asList().get(0);
}
public ItemCameraTransforms getItemCameraTransforms()
{
return ItemCameraTransforms.DEFAULT;
}
@Override
public BakedWrapper handleBlockState(IBlockState state)
{
if(state instanceof IExtendedBlockState)
{
IExtendedBlockState exState = (IExtendedBlockState)state;
if(exState.getUnlistedNames().contains(B3DFrameProperty.instance))
{
B3DState s = (B3DState)exState.getValue(B3DFrameProperty.instance);
if(s != null)
{
return getCachedModel(s.getFrame());
}
}
}
return this;
}
private final Map<Integer, BakedWrapper> cache = new HashMap<Integer, BakedWrapper>();
public BakedWrapper getCachedModel(int frame)
{
if(!cache.containsKey(frame))
{
cache.put(frame, new BakedWrapper(model, new B3DState(model.getNode().getAnimation(), frame), format, textures));
}
return cache.get(frame);
}
public VertexFormat getFormat()
{
return format;
}
public BakedWrapper handleItemState(ItemStack stack)
{
// TODO specify how to get B3DState from ItemStack
return this;
}
}
}
File diff suppressed because it is too large. Load diff
@@ -1,84 +0,0 @@
package net.minecraftforge.client.model.obj;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.Vec3;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class Face
{
public Vertex[] vertices;
public Vertex[] vertexNormals;
public Vertex faceNormal;
public TextureCoordinate[] textureCoordinates;
@SideOnly(Side.CLIENT)
public void addFaceForRender(Tessellator tessellator)
{
addFaceForRender(tessellator, 0.0005F);
}
@SideOnly(Side.CLIENT)
public void addFaceForRender(Tessellator tessellator, float textureOffset)
{
if (faceNormal == null)
{
faceNormal = this.calculateFaceNormal();
}
tessellator.setNormal(faceNormal.x, faceNormal.y, faceNormal.z);
float averageU = 0F;
float averageV = 0F;
if ((textureCoordinates != null) && (textureCoordinates.length > 0))
{
for (int i = 0; i < textureCoordinates.length; ++i)
{
averageU += textureCoordinates[i].u;
averageV += textureCoordinates[i].v;
}
averageU = averageU / textureCoordinates.length;
averageV = averageV / textureCoordinates.length;
}
float offsetU, offsetV;
for (int i = 0; i < vertices.length; ++i)
{
if ((textureCoordinates != null) && (textureCoordinates.length > 0))
{
offsetU = textureOffset;
offsetV = textureOffset;
if (textureCoordinates[i].u > averageU)
{
offsetU = -offsetU;
}
if (textureCoordinates[i].v > averageV)
{
offsetV = -offsetV;
}
tessellator.addVertexWithUV(vertices[i].x, vertices[i].y, vertices[i].z, textureCoordinates[i].u + offsetU, textureCoordinates[i].v + offsetV);
}
else
{
tessellator.addVertex(vertices[i].x, vertices[i].y, vertices[i].z);
}
}
}
public Vertex calculateFaceNormal()
{
Vec3 v1 = Vec3.createVectorHelper(vertices[1].x - vertices[0].x, vertices[1].y - vertices[0].y, vertices[1].z - vertices[0].z);
Vec3 v2 = Vec3.createVectorHelper(vertices[2].x - vertices[0].x, vertices[2].y - vertices[0].y, vertices[2].z - vertices[0].z);
Vec3 normalVector = null;
normalVector = v1.crossProduct(v2).normalize();
return new Vertex((float) normalVector.xCoord, (float) normalVector.yCoord, (float) normalVector.zCoord);
}
}
@@ -1,54 +0,0 @@
package net.minecraftforge.client.model.obj;
import java.util.ArrayList;
import net.minecraft.client.renderer.Tessellator;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class GroupObject
{
public String name;
public ArrayList<Face> faces = new ArrayList<Face>();
public int glDrawingMode;
public GroupObject()
{
this("");
}
public GroupObject(String name)
{
this(name, -1);
}
public GroupObject(String name, int glDrawingMode)
{
this.name = name;
this.glDrawingMode = glDrawingMode;
}
@SideOnly(Side.CLIENT)
public void render()
{
if (faces.size() > 0)
{
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawing(glDrawingMode);
render(tessellator);
tessellator.draw();
}
}
@SideOnly(Side.CLIENT)
public void render(Tessellator tessellator)
{
if (faces.size() > 0)
{
for (Face face : faces)
{
face.addFaceForRender(tessellator);
}
}
}
}
@@ -1,29 +0,0 @@
package net.minecraftforge.client.model.obj;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelCustom;
import net.minecraftforge.client.model.IModelCustomLoader;
import net.minecraftforge.client.model.ModelFormatException;
public class ObjModelLoader implements IModelCustomLoader
{
@Override
public String getType()
{
return "OBJ model";
}
private static final String[] types = { "obj" };
@Override
public String[] getSuffixes()
{
return types;
}
@Override
public IModelCustom loadInstance(ResourceLocation resource) throws ModelFormatException
{
return new WavefrontObject(resource);
}
}
@@ -1,21 +0,0 @@
package net.minecraftforge.client.model.obj;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class TextureCoordinate
{
public float u, v, w;
public TextureCoordinate(float u, float v)
{
this(u, v, 0F);
}
public TextureCoordinate(float u, float v, float w)
{
this.u = u;
this.v = v;
this.w = w;
}
}
@@ -1,21 +0,0 @@
package net.minecraftforge.client.model.obj;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class Vertex
{
public float x, y, z;
public Vertex(float x, float y)
{
this(x, y, 0F);
}
public Vertex(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
@@ -1,660 +0,0 @@
package net.minecraftforge.client.model.obj;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.resources.IResource;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelCustom;
import net.minecraftforge.client.model.ModelFormatException;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
/**
* Wavefront Object importer
* Based heavily off of the specifications found at http://en.wikipedia.org/wiki/Wavefront_.obj_file
*/
public class WavefrontObject implements IModelCustom
{
private static Pattern vertexPattern = Pattern.compile("(v( (\\-){0,1}\\d+\\.\\d+){3,4} *\\n)|(v( (\\-){0,1}\\d+\\.\\d+){3,4} *$)");
private static Pattern vertexNormalPattern = Pattern.compile("(vn( (\\-){0,1}\\d+\\.\\d+){3,4} *\\n)|(vn( (\\-){0,1}\\d+\\.\\d+){3,4} *$)");
private static Pattern textureCoordinatePattern = Pattern.compile("(vt( (\\-){0,1}\\d+\\.\\d+){2,3} *\\n)|(vt( (\\-){0,1}\\d+\\.\\d+){2,3} *$)");
private static Pattern face_V_VT_VN_Pattern = Pattern.compile("(f( \\d+/\\d+/\\d+){3,4} *\\n)|(f( \\d+/\\d+/\\d+){3,4} *$)");
private static Pattern face_V_VT_Pattern = Pattern.compile("(f( \\d+/\\d+){3,4} *\\n)|(f( \\d+/\\d+){3,4} *$)");
private static Pattern face_V_VN_Pattern = Pattern.compile("(f( \\d+//\\d+){3,4} *\\n)|(f( \\d+//\\d+){3,4} *$)");
private static Pattern face_V_Pattern = Pattern.compile("(f( \\d+){3,4} *\\n)|(f( \\d+){3,4} *$)");
private static Pattern groupObjectPattern = Pattern.compile("([go]( [\\w\\d\\.]+) *\\n)|([go]( [\\w\\d\\.]+) *$)");
private static Matcher vertexMatcher, vertexNormalMatcher, textureCoordinateMatcher;
private static Matcher face_V_VT_VN_Matcher, face_V_VT_Matcher, face_V_VN_Matcher, face_V_Matcher;
private static Matcher groupObjectMatcher;
public ArrayList<Vertex> vertices = new ArrayList<Vertex>();
public ArrayList<Vertex> vertexNormals = new ArrayList<Vertex>();
public ArrayList<TextureCoordinate> textureCoordinates = new ArrayList<TextureCoordinate>();
public ArrayList<GroupObject> groupObjects = new ArrayList<GroupObject>();
private GroupObject currentGroupObject;
private String fileName;
public WavefrontObject(ResourceLocation resource) throws ModelFormatException
{
this.fileName = resource.toString();
try
{
IResource res = Minecraft.getMinecraft().getResourceManager().getResource(resource);
loadObjModel(res.getInputStream());
}
catch (IOException e)
{
throw new ModelFormatException("IO Exception reading model format", e);
}
}
public WavefrontObject(String filename, InputStream inputStream) throws ModelFormatException
{
this.fileName = filename;
loadObjModel(inputStream);
}
private void loadObjModel(InputStream inputStream) throws ModelFormatException
{
BufferedReader reader = null;
String currentLine = null;
int lineCount = 0;
try
{
reader = new BufferedReader(new InputStreamReader(inputStream));
while ((currentLine = reader.readLine()) != null)
{
lineCount++;
currentLine = currentLine.replaceAll("\\s+", " ").trim();
if (currentLine.startsWith("#") || currentLine.length() == 0)
{
continue;
}
else if (currentLine.startsWith("v "))
{
Vertex vertex = parseVertex(currentLine, lineCount);
if (vertex != null)
{
vertices.add(vertex);
}
}
else if (currentLine.startsWith("vn "))
{
Vertex vertex = parseVertexNormal(currentLine, lineCount);
if (vertex != null)
{
vertexNormals.add(vertex);
}
}
else if (currentLine.startsWith("vt "))
{
TextureCoordinate textureCoordinate = parseTextureCoordinate(currentLine, lineCount);
if (textureCoordinate != null)
{
textureCoordinates.add(textureCoordinate);
}
}
else if (currentLine.startsWith("f "))
{
if (currentGroupObject == null)
{
currentGroupObject = new GroupObject("Default");
}
Face face = parseFace(currentLine, lineCount);
if (face != null)
{
currentGroupObject.faces.add(face);
}
}
else if (currentLine.startsWith("g ") | currentLine.startsWith("o "))
{
GroupObject group = parseGroupObject(currentLine, lineCount);
if (group != null)
{
if (currentGroupObject != null)
{
groupObjects.add(currentGroupObject);
}
}
currentGroupObject = group;
}
}
groupObjects.add(currentGroupObject);
}
catch (IOException e)
{
throw new ModelFormatException("IO Exception reading model format", e);
}
finally
{
try
{
reader.close();
}
catch (IOException e)
{
// hush
}
try
{
inputStream.close();
}
catch (IOException e)
{
// hush
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void renderAll()
{
Tessellator tessellator = Tessellator.instance;
if (currentGroupObject != null)
{
tessellator.startDrawing(currentGroupObject.glDrawingMode);
}
else
{
tessellator.startDrawing(GL11.GL_TRIANGLES);
}
tessellateAll(tessellator);
tessellator.draw();
}
@SideOnly(Side.CLIENT)
public void tessellateAll(Tessellator tessellator)
{
for (GroupObject groupObject : groupObjects)
{
groupObject.render(tessellator);
}
}
@Override
@SideOnly(Side.CLIENT)
public void renderOnly(String... groupNames)
{
for (GroupObject groupObject : groupObjects)
{
for (String groupName : groupNames)
{
if (groupName.equalsIgnoreCase(groupObject.name))
{
groupObject.render();
}
}
}
}
@SideOnly(Side.CLIENT)
public void tessellateOnly(Tessellator tessellator, String... groupNames) {
for (GroupObject groupObject : groupObjects)
{
for (String groupName : groupNames)
{
if (groupName.equalsIgnoreCase(groupObject.name))
{
groupObject.render(tessellator);
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void renderPart(String partName)
{
for (GroupObject groupObject : groupObjects)
{
if (partName.equalsIgnoreCase(groupObject.name))
{
groupObject.render();
}
}
}
@SideOnly(Side.CLIENT)
public void tessellatePart(Tessellator tessellator, String partName) {
for (GroupObject groupObject : groupObjects)
{
if (partName.equalsIgnoreCase(groupObject.name))
{
groupObject.render(tessellator);
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void renderAllExcept(String... excludedGroupNames)
{
for (GroupObject groupObject : groupObjects)
{
boolean skipPart=false;
for (String excludedGroupName : excludedGroupNames)
{
if (excludedGroupName.equalsIgnoreCase(groupObject.name))
{
skipPart=true;
}
}
if(!skipPart)
{
groupObject.render();
}
}
}
@SideOnly(Side.CLIENT)
public void tessellateAllExcept(Tessellator tessellator, String... excludedGroupNames)
{
boolean exclude;
for (GroupObject groupObject : groupObjects)
{
exclude=false;
for (String excludedGroupName : excludedGroupNames)
{
if (excludedGroupName.equalsIgnoreCase(groupObject.name))
{
exclude=true;
}
}
if(!exclude)
{
groupObject.render(tessellator);
}
}
}
private Vertex parseVertex(String line, int lineCount) throws ModelFormatException
{
Vertex vertex = null;
if (isValidVertexLine(line))
{
line = line.substring(line.indexOf(" ") + 1);
String[] tokens = line.split(" ");
try
{
if (tokens.length == 2)
{
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]));
}
else if (tokens.length == 3)
{
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]));
}
}
catch (NumberFormatException e)
{
throw new ModelFormatException(String.format("Number formatting error at line %d",lineCount), e);
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
}
return vertex;
}
private Vertex parseVertexNormal(String line, int lineCount) throws ModelFormatException
{
Vertex vertexNormal = null;
if (isValidVertexNormalLine(line))
{
line = line.substring(line.indexOf(" ") + 1);
String[] tokens = line.split(" ");
try
{
if (tokens.length == 3)
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]));
}
catch (NumberFormatException e)
{
throw new ModelFormatException(String.format("Number formatting error at line %d",lineCount), e);
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
}
return vertexNormal;
}
private TextureCoordinate parseTextureCoordinate(String line, int lineCount) throws ModelFormatException
{
TextureCoordinate textureCoordinate = null;
if (isValidTextureCoordinateLine(line))
{
line = line.substring(line.indexOf(" ") + 1);
String[] tokens = line.split(" ");
try
{
if (tokens.length == 2)
return new TextureCoordinate(Float.parseFloat(tokens[0]), 1 - Float.parseFloat(tokens[1]));
else if (tokens.length == 3)
return new TextureCoordinate(Float.parseFloat(tokens[0]), 1 - Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]));
}
catch (NumberFormatException e)
{
throw new ModelFormatException(String.format("Number formatting error at line %d",lineCount), e);
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
}
return textureCoordinate;
}
private Face parseFace(String line, int lineCount) throws ModelFormatException
{
Face face = null;
if (isValidFaceLine(line))
{
face = new Face();
String trimmedLine = line.substring(line.indexOf(" ") + 1);
String[] tokens = trimmedLine.split(" ");
String[] subTokens = null;
if (tokens.length == 3)
{
if (currentGroupObject.glDrawingMode == -1)
{
currentGroupObject.glDrawingMode = GL11.GL_TRIANGLES;
}
else if (currentGroupObject.glDrawingMode != GL11.GL_TRIANGLES)
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Invalid number of points for face (expected 4, found " + tokens.length + ")");
}
}
else if (tokens.length == 4)
{
if (currentGroupObject.glDrawingMode == -1)
{
currentGroupObject.glDrawingMode = GL11.GL_QUADS;
}
else if (currentGroupObject.glDrawingMode != GL11.GL_QUADS)
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Invalid number of points for face (expected 3, found " + tokens.length + ")");
}
}
// f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ...
if (isValidFace_V_VT_VN_Line(line))
{
face.vertices = new Vertex[tokens.length];
face.textureCoordinates = new TextureCoordinate[tokens.length];
face.vertexNormals = new Vertex[tokens.length];
for (int i = 0; i < tokens.length; ++i)
{
subTokens = tokens[i].split("/");
face.vertices[i] = vertices.get(Integer.parseInt(subTokens[0]) - 1);
face.textureCoordinates[i] = textureCoordinates.get(Integer.parseInt(subTokens[1]) - 1);
face.vertexNormals[i] = vertexNormals.get(Integer.parseInt(subTokens[2]) - 1);
}
face.faceNormal = face.calculateFaceNormal();
}
// f v1/vt1 v2/vt2 v3/vt3 ...
else if (isValidFace_V_VT_Line(line))
{
face.vertices = new Vertex[tokens.length];
face.textureCoordinates = new TextureCoordinate[tokens.length];
for (int i = 0; i < tokens.length; ++i)
{
subTokens = tokens[i].split("/");
face.vertices[i] = vertices.get(Integer.parseInt(subTokens[0]) - 1);
face.textureCoordinates[i] = textureCoordinates.get(Integer.parseInt(subTokens[1]) - 1);
}
face.faceNormal = face.calculateFaceNormal();
}
// f v1//vn1 v2//vn2 v3//vn3 ...
else if (isValidFace_V_VN_Line(line))
{
face.vertices = new Vertex[tokens.length];
face.vertexNormals = new Vertex[tokens.length];
for (int i = 0; i < tokens.length; ++i)
{
subTokens = tokens[i].split("//");
face.vertices[i] = vertices.get(Integer.parseInt(subTokens[0]) - 1);
face.vertexNormals[i] = vertexNormals.get(Integer.parseInt(subTokens[1]) - 1);
}
face.faceNormal = face.calculateFaceNormal();
}
// f v1 v2 v3 ...
else if (isValidFace_V_Line(line))
{
face.vertices = new Vertex[tokens.length];
for (int i = 0; i < tokens.length; ++i)
{
face.vertices[i] = vertices.get(Integer.parseInt(tokens[i]) - 1);
}
face.faceNormal = face.calculateFaceNormal();
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
}
return face;
}
private GroupObject parseGroupObject(String line, int lineCount) throws ModelFormatException
{
GroupObject group = null;
if (isValidGroupObjectLine(line))
{
String trimmedLine = line.substring(line.indexOf(" ") + 1);
if (trimmedLine.length() > 0)
{
group = new GroupObject(trimmedLine);
}
}
else
{
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
}
return group;
}
/***
* Verifies that the given line from the model file is a valid vertex
* @param line the line being validated
* @return true if the line is a valid vertex, false otherwise
*/
private static boolean isValidVertexLine(String line)
{
if (vertexMatcher != null)
{
vertexMatcher.reset();
}
vertexMatcher = vertexPattern.matcher(line);
return vertexMatcher.matches();
}
/***
* Verifies that the given line from the model file is a valid vertex normal
* @param line the line being validated
* @return true if the line is a valid vertex normal, false otherwise
*/
private static boolean isValidVertexNormalLine(String line)
{
if (vertexNormalMatcher != null)
{
vertexNormalMatcher.reset();
}
vertexNormalMatcher = vertexNormalPattern.matcher(line);
return vertexNormalMatcher.matches();
}
/***
* Verifies that the given line from the model file is a valid texture coordinate
* @param line the line being validated
* @return true if the line is a valid texture coordinate, false otherwise
*/
private static boolean isValidTextureCoordinateLine(String line)
{
if (textureCoordinateMatcher != null)
{
textureCoordinateMatcher.reset();
}
textureCoordinateMatcher = textureCoordinatePattern.matcher(line);
return textureCoordinateMatcher.matches();
}
/***
* Verifies that the given line from the model file is a valid face that is described by vertices, texture coordinates, and vertex normals
* @param line the line being validated
* @return true if the line is a valid face that matches the format "f v1/vt1/vn1 ..." (with a minimum of 3 points in the face, and a maximum of 4), false otherwise
*/
private static boolean isValidFace_V_VT_VN_Line(String line)
{
if (face_V_VT_VN_Matcher != null)
{
face_V_VT_VN_Matcher.reset();
}
face_V_VT_VN_Matcher = face_V_VT_VN_Pattern.matcher(line);
return face_V_VT_VN_Matcher.matches();
}
/***
* Verifies that the given line from the model file is a valid face that is described by vertices and texture coordinates
* @param line the line being validated
* @return true if the line is a valid face that matches the format "f v1/vt1 ..." (with a minimum of 3 points in the face, and a maximum of 4), false otherwise
*/
private static boolean isValidFace_V_VT_Line(String line)
{
if (face_V_VT_Matcher != null)
{
face_V_VT_Matcher.reset();
}
face_V_VT_Matcher = face_V_VT_Pattern.matcher(line);
return face_V_VT_Matcher.matches();
}
/***
* Verifies that the given line from the model file is a valid face that is described by vertices and vertex normals
* @param line the line being validated
* @return true if the line is a valid face that matches the format "f v1//vn1 ..." (with a minimum of 3 points in the face, and a maximum of 4), false otherwise
*/
private static boolean isValidFace_V_VN_Line(String line)
{
if (face_V_VN_Matcher != null)
{
face_V_VN_Matcher.reset();
}
face_V_VN_Matcher = face_V_VN_Pattern.matcher(line);
return face_V_VN_Matcher.matches();
}
/***
* Verifies that the given line from the model file is a valid face that is described by only vertices
* @param line the line being validated
* @return true if the line is a valid face that matches the format "f v1 ..." (with a minimum of 3 points in the face, and a maximum of 4), false otherwise
*/
private static boolean isValidFace_V_Line(String line)
{
if (face_V_Matcher != null)
{
face_V_Matcher.reset();
}
face_V_Matcher = face_V_Pattern.matcher(line);
return face_V_Matcher.matches();
}
/***
* Verifies that the given line from the model file is a valid face of any of the possible face formats
* @param line the line being validated
* @return true if the line is a valid face that matches any of the valid face formats, false otherwise
*/
private static boolean isValidFaceLine(String line)
{
return isValidFace_V_VT_VN_Line(line) || isValidFace_V_VT_Line(line) || isValidFace_V_VN_Line(line) || isValidFace_V_Line(line);
}
/***
* Verifies that the given line from the model file is a valid group (or object)
* @param line the line being validated
* @return true if the line is a valid group (or object), false otherwise
*/
private static boolean isValidGroupObjectLine(String line)
{
if (groupObjectMatcher != null)
{
groupObjectMatcher.reset();
}
groupObjectMatcher = groupObjectPattern.matcher(line);
return groupObjectMatcher.matches();
}
@Override
public String getType()
{
return "obj";
}
}
@@ -1,365 +0,0 @@
package net.minecraftforge.client.model.techne;
import java.awt.Dimension;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.client.resources.IResource;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelCustom;
import net.minecraftforge.client.model.ModelFormatException;
/**
* Techne model importer, based on iChun's Hats importer
*/
@SideOnly(Side.CLIENT)
public class TechneModel extends ModelBase implements IModelCustom {
public static final List<String> cubeTypes = Arrays.asList(
"d9e621f7-957f-4b77-b1ae-20dcd0da7751",
"de81aa14-bd60-4228-8d8d-5238bcd3caaa"
);
private String fileName;
private Map<String, byte[]> zipContents = new HashMap<String, byte[]>();
private Map<String, ModelRenderer> parts = new LinkedHashMap<String, ModelRenderer>();
private String texture = null;
private Dimension textureDims = null;
private int textureName;
private boolean textureNameSet = false;
public TechneModel(ResourceLocation resource) throws ModelFormatException
{
this.fileName = resource.toString();
try
{
IResource res = Minecraft.getMinecraft().getResourceManager().getResource(resource);
loadTechneModel(res.getInputStream());
}
catch (IOException e)
{
throw new ModelFormatException("IO Exception reading model format", e);
}
}
private void loadTechneModel(InputStream stream) throws ModelFormatException
{
try
{
ZipInputStream zipInput = new ZipInputStream(stream);
ZipEntry entry;
while ((entry = zipInput.getNextEntry()) != null)
{
byte[] data = new byte[(int) entry.getSize()];
// For some reason, using read(byte[]) makes reading stall upon reaching a 0x1E byte
int i = 0;
while (zipInput.available() > 0 && i < data.length)
{
data[i++] = (byte)zipInput.read();
}
zipContents.put(entry.getName(), data);
}
byte[] modelXml = zipContents.get("model.xml");
if (modelXml == null)
{
throw new ModelFormatException("Model " + fileName + " contains no model.xml file");
}
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(new ByteArrayInputStream(modelXml));
NodeList nodeListTechne = document.getElementsByTagName("Techne");
if (nodeListTechne.getLength() < 1)
{
throw new ModelFormatException("Model " + fileName + " contains no Techne tag");
}
NodeList nodeListModel = document.getElementsByTagName("Model");
if (nodeListModel.getLength() < 1)
{
throw new ModelFormatException("Model " + fileName + " contains no Model tag");
}
NamedNodeMap modelAttributes = nodeListModel.item(0).getAttributes();
if (modelAttributes == null)
{
throw new ModelFormatException("Model " + fileName + " contains a Model tag with no attributes");
}
Node modelTexture = modelAttributes.getNamedItem("texture");
if (modelTexture != null)
{
texture = modelTexture.getTextContent();
}
NodeList textureDim = document.getElementsByTagName("TextureSize");
if (textureDim.getLength() > 0)
{
try
{
String[] tmp = textureDim.item(0).getTextContent().split(",");
if (tmp.length == 2)
{
this.textureDims = new Dimension(Integer.parseInt(tmp[0]), Integer.parseInt(tmp[1]));
}
}
catch (NumberFormatException e)
{
throw new ModelFormatException("Model " + fileName + " contains a TextureSize tag with invalid data");
}
}
NodeList shapes = document.getElementsByTagName("Shape");
for (int i = 0; i < shapes.getLength(); i++)
{
Node shape = shapes.item(i);
NamedNodeMap shapeAttributes = shape.getAttributes();
if (shapeAttributes == null)
{
throw new ModelFormatException("Shape #" + (i + 1) + " in " + fileName + " has no attributes");
}
Node name = shapeAttributes.getNamedItem("name");
String shapeName = null;
if (name != null)
{
shapeName = name.getNodeValue();
}
if (shapeName == null)
{
shapeName = "Shape #" + (i + 1);
}
String shapeType = null;
Node type = shapeAttributes.getNamedItem("type");
if (type != null)
{
shapeType = type.getNodeValue();
}
if (shapeType != null && !cubeTypes.contains(shapeType))
{
FMLLog.warning("Model shape [" + shapeName + "] in " + fileName + " is not a cube, ignoring");
continue;
}
try
{
boolean mirrored = false;
String[] offset = new String[3];
String[] position = new String[3];
String[] rotation = new String[3];
String[] size = new String[3];
String[] textureOffset = new String[2];
NodeList shapeChildren = shape.getChildNodes();
for (int j = 0; j < shapeChildren.getLength(); j++)
{
Node shapeChild = shapeChildren.item(j);
String shapeChildName = shapeChild.getNodeName();
String shapeChildValue = shapeChild.getTextContent();
if (shapeChildValue != null)
{
shapeChildValue = shapeChildValue.trim();
if (shapeChildName.equals("IsMirrored"))
{
mirrored = !shapeChildValue.equals("False");
}
else if (shapeChildName.equals("Offset"))
{
offset = shapeChildValue.split(",");
}
else if (shapeChildName.equals("Position"))
{
position = shapeChildValue.split(",");
}
else if (shapeChildName.equals("Rotation"))
{
rotation = shapeChildValue.split(",");
}
else if (shapeChildName.equals("Size"))
{
size = shapeChildValue.split(",");
}
else if (shapeChildName.equals("TextureOffset"))
{
textureOffset = shapeChildValue.split(",");
}
}
}
// That's what the ModelBase subclassing is needed for
ModelRenderer cube = new ModelRenderer(this, Integer.parseInt(textureOffset[0]), Integer.parseInt(textureOffset[1]));
cube.mirror = mirrored;
cube.addBox(Float.parseFloat(offset[0]), Float.parseFloat(offset[1]), Float.parseFloat(offset[2]), Integer.parseInt(size[0]), Integer.parseInt(size[1]), Integer.parseInt(size[2]));
cube.setRotationPoint(Float.parseFloat(position[0]), Float.parseFloat(position[1]) - 23.4F, Float.parseFloat(position[2]));
cube.rotateAngleX = (float)Math.toRadians(Float.parseFloat(rotation[0]));
cube.rotateAngleY = (float)Math.toRadians(Float.parseFloat(rotation[1]));
cube.rotateAngleZ = (float)Math.toRadians(Float.parseFloat(rotation[2]));
if (this.textureDims != null)
{
cube.setTextureSize((int)textureDims.getWidth(), (int)textureDims.getHeight());
}
parts.put(shapeName, cube);
}
catch (NumberFormatException e)
{
FMLLog.warning("Model shape [" + shapeName + "] in " + fileName + " contains malformed integers within its data, ignoring");
e.printStackTrace();
}
}
}
catch (ZipException e)
{
throw new ModelFormatException("Model " + fileName + " is not a valid zip file");
}
catch (IOException e)
{
throw new ModelFormatException("Model " + fileName + " could not be read", e);
}
catch (ParserConfigurationException e)
{
// hush
}
catch (SAXException e)
{
throw new ModelFormatException("Model " + fileName + " contains invalid XML", e);
}
}
private void bindTexture()
{
/* TODO: Update to 1.6
if (texture != null)
{
if (!textureNameSet)
{
try
{
byte[] textureEntry = zipContents.get(texture);
if (textureEntry == null)
{
throw new ModelFormatException("Model " + fileName + " has no such texture " + texture);
}
BufferedImage image = ImageIO.read(new ByteArrayInputStream(textureEntry));
textureName = Minecraft.getMinecraft().renderEngine.allocateAndSetupTexture(image);
textureNameSet = true;
}
catch (ZipException e)
{
throw new ModelFormatException("Model " + fileName + " is not a valid zip file");
}
catch (IOException e)
{
throw new ModelFormatException("Texture for model " + fileName + " could not be read", e);
}
}
if (textureNameSet)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureName);
Minecraft.getMinecraft().renderEngine.resetBoundTexture();
}
}
*/
}
@Override
public String getType()
{
return "tcn";
}
@Override
public void renderAll()
{
bindTexture();
for (ModelRenderer part : parts.values())
{
part.renderWithRotation(1.0F);
}
}
@Override
public void renderPart(String partName)
{
ModelRenderer part = parts.get(partName);
if (part != null)
{
bindTexture();
part.renderWithRotation(1.0F);
}
}
@Override
public void renderOnly(String... groupNames)
{
bindTexture();
for (ModelRenderer part : parts.values())
{
for (String groupName : groupNames)
{
if (groupName.equalsIgnoreCase(part.boxName))
{
part.render(1.0f);
}
}
}
}
@Override
public void renderAllExcept(String... excludedGroupNames)
{
for (ModelRenderer part : parts.values())
{
boolean skipPart=false;
for (String excludedGroupName : excludedGroupNames)
{
if (excludedGroupName.equalsIgnoreCase(part.boxName))
{
skipPart=true;
}
}
if(!skipPart)
{
part.render(1.0f);
}
}
}
}
@@ -1,29 +0,0 @@
package net.minecraftforge.client.model.techne;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.IModelCustom;
import net.minecraftforge.client.model.IModelCustomLoader;
import net.minecraftforge.client.model.ModelFormatException;
public class TechneModelLoader implements IModelCustomLoader {
@Override
public String getType()
{
return "Techne model";
}
private static final String[] types = { "tcn" };
@Override
public String[] getSuffixes()
{
return types;
}
@Override
public IModelCustom loadInstance(ResourceLocation resource) throws ModelFormatException
{
return new TechneModel(resource);
}
}
@@ -2,7 +2,7 @@ package net.minecraftforge.common;
import java.util.*;
import cpw.mods.fml.common.FMLLog;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraft.init.Blocks;
import net.minecraft.world.biome.*;
import net.minecraftforge.common.util.EnumHelper;
@@ -329,9 +329,9 @@ public class BiomeDictionary
}
}
}
else if(biome.heightVariation <= 0.3F && biome.heightVariation >= 0.0F)
else if(biome.maxHeight <= 0.3F && biome.maxHeight >= 0.0F)
{
if(!biome.isHighHumidity() || biome.rootHeight >= 0.0F)
if(!biome.isHighHumidity() || biome.minHeight >= 0.0F)
{
BiomeDictionary.registerBiomeType(biome, PLAINS);
}
@@ -366,14 +366,14 @@ public class BiomeDictionary
BiomeDictionary.registerBiomeType(biome, DENSE);
}
if (biome.isHighHumidity() && biome.rootHeight < 0.0F && (biome.heightVariation <= 0.3F && biome.heightVariation >= 0.0F))
if (biome.isHighHumidity() && biome.minHeight < 0.0F && (biome.maxHeight <= 0.3F && biome.maxHeight >= 0.0F))
{
BiomeDictionary.registerBiomeType(biome, SWAMP);
}
if (biome.rootHeight <= -0.5F)
if (biome.minHeight <= -0.5F)
{
if (biome.heightVariation == 0.0F)
if (biome.maxHeight == 0.0F)
{
BiomeDictionary.registerBiomeType(biome, RIVER);
}
@@ -383,12 +383,12 @@ public class BiomeDictionary
}
}
if (biome.heightVariation >= 0.4F && biome.heightVariation < 1.5F)
if (biome.maxHeight >= 0.4F && biome.maxHeight < 1.5F)
{
BiomeDictionary.registerBiomeType(biome, HILLS);
}
if (biome.heightVariation >= 1.5F)
if (biome.maxHeight >= 1.5F)
{
BiomeDictionary.registerBiomeType(biome, MOUNTAIN);
}
@@ -19,23 +19,11 @@ import net.minecraftforge.common.util.EnumHelper;
public class BiomeManager
{
private static TrackedList<BiomeEntry>[] biomes = setupBiomes();
/*
* These lists should no longer be accessed directly. Instead, use the appropriate add, remove and get methods within this class.
*/
@Deprecated
public static List<BiomeEntry> desertBiomes = biomes[BiomeType.DESERT.ordinal()];
@Deprecated
public static List<BiomeEntry> warmBiomes = biomes[BiomeType.WARM.ordinal()];
@Deprecated
public static List<BiomeEntry> coolBiomes = biomes[BiomeType.COOL.ordinal()];
@Deprecated
public static List<BiomeEntry> icyBiomes = biomes[BiomeType.ICY.ordinal()];
private static boolean isModded = false;
public static List<BiomeGenBase> oceanBiomes = new ArrayList<BiomeGenBase>();
public static ArrayList<BiomeGenBase> strongHoldBiomes = new ArrayList<BiomeGenBase>();
public static ArrayList<BiomeGenBase> strongHoldBiomesBlackList = new ArrayList<BiomeGenBase>();
@@ -45,19 +33,19 @@ public class BiomeManager
oceanBiomes.add(BiomeGenBase.deepOcean);
oceanBiomes.add(BiomeGenBase.frozenOcean);
}
private static TrackedList<BiomeEntry>[] setupBiomes()
{
TrackedList<BiomeEntry>[] currentBiomes = new TrackedList[BiomeType.values().length];
List list = new ArrayList();
list.add(new BiomeEntry(BiomeGenBase.forest, 10));
list.add(new BiomeEntry(BiomeGenBase.roofedForest, 10));
list.add(new BiomeEntry(BiomeGenBase.extremeHills, 10));
list.add(new BiomeEntry(BiomeGenBase.plains, 10));
list.add(new BiomeEntry(BiomeGenBase.birchForest, 10));
list.add(new BiomeEntry(BiomeGenBase.swampland, 10));
currentBiomes[BiomeType.WARM.ordinal()] = new TrackedList(list);
list.clear();
@@ -65,7 +53,7 @@ public class BiomeManager
list.add(new BiomeEntry(BiomeGenBase.extremeHills, 10));
list.add(new BiomeEntry(BiomeGenBase.taiga, 10));
list.add(new BiomeEntry(BiomeGenBase.plains, 10));
currentBiomes[BiomeType.COOL.ordinal()] = new TrackedList(list);
list.clear();
@@ -74,9 +62,9 @@ public class BiomeManager
currentBiomes[BiomeType.ICY.ordinal()] = new TrackedList(list);
list.clear();
currentBiomes[BiomeType.DESERT.ordinal()] = new TrackedList(list);
return currentBiomes;
}
@@ -133,67 +121,67 @@ public class BiomeManager
WorldChunkManager.allowedBiomes.remove(biome);
}
}
public static void addBiome(BiomeType type, BiomeEntry entry)
{
isModded = true;
int idx = type.ordinal();
List<BiomeEntry> list = idx > biomes.length ? null : biomes[idx];
if (list != null) list.add(entry);
}
public static void removeBiome(BiomeType type, BiomeEntry entry)
{
isModded = true;
int idx = type.ordinal();
List<BiomeEntry> list = idx > biomes.length ? null : biomes[idx];
if (list != null && list.contains(entry))
{
list.remove(entry);
}
}
public static ImmutableList<BiomeEntry> getBiomes(BiomeType type)
{
int idx = type.ordinal();
List<BiomeEntry> list = idx > biomes.length ? null : biomes[idx];
return list != null ? ImmutableList.copyOf(list) : null;
}
public static boolean isTypeListModded(BiomeType type)
{
int idx = type.ordinal();
TrackedList<BiomeEntry> list = idx > biomes.length ? null : biomes[idx];
if (list != null) return list.isModded();
return false;
}
public static enum BiomeType
{
DESERT, WARM, COOL, ICY;
public static BiomeType getType(String name)
{
name = name.toUpperCase();
for (BiomeType t : values())
{
if (t.name().equals(name)) return t;
}
BiomeType ret = EnumHelper.addEnum(BiomeType.class, name, BiomeType.class);
if (ret.ordinal() >= biomes.length)
{
biomes = Arrays.copyOf(biomes, ret.ordinal());
}
return ret;
}
}
@@ -201,89 +189,89 @@ public class BiomeManager
public static class BiomeEntry extends WeightedRandom.Item
{
public final BiomeGenBase biome;
public BiomeEntry(BiomeGenBase biome, int weight)
{
super(weight);
this.biome = biome;
}
}
private static class TrackedList<E> extends ArrayList<E>
{
private boolean isModded = false;
public TrackedList(Collection<? extends E> c)
public TrackedList(Collection<? extends E> c)
{
super(c);
}
@Override
public E set(int index, E element)
public E set(int index, E element)
{
isModded = true;
return super.set(index, element);
}
@Override
public boolean add(E e)
public boolean add(E e)
{
isModded = true;
return super.add(e);
}
@Override
public void add(int index, E element)
public void add(int index, E element)
{
isModded = true;
super.add(index, element);
}
@Override
public E remove(int index)
public E remove(int index)
{
isModded = true;
return super.remove(index);
}
@Override
public boolean remove(Object o)
public boolean remove(Object o)
{
isModded = true;
return super.remove(o);
}
@Override
public void clear()
public void clear()
{
isModded = true;
super.clear();
}
@Override
public boolean addAll(Collection<? extends E> c)
public boolean addAll(Collection<? extends E> c)
{
isModded = true;
return super.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c)
public boolean addAll(int index, Collection<? extends E> c)
{
isModded = true;
return super.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c)
public boolean removeAll(Collection<?> c)
{
isModded = true;
return super.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c)
public boolean retainAll(Collection<?> c)
{
isModded = true;
return super.retainAll(c);
@@ -1,7 +1,7 @@
package net.minecraftforge.common;
import java.util.*;
import com.google.common.collect.ImmutableList;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -47,27 +47,23 @@ public class ChestGenHooks
}
hasInit = true;
// This causes the classes static initializers to run
new WorldGenDungeons();
new DesertPyramid();
new JunglePyramid();
new StructureMineshaftPieces();
new StructureOceanMonument();
new StructureStrongholdPieces.ChestCorridor();
new StructureStrongholdPieces.Library();
new StructureStrongholdPieces.RoomCrossing();
new StructureVillagePieces.House2();
WorldServer.fillChestHook();
}
addInfo(MINESHAFT_CORRIDOR, StructureMineshaftPieces.mineshaftChestContents, 3, 7);
addInfo(PYRAMID_DESERT_CHEST, DesertPyramid.itemsToGenerateInTemple, 2, 7);
addInfo(PYRAMID_JUNGLE_CHEST, JunglePyramid.junglePyramidsChestContents, 2, 7);
addInfo(PYRAMID_JUNGLE_DISPENSER, JunglePyramid.junglePyramidsDispenserContents, 2, 2);
addInfo(STRONGHOLD_CORRIDOR, ChestCorridor.strongholdChestContents, 2, 4);
addInfo(STRONGHOLD_LIBRARY, Library.strongholdLibraryChestContents, 1, 5);
addInfo(STRONGHOLD_CROSSING, RoomCrossing.strongholdRoomCrossingChestContents, 1, 5);
addInfo(VILLAGE_BLACKSMITH, House2.villageBlacksmithChestContents, 3, 9);
addInfo(BONUS_CHEST, WorldServer.bonusChestContent, 10, 10);
addInfo(DUNGEON_CHEST, WorldGenDungeons.field_111189_a, 8, 8);
ItemStack book = new ItemStack(Items.enchanted_book, 1, 0);
WeightedRandomChestContent tmp = new WeightedRandomChestContent(book, 1, 1, 1);
getInfo(MINESHAFT_CORRIDOR ).addItem(tmp);
getInfo(PYRAMID_DESERT_CHEST).addItem(tmp);
getInfo(PYRAMID_JUNGLE_CHEST).addItem(tmp);
getInfo(STRONGHOLD_CORRIDOR ).addItem(tmp);
getInfo(STRONGHOLD_LIBRARY ).addItem(new WeightedRandomChestContent(book, 1, 5, 2));
getInfo(STRONGHOLD_CROSSING ).addItem(tmp);
getInfo(DUNGEON_CHEST ).addItem(tmp);
// INTERNAL DO NO USE
public static void init(String category, List items, int min, int max)
{
chestInfo.put(category, new ChestGenHooks(category, (List<WeightedRandomChestContent>)items, min, max));
}
static void addDungeonLoot(ChestGenHooks dungeon, ItemStack item, int weight, int min, int max)
@@ -75,11 +71,6 @@ public class ChestGenHooks
dungeon.addItem(new WeightedRandomChestContent(item, min, max, weight));
}
private static void addInfo(String category, WeightedRandomChestContent[] items, int min, int max)
{
chestInfo.put(category, new ChestGenHooks(category, items, min, max));
}
/**
* Retrieves, or creates the info class for the specified category.
*
@@ -134,7 +125,7 @@ public class ChestGenHooks
}
//shortcut functions, See the non-static versions below
public static WeightedRandomChestContent[] getItems(String category, Random rnd){ return getInfo(category).getItems(rnd); }
public static List<WeightedRandomChestContent> getItems(String category, Random rnd){ return getInfo(category).getItems(rnd); }
public static int getCount(String category, Random rand){ return getInfo(category).getCount(rand); }
public static void addItem(String category, WeightedRandomChestContent item){ getInfo(category).addItem(item); }
public static void removeItem(String category, ItemStack item){ getInfo(category).removeItem(item); }
@@ -150,7 +141,7 @@ public class ChestGenHooks
this.category = category;
}
public ChestGenHooks(String category, WeightedRandomChestContent[] items, int min, int max)
public ChestGenHooks(String category, List<WeightedRandomChestContent> items, int min, int max)
{
this(category);
for (WeightedRandomChestContent item : items)
@@ -195,7 +186,7 @@ public class ChestGenHooks
*
* @return The random objects
*/
public WeightedRandomChestContent[] getItems(Random rnd)
public List<WeightedRandomChestContent> getItems(Random rnd)
{
ArrayList<WeightedRandomChestContent> ret = new ArrayList<WeightedRandomChestContent>();
@@ -213,7 +204,7 @@ public class ChestGenHooks
}
}
return ret.toArray(new WeightedRandomChestContent[ret.size()]);
return ret;
}
/**
@@ -236,8 +227,7 @@ public class ChestGenHooks
*/
public ItemStack getOneItem(Random rand)
{
WeightedRandomChestContent[] items = getItems(rand);
WeightedRandomChestContent item = (WeightedRandomChestContent)WeightedRandom.getRandomItem(rand, items);
WeightedRandomChestContent item = (WeightedRandomChestContent)WeightedRandom.getRandomItem(rand, getItems(rand));
ItemStack[] stacks = ChestGenHooks.generateStacks(rand, item.theItemId, item.theMinimumChanceToGenerateItem, item.theMaximumChanceToGenerateItem);
return (stacks.length > 0 ? stacks[0] : null);
}
@@ -17,8 +17,8 @@ import com.google.common.collect.HashMultiset;
import com.google.common.collect.Lists;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Multiset;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.MinecraftException;
@@ -193,7 +193,7 @@ public class DimensionManager
worlds.put(id, world);
weakWorldMap.put(world, world);
MinecraftServer.getServer().worldTickTimes.put(id, new long[100]);
FMLLog.info("Loading dimension %d (%s) (%s)", id, world.getWorldInfo().getWorldName(), world.func_73046_m());
FMLLog.info("Loading dimension %d (%s) (%s)", id, world.getWorldInfo().getWorldName(), world.getMinecraftServer());
}
else
{
@@ -223,7 +223,8 @@ public class DimensionManager
MinecraftServer.getServer().worldServers = tmp.toArray(new WorldServer[tmp.size()]);
}
public static void initDimension(int dim) {
public static void initDimension(int dim)
{
WorldServer overworld = getWorld(0);
if (overworld == null)
{
@@ -238,11 +239,11 @@ public class DimensionManager
System.err.println("Cannot Hotload Dim: " + e.getMessage());
return; // If a provider hasn't been registered then we can't hotload the dim
}
MinecraftServer mcServer = overworld.func_73046_m();
MinecraftServer mcServer = overworld.getMinecraftServer();
ISaveHandler savehandler = overworld.getSaveHandler();
WorldSettings worldSettings = new WorldSettings(overworld.getWorldInfo());
WorldServer world = (dim == 0 ? overworld : new WorldServerMulti(mcServer, savehandler, overworld.getWorldInfo().getWorldName(), dim, worldSettings, overworld, mcServer.theProfiler));
WorldServer world = (dim == 0 ? overworld : (WorldServer)(new WorldServerMulti(mcServer, savehandler, dim, overworld, mcServer.theProfiler).init()));
world.addWorldAccess(new WorldManager(mcServer, world));
MinecraftForge.EVENT_BUS.post(new WorldEvent.Load(world));
if (!mcServer.isSinglePlayer())
@@ -250,7 +251,7 @@ public class DimensionManager
world.getWorldInfo().setGameType(mcServer.getGameType());
}
mcServer.func_147139_a(mcServer.func_147135_j());
mcServer.setDifficultyForAllWorlds(mcServer.getDifficulty());
}
public static WorldServer getWorld(int id)
@@ -425,4 +426,4 @@ public class DimensionManager
return null;
}
}
}
}
@@ -43,19 +43,19 @@ public class FishingHooks
if (chance < junkChance)
{
return ((WeightedRandomFishable)WeightedRandom.getRandomItem(rand, junk)).func_150708_a(rand);
return ((WeightedRandomFishable)WeightedRandom.getRandomItem(rand, junk)).getItemStack(rand);
}
chance -= junkChance;
if (chance < treasureChance)
{
return ((WeightedRandomFishable)WeightedRandom.getRandomItem(rand, treasure)).func_150708_a(rand);
return ((WeightedRandomFishable)WeightedRandom.getRandomItem(rand, treasure)).getItemStack(rand);
}
chance -= treasureChance;
// this is done in EntityFishHook.func_146033_f. more loot types expected?
{
return ((WeightedRandomFishable)WeightedRandom.getRandomItem(rand, fish)).func_150708_a(rand);
return ((WeightedRandomFishable)WeightedRandom.getRandomItem(rand, fish)).getItemStack(rand);
}
}
@@ -93,15 +93,15 @@ public class FishingHooks
static
{
fish.addAll(EntityFishHook.field_146036_f);
junk.addAll(EntityFishHook.field_146039_d);
treasure.addAll(EntityFishHook.field_146041_e);
fish.addAll(EntityFishHook.FISH);
junk.addAll(EntityFishHook.JUNK);
treasure.addAll(EntityFishHook.TREASURE);
}
public static enum FishableCategory
{
JUNK(StatList.field_151183_A),
TREASURE(StatList.field_151184_B),
JUNK(StatList.junkFishedStat),
TREASURE(StatList.treasureFishedStat),
FISH(StatList.fishCaughtStat);
public final StatBase stat;
@@ -111,4 +111,4 @@ public class FishingHooks
this.stat = stat;
}
}
}
}
@@ -8,14 +8,13 @@ package net.minecraftforge.common;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.logging.log4j.Level;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ArrayListMultimap;
@@ -33,16 +32,16 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.entity.Entity;
import net.minecraft.util.ClassInheritanceMultiMap;
import net.minecraft.util.MathHelper;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
@@ -895,7 +894,7 @@ public class ForgeChunkManager
public static void putDormantChunk(long coords, Chunk chunk)
{
Cache<Long, Chunk> cache = dormantChunkCache.get(chunk.worldObj);
Cache<Long, Chunk> cache = dormantChunkCache.get(chunk.getWorld());
if (cache != null)
{
cache.put(coords, chunk);
@@ -913,11 +912,12 @@ public class ForgeChunkManager
Chunk chunk = cache.getIfPresent(coords);
if (chunk != null)
{
for (List<Entity> eList : (List<Entity>[])chunk.entityLists)
for (ClassInheritanceMultiMap eList : chunk.getEntityLists())
{
for (Entity e: eList)
Iterator<Entity> itr = (Iterator<Entity>)eList.iterator();
while (itr.hasNext())
{
e.resetEntityId();
(itr.next()).resetEntityId();
}
}
}
@@ -1,15 +1,28 @@
package net.minecraftforge.common;
import static net.minecraft.init.Blocks.diamond_block;
import static net.minecraft.init.Blocks.diamond_ore;
import static net.minecraft.init.Blocks.emerald_block;
import static net.minecraft.init.Blocks.emerald_ore;
import static net.minecraft.init.Blocks.gold_block;
import static net.minecraft.init.Blocks.gold_ore;
import static net.minecraft.init.Blocks.lit_redstone_ore;
import static net.minecraft.init.Blocks.redstone_ore;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cpw.mods.fml.common.eventhandler.Event;
import cpw.mods.fml.relauncher.ReflectionHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
@@ -20,6 +33,7 @@ import net.minecraft.init.Items;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ContainerRepair;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemAxe;
@@ -29,6 +43,8 @@ import net.minecraft.item.ItemSpade;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S23PacketBlockChange;
@@ -36,16 +52,22 @@ import net.minecraft.stats.StatList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityNote;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.MovingObjectPosition.MovingObjectType;
import net.minecraft.util.WeightedRandom;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldSettings.GameType;
import net.minecraft.world.gen.feature.WorldGeneratorBonusChest;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.ServerChatEvent;
@@ -58,11 +80,15 @@ import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.event.entity.living.LivingFallEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent;
import net.minecraftforge.event.entity.player.PlayerOpenContainerEvent;
import net.minecraftforge.event.entity.player.AnvilRepairEvent;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
import net.minecraftforge.event.entity.player.PlayerOpenContainerEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.NoteBlockEvent;
import static net.minecraft.init.Blocks.*;
import net.minecraftforge.fluids.IFluidBlock;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
public class ForgeHooks
{
@@ -77,9 +103,9 @@ public class ForgeHooks
}
static final List<SeedEntry> seedList = new ArrayList<SeedEntry>();
public static ItemStack getGrassSeed(World world)
public static ItemStack getGrassSeed(Random rand)
{
SeedEntry entry = (SeedEntry)WeightedRandom.getRandomItem(world.rand, seedList);
SeedEntry entry = (SeedEntry)WeightedRandom.getRandomItem(rand, seedList);
if (entry == null || entry.seed == null)
{
return null;
@@ -90,7 +116,7 @@ public class ForgeHooks
private static boolean toolInit = false;
//static HashSet<List> toolEffectiveness = new HashSet<List>();
public static boolean canHarvestBlock(Block block, EntityPlayer player, int metadata)
public static boolean canHarvestBlock(Block block, EntityPlayer player, IBlockAccess world, BlockPos pos)
{
if (block.getMaterial().isToolNotRequired())
{
@@ -98,7 +124,9 @@ public class ForgeHooks
}
ItemStack stack = player.inventory.getCurrentItem();
String tool = block.getHarvestTool(metadata);
IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos);
String tool = block.getHarvestTool(state);
if (stack == null || tool == null)
{
return player.canHarvestBlock(block);
@@ -110,40 +138,43 @@ public class ForgeHooks
return player.canHarvestBlock(block);
}
return toolLevel >= block.getHarvestLevel(metadata);
return toolLevel >= block.getHarvestLevel(state);
}
public static boolean canToolHarvestBlock(Block block, int metadata, ItemStack stack)
public static boolean canToolHarvestBlock(IBlockAccess world, BlockPos pos, ItemStack stack)
{
String tool = block.getHarvestTool(metadata);
IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos);
String tool = state.getBlock().getHarvestTool(state);
if (stack == null || tool == null) return false;
return stack.getItem().getHarvestLevel(stack, tool) >= block.getHarvestLevel(metadata);
return stack.getItem().getHarvestLevel(stack, tool) >= state.getBlock().getHarvestLevel(state);
}
public static float blockStrength(Block block, EntityPlayer player, World world, int x, int y, int z)
public static float blockStrength(IBlockState state, EntityPlayer player, World world, BlockPos pos)
{
int metadata = world.getBlockMetadata(x, y, z);
float hardness = block.getBlockHardness(world, x, y, z);
float hardness = state.getBlock().getBlockHardness(world, pos);
if (hardness < 0.0F)
{
return 0.0F;
}
if (!canHarvestBlock(block, player, metadata))
if (!canHarvestBlock(state.getBlock(), player, world, pos))
{
return player.getBreakSpeed(block, true, metadata, x, y, z) / hardness / 100F;
return player.getBreakSpeed(state, pos) / hardness / 100F;
}
else
{
return player.getBreakSpeed(block, false, metadata, x, y, z) / hardness / 30F;
return player.getBreakSpeed(state, pos) / hardness / 30F;
}
}
public static boolean isToolEffective(ItemStack stack, Block block, int metadata)
public static boolean isToolEffective(IBlockAccess world, BlockPos pos, ItemStack stack)
{
IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos);
for (String type : stack.getItem().getToolClasses(stack))
{
if (block.isToolEffective(type, metadata))
if (state.getBlock().isToolEffective(type, state))
return true;
}
return false;
@@ -218,20 +249,21 @@ public class ForgeHooks
{
ItemStack result = null;
boolean isCreative = player.capabilities.isCreativeMode;
TileEntity te = null;
if (target.typeOfHit == MovingObjectType.BLOCK)
{
int x = target.blockX;
int y = target.blockY;
int z = target.blockZ;
Block block = world.getBlock(x, y, z);
IBlockState state = world.getBlockState(target.getBlockPos());
if (block.isAir(world, x, y, z))
if (state.getBlock().isAir(world, target.getBlockPos()))
{
return false;
}
result = block.getPickBlock(target, world, x, y, z, player);
if (isCreative && GuiScreen.isCtrlKeyDown())
te = world.getTileEntity(target.getBlockPos());
result = state.getBlock().getPickBlock(target, world, target.getBlockPos());
}
else
{
@@ -248,6 +280,20 @@ public class ForgeHooks
return false;
}
if (te != null)
{
NBTTagCompound nbt = new NBTTagCompound();
te.writeToNBT(nbt);
result.setTagInfo("BlockEntityTag", nbt);
NBTTagCompound display = new NBTTagCompound();
result.setTagInfo("display", display);
NBTTagList lore = new NBTTagList();
display.setTag("Lore", lore);
lore.appendTag(new NBTTagString("(+NBT)"));
}
for (int x = 0; x < 9; x++)
{
ItemStack stack = player.inventory.getStackInSlot(x);
@@ -289,7 +335,7 @@ public class ForgeHooks
public static boolean onLivingAttack(EntityLivingBase entity, DamageSource src, float amount)
{
return MinecraftForge.EVENT_BUS.post(new LivingAttackEvent(entity, src, amount));
return !MinecraftForge.EVENT_BUS.post(new LivingAttackEvent(entity, src, amount));
}
public static float onLivingHurt(EntityLivingBase entity, DamageSource src, float amount)
@@ -303,26 +349,28 @@ public class ForgeHooks
return MinecraftForge.EVENT_BUS.post(new LivingDeathEvent(entity, src));
}
public static boolean onLivingDrops(EntityLivingBase entity, DamageSource source, ArrayList<EntityItem> drops, int lootingLevel, boolean recentlyHit, int specialDropValue)
public static boolean onLivingDrops(EntityLivingBase entity, DamageSource source, ArrayList<EntityItem> drops, int lootingLevel, boolean recentlyHit)
{
return MinecraftForge.EVENT_BUS.post(new LivingDropsEvent(entity, source, drops, lootingLevel, recentlyHit, specialDropValue));
return MinecraftForge.EVENT_BUS.post(new LivingDropsEvent(entity, source, drops, lootingLevel, recentlyHit));
}
public static float onLivingFall(EntityLivingBase entity, float distance)
public static float[] onLivingFall(EntityLivingBase entity, float distance, float damageMultiplier)
{
LivingFallEvent event = new LivingFallEvent(entity, distance);
return (MinecraftForge.EVENT_BUS.post(event) ? 0.0f : event.distance);
LivingFallEvent event = new LivingFallEvent(entity, distance, damageMultiplier);
return (MinecraftForge.EVENT_BUS.post(event) ? null : new float[]{event.distance, event.damageMultiplier});
}
public static boolean isLivingOnLadder(Block block, World world, int x, int y, int z, EntityLivingBase entity)
public static boolean isLivingOnLadder(Block block, World world, BlockPos pos, EntityLivingBase entity)
{
boolean isSpectator = (entity instanceof EntityPlayer && ((EntityPlayer)entity).isSpectator());
if (isSpectator) return false;
if (!ForgeModContainer.fullBoundingBoxLadders)
{
return block != null && block.isLadder(world, x, y, z, entity);
return block != null && block.isLadder(world, pos, entity);
}
else
{
AxisAlignedBB bb = entity.boundingBox;
AxisAlignedBB bb = entity.getEntityBoundingBox();
int mX = MathHelper.floor_double(bb.minX);
int mY = MathHelper.floor_double(bb.minY);
int mZ = MathHelper.floor_double(bb.minZ);
@@ -332,8 +380,8 @@ public class ForgeHooks
{
for (int z2 = mZ; z2 < bb.maxZ; z2++)
{
block = world.getBlock(x2, y2, z2);
if (block != null && block.isLadder(world, x2, y2, z2, entity))
BlockPos tmp = new BlockPos(x2, y2, z2);
if (world.getBlockState(tmp).getBlock().isLadder(world, tmp, entity))
{
return true;
}
@@ -352,7 +400,7 @@ public class ForgeHooks
public static EntityItem onPlayerTossEvent(EntityPlayer player, ItemStack item, boolean includeName)
{
player.captureDrops = true;
EntityItem ret = player.func_146097_a(item, false, includeName);
EntityItem ret = player.dropItem(item, false, includeName);
player.capturedDrops.clear();
player.captureDrops = false;
@@ -371,9 +419,9 @@ public class ForgeHooks
return event.entityItem;
}
public static float getEnchantPower(World world, int x, int y, int z)
public static float getEnchantPower(World world, BlockPos pos)
{
return world.getBlock(x, y, z).getEnchantPowerBonus(world, x, y, z);
return world.getBlockState(pos).getBlock().getEnchantPowerBonus(world, pos);
}
public static ChatComponentTranslation onServerChatEvent(NetHandlerPlayServer net, String raw, ChatComponentTranslation comp)
@@ -386,16 +434,18 @@ public class ForgeHooks
return event.component;
}
static final Pattern URL_PATTERN = Pattern.compile(
// schema ipv4 OR namespace port path ends
// |-----------------| |-------------------------| |----------------------------| |---------| |--| |---------------|
"((?:[a-z0-9]{2,}:\\/\\/)?(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3}|(?:[-\\w_\\.]{1,}\\.[a-z]{2,}?))(?::[0-9]{1,5})?.*?(?=[!\"\u00A7 \n]|$))",
Pattern.CASE_INSENSITIVE);
public static IChatComponent newChatWithLinks(String string)
{
// Includes ipv4 and domain pattern
// Matches an ip (xx.xxx.xx.xxx) or a domain (something.com) with or
// without a protocol or path.
final Pattern URL_PATTERN = Pattern.compile(
// schema ipv4 OR namespace port path ends
// |-----------------| |-------------------------| |----------------------------| |---------| |--| |---------------|
"((?:[a-z0-9]{2,}:\\/\\/)?(?:(?:[0-9]{1,3}\\.){3}[0-9]{1,3}|(?:[-\\w_\\.]{1,}\\.[a-z]{2,}?))(?::[0-9]{1,5})?.*?(?=[!\"\u00A7 \n]|$))",
Pattern.CASE_INSENSITIVE);
IChatComponent ichat = new ChatComponentText("");
Matcher matcher = URL_PATTERN.matcher(string);
int lastEnd = 0;
@@ -437,32 +487,37 @@ public class ForgeHooks
return event.getResult() == Event.Result.DEFAULT ? event.canInteractWith : event.getResult() == Event.Result.ALLOW ? true : false;
}
public static BlockEvent.BreakEvent onBlockBreakEvent(World world, GameType gameType, EntityPlayerMP entityPlayer, int x, int y, int z)
public static int onBlockBreakEvent(World world, GameType gameType, EntityPlayerMP entityPlayer, BlockPos pos)
{
// Logic from tryHarvestBlock for pre-canceling the event
boolean preCancelEvent = false;
if (gameType.isAdventure() && !entityPlayer.isCurrentToolAdventureModeExempt(x, y, z))
{
if (gameType.isCreative() && entityPlayer.getHeldItem() != null && entityPlayer.getHeldItem().getItem() instanceof ItemSword)
preCancelEvent = true;
}
else if (gameType.isCreative() && entityPlayer.getHeldItem() != null && entityPlayer.getHeldItem().getItem() instanceof ItemSword)
if (gameType.isAdventure())
{
preCancelEvent = true;
if (gameType == WorldSettings.GameType.SPECTATOR)
preCancelEvent = true;
if (!entityPlayer.isAllowEdit())
{
ItemStack itemstack = entityPlayer.getCurrentEquippedItem();
if (itemstack == null || !itemstack.canDestroy(world.getBlockState(pos).getBlock()))
preCancelEvent = true;
}
}
// Tell client the block is gone immediately then process events
if (world.getTileEntity(x, y, z) == null)
if (world.getTileEntity(pos) == null)
{
S23PacketBlockChange packet = new S23PacketBlockChange(x, y, z, world);
packet.field_148883_d = Blocks.air;
packet.field_148884_e = 0;
S23PacketBlockChange packet = new S23PacketBlockChange(world, pos);
packet.field_148883_d = Blocks.air.getDefaultState();
entityPlayer.playerNetServerHandler.sendPacket(packet);
}
// Post the block break event
Block block = world.getBlock(x, y, z);
int blockMetadata = world.getBlockMetadata(x, y, z);
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(x, y, z, world, block, blockMetadata, entityPlayer);
IBlockState state = world.getBlockState(pos);
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, state, entityPlayer);
event.setCanceled(preCancelEvent);
MinecraftForge.EVENT_BUS.post(event);
@@ -470,10 +525,10 @@ public class ForgeHooks
if (event.isCanceled())
{
// Let the client know the block still exists
entityPlayer.playerNetServerHandler.sendPacket(new S23PacketBlockChange(x, y, z, world));
entityPlayer.playerNetServerHandler.sendPacket(new S23PacketBlockChange(world, pos));
// Update any tile entity data for this block
TileEntity tileentity = world.getTileEntity(x, y, z);
TileEntity tileentity = world.getTileEntity(pos);
if (tileentity != null)
{
Packet pkt = tileentity.getDescriptionPacket();
@@ -483,10 +538,10 @@ public class ForgeHooks
}
}
}
return event;
return event.isCanceled() ? -1 : event.getExpToDrop();
}
public static boolean onPlaceItemIntoWorld(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ)
public static boolean onPlaceItemIntoWorld(ItemStack itemstack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ)
{
// handle all placement events here
int meta = itemstack.getItemDamage();
@@ -502,7 +557,7 @@ public class ForgeHooks
world.captureBlockSnapshots = true;
}
boolean flag = itemstack.getItem().onItemUse(itemstack, player, world, x, y, z, side, hitX, hitY, hitZ);
boolean flag = itemstack.getItem().onItemUse(itemstack, player, world, pos, side, hitX, hitY, hitZ);
world.captureBlockSnapshots = false;
if (flag)
@@ -516,7 +571,7 @@ public class ForgeHooks
newNBT = (NBTTagCompound)itemstack.getTagCompound().copy();
}
net.minecraftforge.event.world.BlockEvent.PlaceEvent placeEvent = null;
List<net.minecraftforge.common.util.BlockSnapshot> blockSnapshots = (List<net.minecraftforge.common.util.BlockSnapshot>) world.capturedBlockSnapshots.clone();
List<net.minecraftforge.common.util.BlockSnapshot> blockSnapshots = (List<BlockSnapshot>)world.capturedBlockSnapshots.clone();
world.capturedBlockSnapshots.clear();
// make sure to set pre-placement item data for event
@@ -528,11 +583,11 @@ public class ForgeHooks
}
if (blockSnapshots.size() > 1)
{
placeEvent = ForgeEventFactory.onPlayerMultiBlockPlace(player, blockSnapshots, net.minecraftforge.common.util.ForgeDirection.getOrientation(side));
placeEvent = ForgeEventFactory.onPlayerMultiBlockPlace(player, blockSnapshots, side);
}
else if (blockSnapshots.size() == 1)
{
placeEvent = ForgeEventFactory.onPlayerBlockPlace(player, blockSnapshots.get(0), net.minecraftforge.common.util.ForgeDirection.getOrientation(side));
placeEvent = ForgeEventFactory.onPlayerBlockPlace(player, blockSnapshots.get(0), side);
}
if (placeEvent != null && (placeEvent.isCanceled()))
@@ -556,21 +611,17 @@ public class ForgeHooks
itemstack.setTagCompound(newNBT);
}
for (net.minecraftforge.common.util.BlockSnapshot blocksnapshot : blockSnapshots)
for (BlockSnapshot snap : blockSnapshots)
{
int blockX = blocksnapshot.x;
int blockY = blocksnapshot.y;
int blockZ = blocksnapshot.z;
int metadata = world.getBlockMetadata(blockX, blockY, blockZ);
int updateFlag = blocksnapshot.flag;
Block oldBlock = blocksnapshot.replacedBlock;
Block newBlock = world.getBlock(blockX, blockY, blockZ);
if (newBlock != null && !(newBlock.hasTileEntity(metadata))) // Containers get placed automatically
int updateFlag = snap.flag;
IBlockState oldBlock = snap.replacedBlock;
IBlockState newBlock = world.getBlockState(snap.pos);
if (newBlock != null && !(newBlock.getBlock().hasTileEntity(newBlock))) // Containers get placed automatically
{
newBlock.onBlockAdded(world, blockX, blockY, blockZ);
newBlock.getBlock().onBlockAdded(world, snap.pos, newBlock);
}
world.markAndNotifyBlock(blockX, blockY, blockZ, null, oldBlock, newBlock, updateFlag);
world.markAndNotifyBlock(snap.pos, null, oldBlock, newBlock, updateFlag);
}
player.addStat(StatList.objectUseStats[Item.getIdFromItem(itemstack.getItem())], 1);
}
@@ -588,7 +639,7 @@ public class ForgeHooks
outputSlot.setInventorySlotContents(0, e.output);
container.maximumCost = e.cost;
container.stackSizeToBeUsedInRepair = e.materialCost;
container.materialCost = e.materialCost;
return false;
}
@@ -601,7 +652,7 @@ public class ForgeHooks
public static boolean onNoteChange(TileEntityNote te, byte old)
{
NoteBlockEvent.Change e = new NoteBlockEvent.Change(te.getWorldObj(), te.xCoord, te.yCoord, te.zCoord, te.getBlockMetadata(), old, te.note);
NoteBlockEvent.Change e = new NoteBlockEvent.Change(te.getWorld(), te.getPos(), te.getWorld().getBlockState(te.getPos()), old, te.note);
if (MinecraftForge.EVENT_BUS.post(e))
{
te.note = old;
@@ -610,4 +661,90 @@ public class ForgeHooks
te.note = (byte)e.getVanillaNoteId();
return true;
}
/**
* Default implementation of IRecipe.func_179532_b {getRemainingItems} because
* this is just copy pasted over a lot of recipes.
*
* Another use case for java 8 but sadly we can't use it!
*
* @param inv Crafting inventory
* @return Crafting inventory contents after the recipe.
*/
public static ItemStack[] defaultRecipeGetRemainingItems(InventoryCrafting inv)
{
ItemStack[] ret = new ItemStack[inv.getSizeInventory()];
for (int i = 0; i < ret.length; i++)
{
ret[i] = getContainerItem(inv.getStackInSlot(i));
}
return ret;
}
private static ThreadLocal<EntityPlayer> craftingPlayer = new ThreadLocal<EntityPlayer>();
public static void setCraftingPlayer(EntityPlayer player)
{
craftingPlayer.set(player);
}
public static EntityPlayer getCraftingPlayer()
{
return craftingPlayer.get();
}
public static ItemStack getContainerItem(ItemStack stack)
{
if (stack == null) return null;
if (stack.getItem().hasContainerItem(stack))
{
stack = stack.getItem().getContainerItem(stack);
if (stack != null && stack.isItemStackDamageable() && stack.getMetadata() > stack.getMaxDamage())
{
MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(craftingPlayer.get(), stack));
return null;
}
return stack;
}
return null;
}
public static WorldGeneratorBonusChest getBonusChest(Random rand)
{
return new WorldGeneratorBonusChest(ChestGenHooks.getItems(ChestGenHooks.BONUS_CHEST, rand), ChestGenHooks.getCount(ChestGenHooks.BONUS_CHEST, rand));
}
public static boolean isInsideOfMaterial(Material material, Entity entity, BlockPos pos)
{
IBlockState state = entity.worldObj.getBlockState(pos);
Block block = state.getBlock();
double eyes = entity.posY + (double)entity.getEyeHeight();
double filled = 1.0f; //If it's not a liquid assume it's a solid block
if (block instanceof IFluidBlock)
{
filled = ((IFluidBlock)block).getFilledPercentage(entity.worldObj, pos);
}
else if (block instanceof BlockLiquid)
{
filled = BlockLiquid.getLiquidHeightPercent(block.getMetaFromState(state));
}
if (filled < 0)
{
filled *= -1;
//filled -= 0.11111111F; //Why this is needed.. not sure...
return eyes > (double)(pos.getY() + 1 + (1 - filled));
}
else
{
return eyes < (double)(pos.getY() + 1 + filled);
}
}
public static boolean onPlayerAttackTarget(EntityPlayer player, Entity target)
{
if (MinecraftForge.EVENT_BUS.post(new AttackEntityEvent(player, target))) return false;
ItemStack stack = player.getCurrentEquippedItem();
if (stack != null && stack.getItem().onLeftClickEntity(stack, player, target)) return false;
return true;
}
}
@@ -1,8 +1,8 @@
package net.minecraftforge.common;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.Item;
@@ -34,25 +34,25 @@ import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.client.FMLFileResourcePack;
import cpw.mods.fml.client.FMLFolderResourcePack;
import cpw.mods.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
import cpw.mods.fml.common.DummyModContainer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.LoadController;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.WorldAccessContainer;
import cpw.mods.fml.common.event.FMLConstructionEvent;
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
import cpw.mods.fml.common.event.FMLModIdMappingEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.PlayerEvent;
import cpw.mods.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.client.FMLFileResourcePack;
import net.minecraftforge.fml.client.FMLFolderResourcePack;
import net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
import net.minecraftforge.fml.common.DummyModContainer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.LoadController;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModMetadata;
import net.minecraftforge.fml.common.WorldAccessContainer;
import net.minecraftforge.fml.common.event.FMLConstructionEvent;
import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
import net.minecraftforge.fml.common.event.FMLModIdMappingEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
public class ForgeModContainer extends DummyModContainer implements WorldAccessContainer
{
@@ -190,9 +190,9 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
FMLLog.warning("Enabling removal of erroring Tile Entities - USE AT YOUR OWN RISK");
}
//prop = config.get(Configuration.CATEGORY_GENERAL, "disableStitchedFileSaving", true);
//prop.comment = "Set this to just disable the texture stitcher from writing the 'debug.stitched_{name}.png file to disc. Just a small performance tweak. Default: true";
//disableStitchedFileSaving = prop.getBoolean(true);
prop = config.get(Configuration.CATEGORY_GENERAL, "disableStitchedFileSaving", true);
prop.comment = "Set this to just disable the texture stitcher from writing the '{name}_{mipmap}.png files to disc. Just a small performance tweak. Default: true";
disableStitchedFileSaving = prop.getBoolean(true);
prop = config.get(Configuration.CATEGORY_GENERAL, "fullBoundingBoxLadders", false);
prop.comment = "Set this to true to check the entire entity's collision bounding box for ladders instead of just the block they are in. Causes noticable differences in mechanics so default is vanilla behavior. Default: false";
@@ -253,7 +253,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
}
}
}
@SubscribeEvent
public void playerLogin(PlayerEvent.PlayerLoggedInEvent event)
{
@@ -326,7 +326,6 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
@Subscribe
public void mappingChanged(FMLModIdMappingEvent evt)
{
Blocks.fire.rebuildFireInfo();
OreDictionary.rebakeMap();
}
@@ -13,17 +13,17 @@ import java.util.Map;
import com.google.common.io.ByteStreams;
import com.google.gson.Gson;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;
public class ForgeVersion
{
//This number is incremented every time we remove deprecated code/major API changes, never reset
public static final int majorVersion = 10;
public static final int majorVersion = 11;
//This number is incremented every minecraft release, never reset
public static final int minorVersion = 13;
public static final int minorVersion = 14;
//This number is incremented every time a interface changes or new major feature is added, and reset every Minecraft version
public static final int revisionVersion = 2;
public static final int revisionVersion = 0;
//This number is incremented every time Jenkins builds Forge, and never reset. Should always be 0 in the repo code.
public static final int buildVersion = 0;
@@ -1,11 +1,12 @@
package net.minecraftforge.common;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BlockPos;
import net.minecraft.world.IBlockAccess;
public interface IPlantable
{
public EnumPlantType getPlantType(IBlockAccess world, int x, int y, int z);
public Block getPlant(IBlockAccess world, int x, int y, int z);
public int getPlantMetadata(IBlockAccess world, int x, int y, int z);
public EnumPlantType getPlantType(IBlockAccess world, BlockPos pos);
public IBlockState getPlant(IBlockAccess world, BlockPos pos);
}
@@ -1,8 +1,9 @@
package net.minecraftforge.common;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraft.util.BlockPos;
import net.minecraft.world.IBlockAccess;
/**
@@ -21,12 +22,10 @@ public interface IShearable
*
* @param item The itemstack that is being used, Possible to be null
* @param world The current world
* @param x The X Position
* @param y The Y Position
* @param z The Z Position
* @param pos Block's position in world.
* @return If this is shearable, and onSheared should be called.
*/
public boolean isShearable(ItemStack item, IBlockAccess world, int x, int y, int z);
public boolean isShearable(ItemStack item, IBlockAccess world, BlockPos pos);
/**
* Performs the shear function on this object.
@@ -42,11 +41,9 @@ public interface IShearable
*
* @param item The itemstack that is being used, Possible to be null
* @param world The current world
* @param x The X Position
* @param y The Y Position
* @param z The Z Position
* @param pos If this is a block, the block's position in world.
* @param fortune The fortune level of the shears being used
* @return A ArrayList containing all items from this shearing. Possible to be null.
*/
public ArrayList<ItemStack> onSheared(ItemStack item, IBlockAccess world, int x, int y, int z, int fortune);
public List<ItemStack> onSheared(ItemStack item, IBlockAccess world, BlockPos pos, int fortune);
}
@@ -64,7 +64,7 @@ public interface ISpecialArmor
* @param slot The armor slot the item is in.
*/
public abstract void damageArmor(EntityLivingBase entity, ItemStack stack, DamageSource source, int damage, int slot);
public static class ArmorProperties implements Comparable<ArmorProperties>
{
public int Priority = 0;
@@ -90,7 +90,7 @@ public interface ISpecialArmor
* @param damage The total damage being done
* @return The left over damage that has not been absorbed by the armor
*/
public static float ApplyArmor(EntityLivingBase entity, ItemStack[] inventory, DamageSource source, double damage)
public static float applyArmor(EntityLivingBase entity, ItemStack[] inventory, DamageSource source, double damage)
{
if (DEBUG)
{
@@ -1,8 +1,8 @@
package net.minecraftforge.common;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.eventhandler.EventBus;
import net.minecraft.crash.CrashReport;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.ForgeHooks.SeedEntry;
@@ -23,7 +23,7 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import cpw.mods.fml.relauncher.FMLInjectionData;
import net.minecraftforge.fml.relauncher.FMLInjectionData;
/**
* Caches player's last known usernames
@@ -23,8 +23,6 @@ public class WorldSpecificSaveHandler implements ISaveHandler
{
this.world = world;
this.parent = parent;
dataDir = new File(world.getChunkSaveLocation(), "data");
dataDir.mkdirs();
}
@Override public WorldInfo loadWorldInfo() { return parent.loadWorldInfo(); }
@@ -32,7 +30,7 @@ public class WorldSpecificSaveHandler implements ISaveHandler
@Override public IChunkLoader getChunkLoader(WorldProvider var1) { return parent.getChunkLoader(var1); }
@Override public void saveWorldInfoWithPlayer(WorldInfo var1, NBTTagCompound var2) { parent.saveWorldInfoWithPlayer(var1, var2); }
@Override public void saveWorldInfo(WorldInfo var1){ parent.saveWorldInfo(var1); }
@Override public IPlayerFileData getSaveHandler() { return parent.getSaveHandler(); }
@Override public IPlayerFileData getPlayerNBTManager() { return parent.getPlayerNBTManager(); }
@Override public void flush() { parent.flush(); }
@Override public String getWorldDirectoryName() { return parent.getWorldDirectoryName(); }
@Override public File getWorldDirectory() { return parent.getWorldDirectory(); }
@@ -40,6 +38,11 @@ public class WorldSpecificSaveHandler implements ISaveHandler
@Override
public File getMapFileFromName(String name)
{
if (dataDir == null) //Delayed down here do that world has time to be initalized first.
{
dataDir = new File(world.getChunkSaveLocation(), "data");
dataDir.mkdirs();
}
return new File(dataDir, name + ".dat");
}
@@ -40,13 +40,13 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu
queuedChunk.loader.loadEntities(queuedChunk.world, queuedChunk.compound.getCompoundTag("Level"), chunk);
MinecraftForge.EVENT_BUS.post(new ChunkDataEvent.Load(chunk, queuedChunk.compound)); // Don't call ChunkDataEvent.Load async
chunk.lastSaveTime = queuedChunk.provider.worldObj.getTotalWorldTime();
queuedChunk.provider.loadedChunkHashMap.add(ChunkCoordIntPair.chunkXZ2Int(queuedChunk.x, queuedChunk.z), chunk);
chunk.setLastSaveTime(queuedChunk.provider.worldObj.getTotalWorldTime());
queuedChunk.provider.id2ChunkMap.add(ChunkCoordIntPair.chunkXZ2Int(queuedChunk.x, queuedChunk.z), chunk);
queuedChunk.provider.loadedChunks.add(chunk);
chunk.onChunkLoad();
if (queuedChunk.provider.currentChunkProvider != null) {
queuedChunk.provider.currentChunkProvider.recreateStructures(queuedChunk.x, queuedChunk.z);
if (queuedChunk.provider.serverChunkGenerator != null) {
queuedChunk.provider.serverChunkGenerator.recreateStructures(chunk, queuedChunk.x, queuedChunk.z);
}
chunk.populateChunk(queuedChunk.provider, queuedChunk.provider, queuedChunk.x, queuedChunk.z);
@@ -43,7 +43,7 @@ class QueuedChunk {
result.append(" z: " + z + NEW_LINE);
result.append(" loader: " + loader + NEW_LINE );
result.append(" world: " + world.getWorldInfo().getWorldName() + NEW_LINE);
result.append(" dimension: " + world.provider.dimensionId + NEW_LINE);
result.append(" dimension: " + world.provider.getDimensionId() + NEW_LINE);
result.append(" provider: " + world.provider.getClass().getName() + NEW_LINE);
result.append("}");
@@ -24,7 +24,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import cpw.mods.fml.client.config.GuiConfigEntries.IConfigEntry;
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
public class ConfigCategory implements Map<String, Property>
{
@@ -11,41 +11,41 @@ import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import cpw.mods.fml.client.config.ConfigGuiType;
import cpw.mods.fml.client.config.GuiConfigEntries.IConfigEntry;
import cpw.mods.fml.client.config.GuiEditArrayEntries.IArrayEntry;
import cpw.mods.fml.client.config.IConfigElement;
import net.minecraftforge.fml.client.config.ConfigGuiType;
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
import net.minecraftforge.fml.client.config.GuiEditArrayEntries.IArrayEntry;
import net.minecraftforge.fml.client.config.IConfigElement;
/**
* This class bridges the gap between the FML config GUI classes and the Forge Configuration classes.
*/
public class ConfigElement<T> implements IConfigElement<T>
public class ConfigElement implements IConfigElement
{
private Property prop;
private Property.Type type;
private boolean isProperty;
private ConfigCategory ctgy;
private boolean categoriesFirst = true;
public ConfigElement(ConfigCategory ctgy)
{
this.ctgy = ctgy;
isProperty = false;
}
public ConfigElement(Property prop)
{
this.prop = prop;
this.type = prop.getType();
this.isProperty = true;
}
public ConfigElement<T> listCategoriesFirst(boolean categoriesFirst)
public ConfigElement listCategoriesFirst(boolean categoriesFirst)
{
this.categoriesFirst = categoriesFirst;
return this;
}
@Override
public List<IConfigElement> getChildElements()
{
@@ -55,7 +55,7 @@ public class ConfigElement<T> implements IConfigElement<T>
Iterator<ConfigCategory> ccI = ctgy.getChildren().iterator();
Iterator<Property> pI = ctgy.getOrderedValues().iterator();
int index = 0;
if (categoriesFirst)
while (ccI.hasNext())
{
@@ -63,14 +63,14 @@ public class ConfigElement<T> implements IConfigElement<T>
if (temp.showInGui()) // don't bother adding elements that shouldn't show
elements.add(temp);
}
while (pI.hasNext())
{
ConfigElement<?> temp = getTypedElement(pI.next());
ConfigElement temp = new ConfigElement(pI.next());
if (temp.showInGui())
elements.add(temp);
}
if (!categoriesFirst)
while (ccI.hasNext())
{
@@ -78,39 +78,24 @@ public class ConfigElement<T> implements IConfigElement<T>
if (temp.showInGui())
elements.add(temp);
}
return elements;
}
return null;
}
public static ConfigElement<?> getTypedElement(Property prop)
{
switch (getType(prop))
{
case BOOLEAN:
return new ConfigElement<Boolean>(prop);
case DOUBLE:
return new ConfigElement<Double>(prop);
case INTEGER:
return new ConfigElement<Integer>(prop);
default:
return new ConfigElement<String>(prop);
}
}
@Override
public String getName()
{
return isProperty ? prop.getName() : ctgy.getName();
}
@Override
public boolean isProperty()
{
return isProperty;
}
@Override
public Class<? extends IConfigEntry> getConfigEntryClass()
{
@@ -122,63 +107,63 @@ public class ConfigElement<T> implements IConfigElement<T>
{
return isProperty ? prop.getArrayEntryClass() : null;
}
@Override
public String getQualifiedName()
{
return isProperty ? prop.getName() : ctgy.getQualifiedName();
}
@Override
public ConfigGuiType getType()
{
return isProperty ? getType(this.prop) : ConfigGuiType.CONFIG_CATEGORY;
}
public static ConfigGuiType getType(Property prop)
{
return prop.getType() == Property.Type.BOOLEAN ? ConfigGuiType.BOOLEAN : prop.getType() == Property.Type.DOUBLE ? ConfigGuiType.DOUBLE :
prop.getType() == Property.Type.INTEGER ? ConfigGuiType.INTEGER : prop.getType() == Property.Type.COLOR ? ConfigGuiType.COLOR :
return prop.getType() == Property.Type.BOOLEAN ? ConfigGuiType.BOOLEAN : prop.getType() == Property.Type.DOUBLE ? ConfigGuiType.DOUBLE :
prop.getType() == Property.Type.INTEGER ? ConfigGuiType.INTEGER : prop.getType() == Property.Type.COLOR ? ConfigGuiType.COLOR :
prop.getType() == Property.Type.MOD_ID ? ConfigGuiType.MOD_ID : ConfigGuiType.STRING;
}
@Override
public boolean isList()
{
return isProperty && prop.isList();
}
@Override
public boolean isListLengthFixed()
{
return isProperty && prop.isListLengthFixed();
}
@Override
public int getMaxListLength()
{
return isProperty ? prop.getMaxListLength() : -1;
}
@Override
public String getComment()
{
return isProperty ? prop.comment : ctgy.getComment();
}
@Override
public boolean isDefault()
{
return !isProperty || prop.isDefault();
}
@Override
public void setToDefault()
{
if (isProperty)
prop.setToDefault();
}
@Override
public boolean requiresWorldRestart()
{
@@ -196,25 +181,25 @@ public class ConfigElement<T> implements IConfigElement<T>
{
return isProperty ? prop.requiresMcRestart() : ctgy.requiresMcRestart();
}
@Override
public String[] getValidValues()
{
return isProperty ? prop.getValidValues() : null;
}
@Override
public String getLanguageKey()
{
return isProperty ? prop.getLanguageKey() : ctgy.getLanguagekey();
}
@Override
public Object getDefault()
{
return isProperty ? (T) prop.getDefault() : null;
return isProperty ? prop.getDefault() : null;
}
@Override
public Object[] getDefaults()
{
@@ -247,7 +232,7 @@ public class ConfigElement<T> implements IConfigElement<T>
}
return null;
}
@Override
public Pattern getValidationPattern()
{
@@ -257,7 +242,7 @@ public class ConfigElement<T> implements IConfigElement<T>
@Override
public Object get()
{
return isProperty ? (T) prop.getString() : null;
return isProperty ? prop.getString() : null;
}
@Override
@@ -294,7 +279,7 @@ public class ConfigElement<T> implements IConfigElement<T>
}
@Override
public void set(T value)
public void set(Object value)
{
if (isProperty)
{
@@ -310,7 +295,7 @@ public class ConfigElement<T> implements IConfigElement<T>
}
@Override
public void set(T[] aVal)
public void set(Object[] aVal)
{
if (isProperty)
{
@@ -346,14 +331,14 @@ public class ConfigElement<T> implements IConfigElement<T>
}
@Override
public T getMinValue()
public Object getMinValue()
{
return isProperty ? (T) prop.getMinValue() : null;
return isProperty ? prop.getMinValue() : null;
}
@Override
public T getMaxValue()
public Object getMaxValue()
{
return isProperty ? (T) prop.getMaxValue() : null;
return isProperty ? prop.getMaxValue() : null;
}
}
@@ -36,10 +36,10 @@ import java.util.regex.Pattern;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableSet;
import cpw.mods.fml.client.config.GuiConfigEntries.IConfigEntry;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.relauncher.FMLInjectionData;
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.relauncher.FMLInjectionData;
/**
* This class offers advanced configurations capabilities, allowing to provide
@@ -9,8 +9,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Pattern;
import cpw.mods.fml.client.config.GuiConfigEntries.IConfigEntry;
import cpw.mods.fml.client.config.GuiEditArrayEntries.IArrayEntry;
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
import net.minecraftforge.fml.client.config.GuiEditArrayEntries.IArrayEntry;
public class Property
{
@@ -5,7 +5,7 @@ import io.netty.channel.SimpleChannelInboundHandler;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.network.ForgeMessage.DimensionRegisterMessage;
import org.apache.logging.log4j.Level;
import cpw.mods.fml.common.FMLLog;
import net.minecraftforge.fml.common.FMLLog;
public class DimensionMessageHandler extends SimpleChannelInboundHandler<ForgeMessage.DimensionRegisterMessage>{
@Override
@@ -4,7 +4,7 @@ import net.minecraftforge.fluids.FluidRegistry;
import org.apache.logging.log4j.Level;
import cpw.mods.fml.common.FMLLog;
import net.minecraftforge.fml.common.FMLLog;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
@@ -7,7 +7,7 @@ import net.minecraftforge.fluids.FluidRegistry;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import cpw.mods.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import io.netty.buffer.ByteBuf;
public abstract class ForgeMessage {
@@ -2,12 +2,12 @@ package net.minecraftforge.common.network;
import java.util.EnumMap;
import net.minecraftforge.common.ForgeModContainer;
import cpw.mods.fml.common.network.FMLEmbeddedChannel;
import cpw.mods.fml.common.network.FMLOutboundHandler;
import cpw.mods.fml.common.network.FMLOutboundHandler.OutboundTarget;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraftforge.fml.common.network.FMLEmbeddedChannel;
import net.minecraftforge.fml.common.network.FMLOutboundHandler;
import net.minecraftforge.fml.common.network.FMLOutboundHandler.OutboundTarget;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class ForgeNetworkHandler
{
@@ -2,7 +2,7 @@ package net.minecraftforge.common.network;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec;
import net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec;
public class ForgeRuntimeCodec extends FMLIndexedMessageToMessageCodec<ForgeMessage> {
public ForgeRuntimeCodec()
@@ -1,6 +1,6 @@
package net.minecraftforge.common.network;
import cpw.mods.fml.common.network.NetworkHandshakeEstablished;
import net.minecraftforge.fml.common.network.NetworkHandshakeEstablished;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
@@ -0,0 +1,139 @@
package net.minecraftforge.common.property;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.BlockState.StateImplementation;
import net.minecraft.block.state.IBlockState;
import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Iterables;
public class ExtendedBlockState extends BlockState
{
private final ImmutableSet<IUnlistedProperty<?>> unlistedProperties;
public ExtendedBlockState(Block blockIn, IProperty[] properties, IUnlistedProperty<?>[] unlistedProperties)
{
super(blockIn, properties, buildUnlistedMap(unlistedProperties));
ImmutableSet.Builder<IUnlistedProperty<?>> builder = ImmutableSet.<IUnlistedProperty<?>>builder();
for(IUnlistedProperty<?> property : unlistedProperties)
{
builder.add(property);
}
this.unlistedProperties = builder.build();
}
private static ImmutableMap<IUnlistedProperty<?>, Optional<?>> buildUnlistedMap(IUnlistedProperty<?>[] unlistedProperties)
{
ImmutableMap.Builder<IUnlistedProperty<?>, Optional<?>> builder = ImmutableMap.<IUnlistedProperty<?>, Optional<?>>builder();
for(IUnlistedProperty<?> p : unlistedProperties)
{
builder.put(p, Optional.absent());
}
return builder.build();
}
@Override
protected StateImplementation createState(Block block, ImmutableMap properties, ImmutableMap unlistedProperties)
{
return new ExtendedStateImplementation(block, properties, unlistedProperties, null);
}
protected static class ExtendedStateImplementation extends StateImplementation implements IExtendedBlockState
{
private final ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties;
private Map<Map<IProperty, Comparable>, IBlockState> normalMap;
protected ExtendedStateImplementation(Block block, ImmutableMap properties, ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties, ImmutableTable<IProperty, Comparable, IBlockState> table)
{
super(block, properties);
this.unlistedProperties = unlistedProperties;
this.propertyValueTable = table;
}
@Override
public IBlockState withProperty(IProperty property, Comparable value)
{
if (!this.getProperties().containsKey(property))
{
throw new IllegalArgumentException("Cannot set property " + property + " as it does not exist in " + getBlock().getBlockState());
}
else if (!property.getAllowedValues().contains(value))
{
throw new IllegalArgumentException("Cannot set property " + property + " to " + value + " on block " + Block.blockRegistry.getNameForObject(getBlock()) + ", it is not an allowed value");
}
else
{
if(this.getProperties().get(property) == value)
{
return this;
}
if(Iterables.all(unlistedProperties.values(), Predicates.<Optional<?>>equalTo(Optional.absent())))
{ // no dynamic properties present, looking up in the normal table
return super.withProperty(property, value);
}
Map<IProperty, Comparable> map = new HashMap<IProperty, Comparable>(getProperties());
map.put(property, value);
ImmutableTable<IProperty, Comparable, IBlockState> table = propertyValueTable;
table = ((StateImplementation)table.get(property, value)).getPropertyValueTable();
return new ExtendedStateImplementation(getBlock(), ImmutableMap.copyOf(map), unlistedProperties, table);
}
}
public <V> IExtendedBlockState withProperty(IUnlistedProperty<V> property, V value)
{
if(!this.unlistedProperties.containsKey(property))
{
throw new IllegalArgumentException("Cannot set unlisted property " + property + " as it does not exist in " + getBlock().getBlockState());
}
if(!property.isValid(value))
{
throw new IllegalArgumentException("Cannot set unlisted property " + property + " to " + value + " on block " + Block.blockRegistry.getNameForObject(getBlock()) + ", it is not an allowed value");
}
Map<IUnlistedProperty<?>, Optional<?>> newMap = new HashMap<IUnlistedProperty<?>, Optional<?>>(unlistedProperties);
newMap.put(property, Optional.fromNullable(value));
if(Iterables.all(newMap.values(), Predicates.<Optional<?>>equalTo(Optional.absent())))
{ // no dynamic properties, lookup normal state
return (IExtendedBlockState) normalMap.get(getProperties());
}
return new ExtendedStateImplementation(getBlock(), getProperties(), ImmutableMap.copyOf(newMap), propertyValueTable);
}
public Collection<IUnlistedProperty<?>> getUnlistedNames()
{
return Collections.unmodifiableCollection(unlistedProperties.keySet());
}
public <V>V getValue(IUnlistedProperty<V> property)
{
if(!this.unlistedProperties.containsKey(property))
{
throw new IllegalArgumentException("Cannot get unlisted property " + property + " as it does not exist in " + getBlock().getBlockState());
}
return property.getType().cast(this.unlistedProperties.get(property).orNull());
}
public ImmutableMap<IUnlistedProperty<?>, Optional<?>> getUnlistedProperties()
{
return unlistedProperties;
}
@Override
public void buildPropertyValueTable(Map map)
{
this.normalMap = map;
super.buildPropertyValueTable(map);
}
}
}
@@ -0,0 +1,19 @@
package net.minecraftforge.common.property;
import java.util.Collection;
import net.minecraft.block.state.IBlockState;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
public interface IExtendedBlockState extends IBlockState
{
Collection<IUnlistedProperty<?>> getUnlistedNames();
<V>V getValue(IUnlistedProperty<V> property);
<V>IExtendedBlockState withProperty(IUnlistedProperty<V> property, V value);
ImmutableMap<IUnlistedProperty<?>, Optional<?>> getUnlistedProperties();
}
@@ -0,0 +1,12 @@
package net.minecraftforge.common.property;
public interface IUnlistedProperty<V>
{
String getName();
boolean isValid(V value);
Class<V> getType();
String valueToString(V value);
}
@@ -0,0 +1,45 @@
package net.minecraftforge.common.property;
import java.lang.reflect.InvocationTargetException;
import net.minecraft.block.properties.IProperty;
import org.apache.commons.lang3.reflect.ConstructorUtils;
public class Properties
{
public static <P extends IProperty, V>IUnlistedProperty<V> toUnlisted(P property)
{
return new PropertyAdapter(property);
}
public static class PropertyAdapter<V extends Comparable> implements IUnlistedProperty<V>
{
private final IProperty parent;
public PropertyAdapter(IProperty parent)
{
this.parent = parent;
}
public String getName()
{
return parent.getName();
}
public boolean isValid(V value)
{
return parent.getAllowedValues().contains(value);
}
public Class<V> getType()
{
return parent.getValueClass();
}
public String valueToString(V value)
{
return parent.getName(value);
}
}
}
@@ -12,7 +12,7 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import cpw.mods.fml.common.FMLLog;
import net.minecraftforge.fml.common.FMLLog;
/**
@@ -4,12 +4,14 @@ package net.minecraftforge.common.util;
import java.io.Serializable;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.GameRegistry.UniqueIdentifier;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry.UniqueIdentifier;
/**
* Represents a captured snapshot of a block which will not change
@@ -23,29 +25,25 @@ public class BlockSnapshot implements Serializable
{
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("forge.debugBlockSnapshot", "false"));
public final int x;
public final int y;
public final int z;
public final BlockPos pos;
public final int dimId;
public transient Block replacedBlock;
public final int meta;
public transient IBlockState replacedBlock;
public int flag;
private final NBTTagCompound nbt;
public transient World world;
public final UniqueIdentifier blockIdentifier;
public final int meta;
public BlockSnapshot(World world, int x, int y, int z, Block block, int meta)
public BlockSnapshot(World world, BlockPos pos, IBlockState state)
{
this.world = world;
this.dimId = world.provider.dimensionId;
this.x = x;
this.y = y;
this.z = z;
this.replacedBlock = block;
this.blockIdentifier = GameRegistry.findUniqueIdentifierFor(block);
this.meta = meta;
this.dimId = world.provider.getDimensionId();
this.pos = pos;
this.replacedBlock = state;
this.blockIdentifier = GameRegistry.findUniqueIdentifierFor(state.getBlock());
this.meta = state.getBlock().getMetaFromState(state);
this.flag = 3;
TileEntity te = world.getTileEntity(x, y, z);
TileEntity te = world.getTileEntity(pos);
if (te != null)
{
nbt = new NBTTagCompound();
@@ -54,57 +52,53 @@ public class BlockSnapshot implements Serializable
else nbt = null;
if (DEBUG)
{
System.out.printf("Created BlockSnapshot - [World: %s ][Location: %d,%d,%d ][Block: %s ][Meta: %d ]", world.getWorldInfo().getWorldName(), x, y, z, block, meta);
System.out.printf("Created BlockSnapshot - [World: %s ][Location: %d,%d,%d ][Block: %s ][Meta: %d ]", world.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ(), blockIdentifier, meta);
}
}
public BlockSnapshot(World world, int x, int y, int z, Block block, int meta, NBTTagCompound nbt)
public BlockSnapshot(World world, BlockPos pos, IBlockState state, NBTTagCompound nbt)
{
this.world = world;
this.dimId = world.provider.dimensionId;
this.x = x;
this.y = y;
this.z = z;
this.replacedBlock = block;
this.blockIdentifier = GameRegistry.findUniqueIdentifierFor(block);
this.meta = meta;
this.dimId = world.provider.getDimensionId();
this.pos = pos;
this.replacedBlock = state;
this.blockIdentifier = GameRegistry.findUniqueIdentifierFor(state.getBlock());
this.meta = state.getBlock().getMetaFromState(state);
this.flag = 3;
this.nbt = nbt;
if (DEBUG)
{
System.out.printf("Created BlockSnapshot - [World: %s ][Location: %d,%d,%d ][Block: %s ][Meta: %d ]", world.getWorldInfo().getWorldName(), x, y, z, block, meta);
System.out.printf("Created BlockSnapshot - [World: %s ][Location: %d,%d,%d ][Block: %s ][Meta: %d ]", world.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ(), blockIdentifier, meta);
}
}
public BlockSnapshot(World world, int x, int y, int z, Block block, int meta, int flag)
public BlockSnapshot(World world, BlockPos pos, IBlockState state, int flag)
{
this(world, x, y, z, block, meta);
this(world, pos, state);
this.flag = flag;
}
/**
* Raw constructor designed for serialization usages.
*/
public BlockSnapshot(int dimension, int x, int y, int z, String modid, String blockName, int meta, int flag, NBTTagCompound nbt)
public BlockSnapshot(int dimension, BlockPos pos, String modid, String blockName, int meta, int flag, NBTTagCompound nbt)
{
this.dimId = dimension;
this.x = x;
this.y = y;
this.z = z;
this.meta = meta;
this.pos = pos;
this.flag = flag;
this.blockIdentifier = new UniqueIdentifier(modid + ":" + blockName);
this.meta = meta;
this.nbt = nbt;
}
public static BlockSnapshot getBlockSnapshot(World world, int x, int y, int z)
public static BlockSnapshot getBlockSnapshot(World world, BlockPos pos)
{
return new BlockSnapshot(world, x, y, z, world.getBlock(x, y, z), world.getBlockMetadata(x, y,z));
return new BlockSnapshot(world, pos, world.getBlockState(pos));
}
public static BlockSnapshot getBlockSnapshot(World world, int x, int y, int z, int flag)
public static BlockSnapshot getBlockSnapshot(World world, BlockPos pos, int flag)
{
return new BlockSnapshot(world, x, y, z, world.getBlock(x, y, z), world.getBlockMetadata(x, y,z), flag);
return new BlockSnapshot(world, pos, world.getBlockState(pos), flag);
}
public static BlockSnapshot readFromNBT(NBTTagCompound tag)
@@ -113,9 +107,7 @@ public class BlockSnapshot implements Serializable
return new BlockSnapshot(
tag.getInteger("dimension"),
tag.getInteger("posX"),
tag.getInteger("posY"),
tag.getInteger("posZ"),
new BlockPos(tag.getInteger("posX"), tag.getInteger("posY"), tag.getInteger("posZ")),
tag.getString("blockMod"),
tag.getString("blockName"),
tag.getInteger("metadata"),
@@ -123,25 +115,25 @@ public class BlockSnapshot implements Serializable
nbt);
}
public Block getCurrentBlock()
public IBlockState getCurrentBlock()
{
return world.getBlock(x, y, z);
return world.getBlockState(pos);
}
public World getWorld()
public World getWorld()
{
if (this.world == null)
if (this.world == null)
{
this.world = DimensionManager.getWorld(dimId);
}
return this.world;
}
public Block getReplacedBlock()
public IBlockState getReplacedBlock()
{
if (this.replacedBlock == null)
if (this.replacedBlock == null)
{
this.replacedBlock = GameRegistry.findBlock(this.blockIdentifier.modId, this.blockIdentifier.name);
this.replacedBlock = GameRegistry.findBlock(this.blockIdentifier.modId, this.blockIdentifier.name).getStateFromMeta(meta);
}
return this.replacedBlock;
}
@@ -153,69 +145,38 @@ public class BlockSnapshot implements Serializable
else return null;
}
public boolean restore()
public boolean restore()
{
return restore(false);
}
public boolean restore(boolean force)
public boolean restore(boolean force)
{
return restore(force, true);
}
public boolean restore(boolean force, boolean applyPhysics)
public boolean restore(boolean force, boolean applyPhysics)
{
if (getCurrentBlock() != getReplacedBlock() || world.getBlockMetadata(x & 15, y, z & 15) != meta)
IBlockState current = getCurrentBlock();
IBlockState replaced = getReplacedBlock();
if (current.getBlock() != replaced.getBlock() || current.getBlock().getMetaFromState(current) != replaced.getBlock().getMetaFromState(replaced))
{
if (force)
{
world.setBlock(x, y, z, getReplacedBlock(), meta, applyPhysics ? 3 : 2);
world.setBlockState(pos, replaced, applyPhysics ? 3 : 2);
}
else
{
return false;
}
}
world.setBlockMetadataWithNotify(x, y, z, meta, applyPhysics ? 3 : 2);
world.markBlockForUpdate(x, y, z);
TileEntity te = null;
if (nbt != null)
{
te = world.getTileEntity(x, y, z);
if (te != null)
{
te.readFromNBT(nbt);
}
}
if (DEBUG)
{
System.out.printf("Restored BlockSnapshot with data [World: %s ][Location: %d,%d,%d ][Meta: %d ][Block: %s ][TileEntity: %s ][force: %s ][applyPhysics: %s]", world.getWorldInfo().getWorldName(), x, y, z, meta, getReplacedBlock(), te, force, applyPhysics);
}
return true;
}
public boolean restoreToLocation(World world, int x, int y, int z, boolean force, boolean applyPhysics)
{
if (getCurrentBlock() != getReplacedBlock() || world.getBlockMetadata(x & 15, y, z & 15) != meta)
{
if (force)
{
world.setBlock(x, y, z, getReplacedBlock(), meta, applyPhysics ? 3 : 2);
}
else
{
return false;
}
}
world.setBlockMetadataWithNotify(x, y, z, meta, applyPhysics ? 3 : 2);
world.markBlockForUpdate(x, y, z);
world.setBlockState(pos, replaced, applyPhysics ? 3 : 2);
world.markBlockForUpdate(pos);
TileEntity te = null;
if (nbt != null)
{
te = world.getTileEntity(x, y, z);
te = world.getTileEntity(pos);
if (te != null)
{
te.readFromNBT(nbt);
@@ -224,7 +185,42 @@ public class BlockSnapshot implements Serializable
if (DEBUG)
{
System.out.printf("Restored BlockSnapshot with data [World: %s ][Location: %d,%d,%d ][Meta: %d ][Block: %s ][TileEntity: %s ][force: %s ][applyPhysics: %s]", world.getWorldInfo().getWorldName(), x, y, z, meta, getReplacedBlock(), te, force, applyPhysics);
System.out.printf("Restored BlockSnapshot with data [World: %s ][Location: %d,%d,%d ][Meta: %d ][Block: %s ][TileEntity: %s ][force: %s ][applyPhysics: %s]", world.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ(), replaced.getBlock().getMetaFromState(replaced), replaced.getBlock().delegate.name(), te, force, applyPhysics);
}
return true;
}
public boolean restoreToLocation(World world, BlockPos pos, boolean force, boolean applyPhysics)
{
IBlockState current = getCurrentBlock();
IBlockState replaced = getReplacedBlock();
if (current.getBlock() != replaced.getBlock() || current.getBlock().getMetaFromState(current) != replaced.getBlock().getMetaFromState(replaced))
{
if (force)
{
world.setBlockState(pos, replaced, applyPhysics ? 3 : 2);
}
else
{
return false;
}
}
world.setBlockState(pos, replaced, applyPhysics ? 3 : 2);
world.markBlockForUpdate(pos);
TileEntity te = null;
if (nbt != null)
{
te = world.getTileEntity(pos);
if (te != null)
{
te.readFromNBT(nbt);
}
}
if (DEBUG)
{
System.out.printf("Restored BlockSnapshot with data [World: %s ][Location: %d,%d,%d ][Meta: %d ][Block: %s ][TileEntity: %s ][force: %s ][applyPhysics: %s]", world.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ(), replaced.getBlock().getMetaFromState(replaced), replaced.getBlock().delegate.name(), te, force, applyPhysics);
}
return true;
}
@@ -233,9 +229,9 @@ public class BlockSnapshot implements Serializable
{
compound.setString("blockMod", blockIdentifier.modId);
compound.setString("blockName", blockIdentifier.name);
compound.setInteger("posX", x);
compound.setInteger("posY", y);
compound.setInteger("posZ", z);
compound.setInteger("posX", pos.getX());
compound.setInteger("posY", pos.getY());
compound.setInteger("posZ", pos.getZ());
compound.setInteger("flag", flag);
compound.setInteger("dimension", dimId);
compound.setInteger("metadata", meta);
@@ -249,7 +245,7 @@ public class BlockSnapshot implements Serializable
}
@Override
public boolean equals(Object obj)
public boolean equals(Object obj)
{
if (obj == null)
{
@@ -260,15 +256,7 @@ public class BlockSnapshot implements Serializable
return false;
}
final BlockSnapshot other = (BlockSnapshot) obj;
if (this.x != other.x)
{
return false;
}
if (this.y != other.y)
{
return false;
}
if (this.z != other.z)
if (!this.pos.equals(other.pos))
{
return false;
}
@@ -299,9 +287,9 @@ public class BlockSnapshot implements Serializable
public int hashCode()
{
int hash = 7;
hash = 73 * hash + this.x;
hash = 73 * hash + this.y;
hash = 73 * hash + this.z;
hash = 73 * hash + this.pos.getX();
hash = 73 * hash + this.pos.getY();
hash = 73 * hash + this.pos.getZ();
hash = 73 * hash + this.meta;
hash = 73 * hash + this.dimId;
hash = 73 * hash + (this.nbt != null ? this.nbt.hashCode() : 0);
@@ -3,11 +3,10 @@ package net.minecraftforge.common.util;
import java.lang.reflect.*;
import java.util.*;
import cpw.mods.fml.common.FMLLog;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraft.block.BlockPressurePlate.Sensitivity;
import net.minecraft.block.material.Material;
import net.minecraft.enchantment.EnumEnchantmentType;
import net.minecraft.entity.Entity.EnumEntitySize;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.item.EntityPainting.EnumArt;
@@ -36,13 +35,12 @@ public class EnumHelper
private static Class[][] commonTypes =
{
{EnumAction.class},
{ArmorMaterial.class, int.class, int[].class, int.class},
{ArmorMaterial.class, String.class, int.class, int[].class, int.class},
{EnumArt.class, String.class, int.class, int.class, int.class, int.class},
{EnumCreatureAttribute.class},
{EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class},
{Door.class},
{EnumEnchantmentType.class},
{EnumEntitySize.class},
{Sensitivity.class},
{MovingObjectType.class},
{EnumSkyBlock.class, int.class},
@@ -55,9 +53,9 @@ public class EnumHelper
{
return addEnum(EnumAction.class, name);
}
public static ArmorMaterial addArmorMaterial(String name, int durability, int[] reductionAmounts, int enchantability)
public static ArmorMaterial addArmorMaterial(String name, String textureName, int durability, int[] reductionAmounts, int enchantability)
{
return addEnum(ArmorMaterial.class, name, durability, reductionAmounts, enchantability);
return addEnum(ArmorMaterial.class, name, textureName, durability, reductionAmounts, enchantability);
}
public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY)
{
@@ -80,10 +78,6 @@ public class EnumHelper
{
return addEnum(EnumEnchantmentType.class, name);
}
public static EnumEntitySize addEntitySize(String name)
{
return addEnum(EnumEntitySize.class, name);
}
public static Sensitivity addSensitivity(String name)
{
return addEnum(Sensitivity.class, name);
@@ -2,19 +2,19 @@ package net.minecraftforge.common.util;
import com.mojang.authlib.GameProfile;
import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.play.client.C15PacketClientSettings;
import net.minecraft.server.management.ItemInWorldManager;
import net.minecraft.stats.StatBase;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.DamageSource;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
//Preliminary, simple Fake Player class
//Preliminary, simple Fake Player class
public class FakePlayer extends EntityPlayerMP
{
public FakePlayer(WorldServer world, GameProfile name)
@@ -22,19 +22,15 @@ public class FakePlayer extends EntityPlayerMP
super(FMLCommonHandler.instance().getMinecraftServerInstance(), world, name, new ItemInWorldManager(world));
}
@Override public boolean canCommandSenderUseCommand(int i, String s){ return false; }
@Override public ChunkCoordinates getPlayerCoordinates()
{
return new ChunkCoordinates(0,0,0);
}
@Override public Vec3 getPositionVector(){ return new Vec3(0, 0, 0); }
@Override public boolean canUseCommand(int i, String s){ return false; }
@Override public void addChatComponentMessage(IChatComponent chatmessagecomponent){}
@Override public void addStat(StatBase par1StatBase, int par2){}
@Override public void openGui(Object mod, int modGuiId, World world, int x, int y, int z){}
@Override public boolean isEntityInvulnerable(){ return true; }
@Override public boolean isEntityInvulnerable(DamageSource source){ return true; }
@Override public boolean canAttackPlayer(EntityPlayer player){ return false; }
@Override public void onDeath(DamageSource source){ return; }
@Override public void onUpdate(){ return; }
@Override public void travelToDimension(int dim){ return; }
@Override public void func_147100_a(C15PacketClientSettings pkt){ return; }
@Override public void handleClientSettings(C15PacketClientSettings pkt){ return; }
}
@@ -1,71 +0,0 @@
package net.minecraftforge.common.util;
public enum ForgeDirection
{
/** -Y */
DOWN(0, -1, 0),
/** +Y */
UP(0, 1, 0),
/** -Z */
NORTH(0, 0, -1),
/** +Z */
SOUTH(0, 0, 1),
/** -X */
WEST(-1, 0, 0),
/** +X */
EAST(1, 0, 0),
/**
* Used only by getOrientation, for invalid inputs
*/
UNKNOWN(0, 0, 0);
public final int offsetX;
public final int offsetY;
public final int offsetZ;
public final int flag;
public static final ForgeDirection[] VALID_DIRECTIONS = {DOWN, UP, NORTH, SOUTH, WEST, EAST};
public static final int[] OPPOSITES = {1, 0, 3, 2, 5, 4, 6};
// Left hand rule rotation matrix for all possible axes of rotation
public static final int[][] ROTATION_MATRIX = {
{0, 1, 4, 5, 3, 2, 6},
{0, 1, 5, 4, 2, 3, 6},
{5, 4, 2, 3, 0, 1, 6},
{4, 5, 2, 3, 1, 0, 6},
{2, 3, 1, 0, 4, 5, 6},
{3, 2, 0, 1, 4, 5, 6},
{0, 1, 2, 3, 4, 5, 6},
};
private ForgeDirection(int x, int y, int z)
{
offsetX = x;
offsetY = y;
offsetZ = z;
flag = 1 << ordinal();
}
public static ForgeDirection getOrientation(int id)
{
if (id >= 0 && id < VALID_DIRECTIONS.length)
{
return VALID_DIRECTIONS[id];
}
return UNKNOWN;
}
public ForgeDirection getOpposite()
{
return getOrientation(OPPOSITES[ordinal()]);
}
public ForgeDirection getRotation(ForgeDirection axis)
{
return getOrientation(ROTATION_MATRIX[axis.ordinal()][ordinal()]);
}
}
@@ -1,439 +0,0 @@
package net.minecraftforge.common.util;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockAnvil;
import net.minecraft.block.BlockBed;
import net.minecraft.block.BlockButton;
import net.minecraft.block.BlockChest;
import net.minecraft.block.BlockCocoa;
import net.minecraft.block.BlockDispenser;
import net.minecraft.block.BlockDoor;
import net.minecraft.block.BlockEndPortalFrame;
import net.minecraft.block.BlockEnderChest;
import net.minecraft.block.BlockFenceGate;
import net.minecraft.block.BlockFurnace;
import net.minecraft.block.BlockHopper;
import net.minecraft.block.BlockHugeMushroom;
import net.minecraft.block.BlockLadder;
import net.minecraft.block.BlockLever;
import net.minecraft.block.BlockLog;
import net.minecraft.block.BlockPistonBase;
import net.minecraft.block.BlockPistonExtension;
import net.minecraft.block.BlockPumpkin;
import net.minecraft.block.BlockRail;
import net.minecraft.block.BlockRailDetector;
import net.minecraft.block.BlockRailPowered;
import net.minecraft.block.BlockRedstoneComparator;
import net.minecraft.block.BlockRedstoneRepeater;
import net.minecraft.block.BlockSkull;
import net.minecraft.block.BlockStairs;
import net.minecraft.block.BlockTorch;
import net.minecraft.block.BlockTrapDoor;
import net.minecraft.block.BlockTripWireHook;
import net.minecraft.block.BlockVine;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;
import java.util.HashMap;
import java.util.Map;
import static net.minecraftforge.common.util.ForgeDirection.*;
/**
* This class is a helper function for vanilla blocks, and should not be called by Modders.
* Refer to block.rotateBlock and block.getValidRotations instead.
*
*/
public class RotationHelper {
/**
* Some blocks have the same rotation.
* The first of these blocks (sorted by itemID) should be listed as a type.
* Some of the types aren't actual blocks (helper types).
*/
private static enum BlockType {
LOG,
DISPENSER,
BED,
RAIL,
RAIL_POWERED,
RAIL_ASCENDING,
RAIL_CORNER,
TORCH,
STAIR,
CHEST,
SIGNPOST,
DOOR,
LEVER,
BUTTON,
REDSTONE_REPEATER,
TRAPDOOR,
MUSHROOM_CAP,
MUSHROOM_CAP_CORNER,
MUSHROOM_CAP_SIDE,
VINE,
SKULL,
ANVIL
}
private static final ForgeDirection[] UP_DOWN_AXES = new ForgeDirection[] { UP, DOWN };
private static final Map<BlockType, BiMap<Integer, ForgeDirection>> MAPPINGS = new HashMap<BlockType, BiMap<Integer, ForgeDirection>>();
public static ForgeDirection[] getValidVanillaBlockRotations(Block block)
{
return (block instanceof BlockBed ||
block instanceof BlockPumpkin ||
block instanceof BlockFenceGate ||
block instanceof BlockEndPortalFrame ||
block instanceof BlockTripWireHook ||
block instanceof BlockCocoa ||
block instanceof BlockRailPowered ||
block instanceof BlockRailDetector ||
block instanceof BlockStairs ||
block instanceof BlockChest ||
block instanceof BlockEnderChest ||
block instanceof BlockFurnace ||
block instanceof BlockLadder ||
block == Blocks.wall_sign ||
block == Blocks.standing_sign ||
block instanceof BlockDoor ||
block instanceof BlockRail ||
block instanceof BlockButton ||
block instanceof BlockRedstoneRepeater ||
block instanceof BlockRedstoneComparator ||
block instanceof BlockTrapDoor ||
block instanceof BlockHugeMushroom ||
block instanceof BlockVine ||
block instanceof BlockSkull ||
block instanceof BlockAnvil) ? UP_DOWN_AXES : VALID_DIRECTIONS;
}
public static boolean rotateVanillaBlock(Block block, World worldObj, int x, int y, int z, ForgeDirection axis)
{
if (worldObj.isRemote)
{
return false;
}
if (axis == UP || axis == DOWN)
{
if (block instanceof BlockBed || block instanceof BlockPumpkin || block instanceof BlockFenceGate || block instanceof BlockEndPortalFrame || block instanceof BlockTripWireHook || block instanceof BlockCocoa)
{
return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.BED);
}
if (block instanceof BlockRail)
{
return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.RAIL);
}
if (block instanceof BlockRailPowered || block instanceof BlockRailDetector)
{
return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.RAIL_POWERED);
}
if (block instanceof BlockStairs)
{
return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.STAIR);
}
if (block instanceof BlockChest || block instanceof BlockEnderChest || block instanceof BlockFurnace || block instanceof BlockLadder || block == Blocks.wall_sign)
{
return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.CHEST);
}
if (block == Blocks.standing_sign)
{
return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.SIGNPOST);
}
if (block instanceof BlockDoor)
{
return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.DOOR);
}
if (block instanceof BlockButton)
{
return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.BUTTON);
}
if (block instanceof BlockRedstoneRepeater || block instanceof BlockRedstoneComparator)
{
return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.REDSTONE_REPEATER);
}
if (block instanceof BlockTrapDoor)
{
return rotateBlock(worldObj, x, y, z, axis, 0x3, BlockType.TRAPDOOR);
}
if (block instanceof BlockHugeMushroom)
{
return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.MUSHROOM_CAP);
}
if (block instanceof BlockVine)
{
return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.VINE);
}
if (block instanceof BlockSkull)
{
return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.SKULL);
}
if (block instanceof BlockAnvil)
{
return rotateBlock(worldObj, x, y, z, axis, 0x1, BlockType.ANVIL);
}
}
if (block instanceof BlockLog)
{
return rotateBlock(worldObj, x, y, z, axis, 0xC, BlockType.LOG);
}
if (block instanceof BlockDispenser || block instanceof BlockPistonBase || block instanceof BlockPistonExtension || block instanceof BlockHopper)
{
return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.DISPENSER);
}
if (block instanceof BlockTorch)
{
return rotateBlock(worldObj, x, y, z, axis, 0xF, BlockType.TORCH);
}
if (block instanceof BlockLever)
{
return rotateBlock(worldObj, x, y, z, axis, 0x7, BlockType.LEVER);
}
return false;
}
private static boolean rotateBlock(World worldObj, int x, int y, int z, ForgeDirection axis, int mask, BlockType blockType)
{
int rotMeta = worldObj.getBlockMetadata(x, y, z);
if (blockType == BlockType.DOOR && (rotMeta & 0x8) == 0x8)
{
return false;
}
int masked = rotMeta & ~mask;
int meta = rotateMetadata(axis, blockType, rotMeta & mask);
if (meta == -1)
{
return false;
}
worldObj.setBlockMetadataWithNotify(x, y, z, meta & mask | masked, 3);
return true;
}
private static int rotateMetadata(ForgeDirection axis, BlockType blockType, int meta)
{
if (blockType == BlockType.RAIL || blockType == BlockType.RAIL_POWERED)
{
if (meta == 0x0 || meta == 0x1)
{
return ~meta & 0x1;
}
if (meta >= 0x2 && meta <= 0x5)
{
blockType = BlockType.RAIL_ASCENDING;
}
if (meta >= 0x6 && meta <= 0x9 && blockType == BlockType.RAIL)
{
blockType = BlockType.RAIL_CORNER;
}
}
if (blockType == BlockType.SIGNPOST)
{
return (axis == UP) ? (meta + 0x4) % 0x10 : (meta + 0xC) % 0x10;
}
if (blockType == BlockType.LEVER && (axis == UP || axis == DOWN))
{
switch (meta)
{
case 0x5:
return 0x6;
case 0x6:
return 0x5;
case 0x7:
return 0x0;
case 0x0:
return 0x7;
}
}
if (blockType == BlockType.MUSHROOM_CAP)
{
if (meta % 0x2 == 0)
{
blockType = BlockType.MUSHROOM_CAP_SIDE;
}
else
{
blockType = BlockType.MUSHROOM_CAP_CORNER;
}
}
if (blockType == BlockType.VINE)
{
return ((meta << 1) | ((meta & 0x8) >> 3));
}
ForgeDirection orientation = metadataToDirection(blockType, meta);
ForgeDirection rotated = orientation.getRotation(axis);
return directionToMetadata(blockType, rotated);
}
private static ForgeDirection metadataToDirection(BlockType blockType, int meta)
{
if (blockType == BlockType.LEVER)
{
if (meta == 0x6)
{
meta = 0x5;
}
else if (meta == 0x0)
{
meta = 0x7;
}
}
if (MAPPINGS.containsKey(blockType))
{
BiMap<Integer, ForgeDirection> biMap = MAPPINGS.get(blockType);
if (biMap.containsKey(meta))
{
return biMap.get(meta);
}
}
if (blockType == BlockType.TORCH)
{
return ForgeDirection.getOrientation(6 - meta);
}
if (blockType == BlockType.STAIR)
{
return ForgeDirection.getOrientation(5 - meta);
}
if (blockType == BlockType.CHEST || blockType == BlockType.DISPENSER || blockType == BlockType.SKULL)
{
return ForgeDirection.getOrientation(meta);
}
if (blockType == BlockType.BUTTON)
{
return ForgeDirection.getOrientation(6 - meta);
}
if (blockType == BlockType.TRAPDOOR)
{
return ForgeDirection.getOrientation(meta + 2).getOpposite();
}
return ForgeDirection.UNKNOWN;
}
private static int directionToMetadata(BlockType blockType, ForgeDirection direction)
{
if ((blockType == BlockType.LOG || blockType == BlockType.ANVIL) && (direction.offsetX + direction.offsetY + direction.offsetZ) < 0)
{
direction = direction.getOpposite();
}
if (MAPPINGS.containsKey(blockType))
{
BiMap<ForgeDirection, Integer> biMap = MAPPINGS.get(blockType).inverse();
if (biMap.containsKey(direction))
{
return biMap.get(direction);
}
}
if (blockType == BlockType.TORCH)
{
if (direction.ordinal() >= 1)
{
return 6 - direction.ordinal();
}
}
if (blockType == BlockType.STAIR)
{
return 5 - direction.ordinal();
}
if (blockType == BlockType.CHEST || blockType == BlockType.DISPENSER || blockType == BlockType.SKULL)
{
return direction.ordinal();
}
if (blockType == BlockType.BUTTON)
{
if (direction.ordinal() >= 2)
{
return 6 - direction.ordinal();
}
}
if (blockType == BlockType.TRAPDOOR)
{
return direction.getOpposite().ordinal() - 2;
}
return -1;
}
static
{
BiMap<Integer, ForgeDirection> biMap;
biMap = HashBiMap.create(3);
biMap.put(0x0, UP);
biMap.put(0x4, EAST);
biMap.put(0x8, SOUTH);
MAPPINGS.put(BlockType.LOG, biMap);
biMap = HashBiMap.create(4);
biMap.put(0x0, SOUTH);
biMap.put(0x1, WEST);
biMap.put(0x2, NORTH);
biMap.put(0x3, EAST);
MAPPINGS.put(BlockType.BED, biMap);
biMap = HashBiMap.create(4);
biMap.put(0x2, EAST);
biMap.put(0x3, WEST);
biMap.put(0x4, NORTH);
biMap.put(0x5, SOUTH);
MAPPINGS.put(BlockType.RAIL_ASCENDING, biMap);
biMap = HashBiMap.create(4);
biMap.put(0x6, WEST);
biMap.put(0x7, NORTH);
biMap.put(0x8, EAST);
biMap.put(0x9, SOUTH);
MAPPINGS.put(BlockType.RAIL_CORNER, biMap);
biMap = HashBiMap.create(6);
biMap.put(0x1, EAST);
biMap.put(0x2, WEST);
biMap.put(0x3, SOUTH);
biMap.put(0x4, NORTH);
biMap.put(0x5, UP);
biMap.put(0x7, DOWN);
MAPPINGS.put(BlockType.LEVER, biMap);
biMap = HashBiMap.create(4);
biMap.put(0x0, WEST);
biMap.put(0x1, NORTH);
biMap.put(0x2, EAST);
biMap.put(0x3, SOUTH);
MAPPINGS.put(BlockType.DOOR, biMap);
biMap = HashBiMap.create(4);
biMap.put(0x0, NORTH);
biMap.put(0x1, EAST);
biMap.put(0x2, SOUTH);
biMap.put(0x3, WEST);
MAPPINGS.put(BlockType.REDSTONE_REPEATER, biMap);
biMap = HashBiMap.create(4);
biMap.put(0x1, EAST);
biMap.put(0x3, SOUTH);
biMap.put(0x7, NORTH);
biMap.put(0x9, WEST);
MAPPINGS.put(BlockType.MUSHROOM_CAP_CORNER, biMap);
biMap = HashBiMap.create(4);
biMap.put(0x2, NORTH);
biMap.put(0x4, WEST);
biMap.put(0x6, EAST);
biMap.put(0x8, SOUTH);
MAPPINGS.put(BlockType.MUSHROOM_CAP_SIDE, biMap);
biMap = HashBiMap.create(2);
biMap.put(0x0, SOUTH);
biMap.put(0x1, EAST);
MAPPINGS.put(BlockType.ANVIL, biMap);
}
}
@@ -1,7 +1,7 @@
package net.minecraftforge.event;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.item.ItemStack;
/**
@@ -1,7 +1,7 @@
package net.minecraftforge.event;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
@@ -2,23 +2,28 @@ package net.minecraftforge.event;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import cpw.mods.fml.common.ObfuscationReflectionHelper;
import cpw.mods.fml.common.eventhandler.Event.Result;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.entity.player.EntityPlayer.EnumStatus;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityBrewingStand;
import net.minecraft.util.BlockPos;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
@@ -26,45 +31,60 @@ import net.minecraft.world.WorldSettings;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.storage.IPlayerFileData;
import net.minecraft.world.storage.SaveHandler;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.IExtendedEntityProperties;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.event.brewing.PotionBrewEvent;
import net.minecraftforge.event.brewing.PotionBrewedEvent;
import net.minecraftforge.event.entity.EntityEvent;
import net.minecraftforge.event.entity.EntityStruckByLightningEvent;
import net.minecraftforge.event.entity.PlaySoundAtEntityEvent;
import net.minecraftforge.event.entity.item.ItemExpireEvent;
import net.minecraftforge.event.entity.living.LivingHealEvent;
import net.minecraftforge.event.entity.living.LivingPackSizeEvent;
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
import net.minecraftforge.event.entity.living.LivingSpawnEvent.AllowDespawn;
import net.minecraftforge.event.entity.living.ZombieEvent.SummonAidEvent;
import net.minecraftforge.event.entity.player.BonemealEvent;
import net.minecraftforge.event.entity.player.EntityInteractEvent;
import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
import net.minecraftforge.event.entity.player.FillBucketEvent;
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
import net.minecraftforge.event.entity.player.PlayerDropsEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.player.PlayerFlyableFallEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
import net.minecraftforge.event.entity.player.PlayerUseItemEvent;
import net.minecraftforge.event.entity.player.PlayerWakeUpEvent;
import net.minecraftforge.event.entity.player.UseHoeEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.BlockEvent.MultiPlaceEvent;
import net.minecraftforge.event.world.BlockEvent.PlaceEvent;
import net.minecraftforge.event.world.ExplosionEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.Event.Result;
public class ForgeEventFactory
{
public static MultiPlaceEvent onPlayerMultiBlockPlace(EntityPlayer player, List<BlockSnapshot> blockSnapshots, ForgeDirection direction)
public static MultiPlaceEvent onPlayerMultiBlockPlace(EntityPlayer player, List<BlockSnapshot> blockSnapshots, EnumFacing direction)
{
Block placedAgainst = blockSnapshots.get(0).world.getBlock(blockSnapshots.get(0).x + direction.getOpposite().offsetX, blockSnapshots.get(0).y + direction.getOpposite().offsetY, blockSnapshots.get(0).z + direction.getOpposite().offsetZ);
BlockSnapshot snap = blockSnapshots.get(0);
IBlockState placedAgainst = snap.world.getBlockState(snap.pos.offset(direction.getOpposite()));
MultiPlaceEvent event = new MultiPlaceEvent(blockSnapshots, placedAgainst, player);
MinecraftForge.EVENT_BUS.post(event);
return event;
}
public static PlaceEvent onPlayerBlockPlace(EntityPlayer player, BlockSnapshot blockSnapshot, ForgeDirection direction)
public static PlaceEvent onPlayerBlockPlace(EntityPlayer player, BlockSnapshot blockSnapshot, EnumFacing direction)
{
Block placedAgainst = blockSnapshot.world.getBlock(blockSnapshot.x + direction.getOpposite().offsetX, blockSnapshot.y + direction.getOpposite().offsetY, blockSnapshot.z + direction.getOpposite().offsetZ);
IBlockState placedAgainst = blockSnapshot.world.getBlockState(blockSnapshot.pos.offset(direction.getOpposite()));
PlaceEvent event = new PlaceEvent(blockSnapshot, placedAgainst, player);
MinecraftForge.EVENT_BUS.post(event);
return event;
@@ -77,26 +97,15 @@ public class ForgeEventFactory
return event.success;
}
@Deprecated // Location version below
public static float getBreakSpeed(EntityPlayer player, Block block, int metadata, float original)
public static float getBreakSpeed(EntityPlayer player, IBlockState state, float original, BlockPos pos)
{
return getBreakSpeed(player, block, metadata, original, 0, -1, 0);
}
public static float getBreakSpeed(EntityPlayer player, Block block, int metadata, float original, int x, int y, int z)
{
PlayerEvent.BreakSpeed event = new PlayerEvent.BreakSpeed(player, block, metadata, original, x, y, z);
PlayerEvent.BreakSpeed event = new PlayerEvent.BreakSpeed(player, state, original, pos);
return (MinecraftForge.EVENT_BUS.post(event) ? -1 : event.newSpeed);
}
@Deprecated
public static PlayerInteractEvent onPlayerInteract(EntityPlayer player, Action action, int x, int y, int z, int face)
public static PlayerInteractEvent onPlayerInteract(EntityPlayer player, Action action, World world, BlockPos pos, EnumFacing face)
{
return onPlayerInteract(player, action, x, y, z, face, null);
}
public static PlayerInteractEvent onPlayerInteract(EntityPlayer player, Action action, int x, int y, int z, int face, World world)
{
PlayerInteractEvent event = new PlayerInteractEvent(player, action, x, y, z, face, world);
PlayerInteractEvent event = new PlayerInteractEvent(player, action, pos, face, world);
MinecraftForge.EVENT_BUS.post(event);
return event;
}
@@ -125,9 +134,9 @@ public class ForgeEventFactory
return event.getResult();
}
public static List<BiomeGenBase.SpawnListEntry> getPotentialSpawns(WorldServer world, EnumCreatureType type, int x, int y, int z, List<BiomeGenBase.SpawnListEntry> oldList)
public static List<BiomeGenBase.SpawnListEntry> getPotentialSpawns(WorldServer world, EnumCreatureType type, BlockPos pos, List<BiomeGenBase.SpawnListEntry> oldList)
{
WorldEvent.PotentialSpawns event = new WorldEvent.PotentialSpawns(world, type, x, y, z, oldList);
WorldEvent.PotentialSpawns event = new WorldEvent.PotentialSpawns(world, type, pos, oldList);
if (MinecraftForge.EVENT_BUS.post(event))
{
return null;
@@ -149,9 +158,9 @@ public class ForgeEventFactory
return event.displayname;
}
public static float fireBlockHarvesting(ArrayList<ItemStack> drops, World world, Block block, int x, int y, int z, int meta, int fortune, float dropChance, boolean silkTouch, EntityPlayer player)
public static float fireBlockHarvesting(List<ItemStack> drops, World world, BlockPos pos, IBlockState state, int fortune, float dropChance, boolean silkTouch, EntityPlayer player)
{
BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(x, y, z, world, block, meta, fortune, dropChance, drops, player, silkTouch);
BlockEvent.HarvestDropsEvent event = new BlockEvent.HarvestDropsEvent(world, pos, state, fortune, dropChance, drops, player, silkTouch);
MinecraftForge.EVENT_BUS.post(event);
return event.dropChance;
}
@@ -226,6 +235,126 @@ public class ForgeEventFactory
MinecraftForge.EVENT_BUS.post(new PlayerEvent.LoadFromFile(player, dir, uuidString));
}
public static IChatComponent onClientChat(byte type, IChatComponent message)
{
ClientChatReceivedEvent event = new ClientChatReceivedEvent(type, message);
return MinecraftForge.EVENT_BUS.post(event) ? null : event.message;
}
public static int onHoeUse(ItemStack stack, EntityPlayer player, World worldIn, BlockPos pos)
{
UseHoeEvent event = new UseHoeEvent(player, stack, worldIn, pos);
if (MinecraftForge.EVENT_BUS.post(event)) return -1;
if (event.getResult() == Result.ALLOW)
{
stack.damageItem(1, player);
return 1;
}
return 0;
}
public static int onApplyBonemeal(EntityPlayer player, World world, BlockPos pos, IBlockState state, ItemStack stack)
{
BonemealEvent event = new BonemealEvent(player, world, pos, state);
if (MinecraftForge.EVENT_BUS.post(event)) return -1;
if (event.getResult() == Result.ALLOW)
{
if (!world.isRemote)
stack.stackSize--;
return 1;
}
return 0;
}
public static ItemStack onBucketUse(EntityPlayer player, World world, ItemStack stack, MovingObjectPosition target)
{
FillBucketEvent event = new FillBucketEvent(player, stack, world, target);
if (MinecraftForge.EVENT_BUS.post(event)) return stack;
if (event.getResult() == Result.ALLOW)
{
if (player.capabilities.isCreativeMode)
return stack;
if (--stack.stackSize <= 0)
return event.result;
if (!player.inventory.addItemStackToInventory(event.result))
player.dropPlayerItemWithRandomChoice(event.result, false);
return stack;
}
return null;
}
public static boolean canEntityUpdate(Entity entity)
{
EntityEvent.CanUpdate event = new EntityEvent.CanUpdate(entity);
MinecraftForge.EVENT_BUS.post(event);
return event.canUpdate;
}
public static String onPlaySoundAt(Entity entity, String name, float volume, float pitch)
{
PlaySoundAtEntityEvent event = new PlaySoundAtEntityEvent(entity, name, volume, pitch);
MinecraftForge.EVENT_BUS.post(event);
return event.name;
}
public static int onItemExpire(EntityItem entity, ItemStack item)
{
if (item == null) return -1;
ItemExpireEvent event = new ItemExpireEvent(entity, (item.getItem() == null ? 6000 : item.getItem().getEntityLifespan(item, entity.worldObj)));
if (!MinecraftForge.EVENT_BUS.post(event)) return -1;
return event.extraLife;
}
public static int onItemPickup(EntityItem entityItem, EntityPlayer entityIn, ItemStack itemstack)
{
Event event = new EntityItemPickupEvent(entityIn, entityItem);
if (MinecraftForge.EVENT_BUS.post(event)) return -1;
return event.getResult() == Result.ALLOW ? 1 : 0;
}
public static void onPlayerDrops(EntityPlayer player, DamageSource cause, List<EntityItem> capturedDrops, boolean recentlyHit)
{
PlayerDropsEvent event = new PlayerDropsEvent(player, cause, capturedDrops, recentlyHit);
if (!MinecraftForge.EVENT_BUS.post(event))
{
for (EntityItem item : capturedDrops)
{
player.joinEntityItemWithWorld(item);
}
}
}
public static boolean canInteractWith(EntityPlayer player, Entity entity)
{
return !MinecraftForge.EVENT_BUS.post(new EntityInteractEvent(player, entity));
}
public static EnumStatus onPlayerSleepInBed(EntityPlayer player, BlockPos pos)
{
PlayerSleepInBedEvent event = new PlayerSleepInBedEvent(player, pos);
MinecraftForge.EVENT_BUS.post(event);
return event.result;
}
public static void onPlayerWakeup(EntityPlayer player, boolean wakeImmediatly, boolean updateWorldFlag, boolean setSpawn)
{
MinecraftForge.EVENT_BUS.post(new PlayerWakeUpEvent(player, wakeImmediatly, updateWorldFlag, setSpawn));
}
public static void onPlayerFall(EntityPlayer player, float distance, float multiplier)
{
MinecraftForge.EVENT_BUS.post(new PlayerFlyableFallEvent(player, distance, multiplier));
}
public static void onPlayerClone(EntityPlayer player, EntityPlayer oldPlayer, boolean wasDeath)
{
MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.player.PlayerEvent.Clone(player, oldPlayer, wasDeath));
}
public static boolean onExplosionStart(World world, Explosion explosion)
{
return MinecraftForge.EVENT_BUS.post(new ExplosionEvent.Start(world, explosion));
@@ -236,11 +365,12 @@ public class ForgeEventFactory
//Filter entities to only those who are effected, to prevent modders from seeing more then will be hurt.
/* Enable this if we get issues with modders looping to much.
Iterator<Entity> itr = list.iterator();
Vec3 p = explosion.getPosition();
while (itr.hasNext())
{
Entity e = itr.next();
double dist = e.getDistance(explosion.explosionX, explosion.explosionY, explosion.explosionZ) / diameter;
if (dist > 1.0F) itr.remove();
double dist = e.getDistance(p.xCoord, p.yCoord, p.zCoord) / diameter;
if (e.func_180427_aV() || dist > 1.0F) itr.remove();
}
*/
MinecraftForge.EVENT_BUS.post(new ExplosionEvent.Detonate(world, explosion, list));
Loaded 100 of 458 files, more files were not shown because too many files have changed in this diff. Show more