Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Reika

Members
  • Joined

  • Last visited

Everything posted by Reika

  1. I am, yes, but I got bigger problems when I was not. If server-only, it was leaving ghost items on the ground, and with client only, it did not even absorb them.
  2. I made an item vacuum that absorbs the item drops around it and stores them in its own internal inventory. It works, but with one bug: When given multiple different stacks of the same ID, it will start losing items or getting extras. The gain rate is about 0.2 - 2%, whereas the loss rate, while usually zero, has, rarely, exceeded 76000% (36 stacks -> 3 items). Why is it doing this? Also worth noting: it was duplicating everything (running the method twice per call, for a total of 4 times (2x server + 2x client) when I let it run the absorb code every tick, but when I switched that to every 2 ticks, that bug stopped and this new subtler one arose. Here is my code: public void updateEntity() { tickcount++; if (this.power < MINPOWER) return; if (tickcount < 2) return; tickcount = 0; this.suck(this.worldObj, this.xCoord, this.yCoord, this.zCoord); this.absorb(this.worldObj, this.xCoord, this.yCoord, this.zCoord); } public void suck(World world, int x, int y, int z) { AxisAlignedBB box = this.getBox(world, x, y, z); List inbox = world.getEntitiesWithinAABB(EntityItem.class, box); for (int i = 0; i < inbox.size(); i++) { EntityItem ent = (EntityItem)inbox.get(i); double dd = 8.0D; double dx = (this.xCoord - ent.posX) / dd; double dy = (this.yCoord - ent.posY) / dd; double dz = (this.zCoord - ent.posZ) / dd; double ddt = ReikaMathLibrary.py3d(dx, dy, dz); double dd1 = 1.0D - ddt; if (dd1 > 0.0D) { dd1 *= dd1; ent.motionX += dx / ddt * dd1 * 0.2D; ent.motionY += dy / ddt * dd1 * 0.2D; ent.motionZ += dz / ddt * dd1 * 0.2D; } } } public void absorb(World world, int x, int y, int z) { AxisAlignedBB close = AxisAlignedBB.getBoundingBox(this.xCoord, this.yCoord, this.zCoord, this.xCoord+1, this.yCoord+1, this.zCoord+1).expand(0.25D, 0.25D, 0.25D); List closeitems = world.getEntitiesWithinAABB(EntityItem.class, close); for (int i = 0; i < closeitems.size(); i++) { EntityItem ent = (EntityItem)closeitems.get(i); ItemStack is = ent.getEntityItem(); int targetslot = this.checkForStack(is); if (targetslot != -1) { if (this.inventory[targetslot] == null) this.inventory[targetslot] = new ItemStack(is.itemID, is.stackSize, is.getItemDamage()); else this.inventory[targetslot].stackSize += is.stackSize; } else { return; } ent.setDead(); world.playSoundEffect(x+0.5, y+0.5, z+0.5, "random.pop", 0.1F+0.5F*par5Random.nextFloat(), par5Random.nextFloat()); } } public int checkForStack(ItemStack is) { int target = -1; int id = is.itemID; int meta = is.getItemDamage(); int size = is.stackSize; int firstempty = -1; for (int k = 0; k < this.inventory.length; k++) { //Find first empty slot if (inventory[k] == null) { firstempty = k; k = inventory.length; } } for (int j = 0; j < this.inventory.length; j++) { if (inventory[j] != null) { if (inventory[j].itemID == id && inventory[j].getItemDamage() == meta) { if (inventory[j].stackSize+size <= is.getMaxStackSize()) { target = j; j = inventory.length; } else { int diff = is.getMaxStackSize() - inventory[j].stackSize; inventory[j].stackSize += diff; is.stackSize -= diff; } } } } if (target == -1) target = firstempty; return target; } public AxisAlignedBB getBox(World world, int x, int y, int z) { int expand = 5; AxisAlignedBB box = AxisAlignedBB.getBoundingBox(this.xCoord, this.yCoord, this.zCoord, this.xCoord+1, this.yCoord+1, this.zCoord+1).expand(expand, expand, expand); return box; }
  3. OK...this is strange. I have not changed any of my rendering code (though I have added classes like new Tile Entities, new GUIs, and the like), but the behavior of my glitch changed. In the OP I said I could limit it to my custom creative tab by disabling 3 renders...now it is limited there even with the renders enabled... This is an improvement, but HOW did it change itself?
  4. I tried that, it causes no change.
  5. It works now, but given that I was working from that tutorial - my PacketHandler is a copy-and-paste of its code - I question its use if it caused this much headache. Of course, in hindsight one remembers one of the opening lines of the tutorial, which says the tutorial will not actually show how to use the packets usefully... Now, I am left with one other, smaller, glitch. My button toggles the state of a variable in the Tile Entity, and should update the GUI to match (switch a variable inside the Gui Class which controls a string inside a button constructor). The Tile Entity updates and behaves correctly, but the GUI must be closed and reopened, manually, to change...why? (Even more interesting: before I set it to set the GUI class variable to be equal to the one in the Tile Entity, it would only update on world reload (save/reenter).)
  6. Everything but block was in the OP, but here is my block code: public BlockBorer(int blockID, int textureID) { super(blockID, textureID, Material.iron); setHardness(4F); setResistance(10F); setLightValue(0F); setStepSound(soundMetalFootstep); this.requiresSelfNotify[this.blockID] = true; this.blockIndexInTexture = 57; setCreativeTab(mod_RotaryCraft.tabRotary); } public void addCreativeItems(ArrayList list) { list.add(new ItemStack(this)); } /** * Returns the TileEntity used by this block. */ public TileEntity createNewTileEntity(World world) { return new TileEntityBorer(); } public int idDropped(int par1, Random par2Random, int par3) { return this.blockID; } public int damageDropped(int par1) { return 0; } public int quantityDropped(Random par1Random) { return 1; } /** * Called upon block activation (left or right click on the block.). The three integers represent x,y,z of the * block. */ public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer ep, int par6, float par7, float par8, float par9) { if (world.isRemote) { return true; } TileEntityBorer borer = (TileEntityBorer)world.getBlockTileEntity(x, y, z); if (borer != null) { ep.openGui(mod_RotaryCraft.instance, 9, world, x, y, z); //ModLoader.openGUI(ep, new GuiBorer()); } return true; } public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) //Directional code { int i = MathHelper.floor_double((double)((par5EntityLiving.rotationYaw * 4F) / 360F) + 0.5D); while (i > 3) i -= 4; while (i < 0) i += 4; switch (i) { case 0: par1World.setBlockMetadataWithNotify(par2, par3, par4, 2); break; case 1: par1World.setBlockMetadataWithNotify(par2, par3, par4, 1); break; case 2: par1World.setBlockMetadataWithNotify(par2, par3, par4, 3); break; case 3: par1World.setBlockMetadataWithNotify(par2, par3, par4, 0); break; } this.metadata = par1World.getBlockMetadata(par2, par3, par4); } @Override public String getTextureFile(){ return "/Reika/RotaryCraft/textures.png"; //return the block texture where the block texture is saved in }
  7. I used an online tutorial to accomplish what BuildCraft, Redpower, and other big mods do to render custom-modelled blocks as 3D items in the inventory, using the ItemRendering system... ...And it caused a very strange error. Blocks - and only full-cube "Render Type 0" blocks - in the inventory will, when under a cursor, in the hotbar, or when my custom creative inventory tab is open, render rather darker than normal. Even more strangely, if I disable the rendering of a few of my custom blocks (Fan, Shaft, and Bridge Emitter - see code), this restricts to only in my custom inventory tab. My ItemRenderer code: public class ItemMachineRenderer implements IItemRenderer { private ModelAC acModel; private ModelAerosolizer aeroModel; private ModelBevel bevelModel; private ModelBridge bridgeModel; private ModelClutch clutchModel; private ModelCombustion combustionModel; private ModelCompactor compactorModel; private ModelDC dcModel; private ModelExtractor extractorModel; private ModelFan fanModel; private ModelFlywheel flywheelModel; private ModelGearbox gearModel; private ModelGearbox16 gearModel16; private ModelGearbox8 gearModel8; private ModelGearbox4 gearModel4; private ModelHRay rayModel; private ModelLamp lampModel; private ModelPulseFurnace pulseModel; private ModelPump pumpModel; private ModelReservoir reservoirModel; private ModelShaft shaftModel; private ModelShaftV shaftvModel; private ModelSteam steamModel; private int Renderid; private int engineType; private int metadata; private float floatControl; //public static final float cheatControl = -200F; public ItemMachineRenderer(int id) { acModel = new ModelAC(); aeroModel = new ModelAerosolizer(); bevelModel = new ModelBevel(); bridgeModel = new ModelBridge(); clutchModel = new ModelClutch(); combustionModel = new ModelCombustion(); compactorModel = new ModelCompactor(); dcModel = new ModelDC(); extractorModel = new ModelExtractor(); fanModel = new ModelFan(); flywheelModel = new ModelFlywheel(); gearModel = new ModelGearbox(); gearModel16 = new ModelGearbox16(); gearModel8 = new ModelGearbox8(); gearModel4 = new ModelGearbox4(); rayModel = new ModelHRay(); lampModel = new ModelLamp(); pulseModel = new ModelPulseFurnace(); pumpModel = new ModelPump(); reservoirModel = new ModelReservoir(); shaftModel = new ModelShaft(); shaftvModel = new ModelShaftV(); steamModel = new ModelSteam(); Renderid = id; if (id == 0) { } if (id == { switch(this.metadata/4) { case 0: floatControl = -1000; break; case 1: floatControl = -2000; break; case 2: floatControl = -3000; break; case 3: floatControl = -4000; break; } } } @Override public boolean handleRenderType(ItemStack item, ItemRenderType type) { //this.metadata = item.getItemDamage(); if (item.itemID == mod_RotaryCraft.fan.blockID) return true; if (item.itemID == mod_RotaryCraft.aerosolizer.blockID) return true; if (item.itemID == mod_RotaryCraft.engine.blockID) return true; if (item.itemID == mod_RotaryCraft.bridgeemitter.blockID) return true; if (item.itemID == mod_RotaryCraft.clutch.blockID) return true; if (item.itemID == mod_RotaryCraft.compactor.blockID) return true; if (item.itemID == mod_RotaryCraft.extractor.blockID) return true; if (item.itemID == mod_RotaryCraft.floodlight.blockID) return true; if (item.itemID == mod_RotaryCraft.flywheel.blockID) return true; if (item.itemID == mod_RotaryCraft.gbevel.blockID) return true; if (item.itemID == mod_RotaryCraft.gearbox.blockID) return true; if (item.itemID == mod_RotaryCraft.heatray.blockID) return true; if (item.itemID == mod_RotaryCraft.pulsejet.blockID) return true; if (item.itemID == mod_RotaryCraft.pump.blockID) return true; if (item.itemID == mod_RotaryCraft.reservoir.blockID) return true; if (item.itemID == mod_RotaryCraft.shaft.blockID) return true; if (item.itemID == mod_RotaryCraft.splitter.blockID) return true; return false; } @Override public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) { if (type.equals(helper.BLOCK_3D)) return false; return true; } @Override public void renderItem(ItemRenderType type, ItemStack item, Object... data) { switch (Renderid) { case 0: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityEngine(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 1: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityAerosolizer(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 2: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityGearBevel(), 0.0D, -0.1D, 0.0D, 0.0F); break; case 3: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityBridgeEmitter(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 4: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityClutch(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 5: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityCompactor(), 0.0D, -0.1D, 0.0D, 0.0F); break; case 6: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityExtractor(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 7: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityFan(), 0.0D, -0.1D, 0.0D, 0.0F); break; case 8: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityFlywheel(), 0.0D, 0.0D, 0.0D, floatControl); break; case 9: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityGearbox(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 10: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityHeatRay(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 11: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityFloodlight(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 12: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityPulseFurnace(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 13: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityPump(), 0.0D, 0.0D, 0.0D, 0.0F); break; case 14: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityReservoir(), 0.0D, -0.1D, 0.0D, 0.0F); break; case 15: TileEntityRenderer.instance.renderTileEntityAt(new TileEntityShaft(), 0.0D, 0.0D, 0.0D, 0.0F); break; } } And the relevant part of my ClientProxy: MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.engine.blockID, new ItemMachineRenderer(0)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.aerosolizer.blockID, new ItemMachineRenderer(1)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.gbevel.blockID, new ItemMachineRenderer(2)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.bridgeemitter.blockID, new ItemMachineRenderer(3)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.clutch.blockID, new ItemMachineRenderer(4)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.compactor.blockID, new ItemMachineRenderer(5)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.extractor.blockID, new ItemMachineRenderer(6)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.fan.blockID, new ItemMachineRenderer(7)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.flywheel.blockID, new ItemMachineRenderer(); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.gearbox.blockID, new ItemMachineRenderer(9)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.heatray.blockID, new ItemMachineRenderer(10)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.floodlight.blockID, new ItemMachineRenderer(11)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.pulsejet.blockID, new ItemMachineRenderer(12)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.pump.blockID, new ItemMachineRenderer(13)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.reservoir.blockID, new ItemMachineRenderer(14)); MinecraftForgeClient.registerItemRenderer(mod_RotaryCraft.shaft.blockID, new ItemMachineRenderer(15));
  8. I am aware this has been asked before, but no thread I have found has had a solution that worked for me. What I need to do is simple and probably will look excessively newbie-like to those of you experienced with the 1.3+ integrated server. I have a GUI with several custom buttons, and I want clicking these buttons to be able to update the state of variables inside the Tile Entity. I started off with old 1.2.5-style code, and got the "client side effect but no server update" glitch; switching to using the packet handlers in the forge tutorials now leaves the changes not happening at all. The relevant sections of my code: Tile Entity: @Override public Packet getDescriptionPacket() { NBTTagCompound var1 = new NBTTagCompound(); this.writeToNBT(var1); return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 2, var1); } @Override public void onDataPacket(INetworkManager netManager, Packet132TileEntityData packet) { readFromNBT(packet.customParam1); } @Override public void handlePacketData(INetworkManager network, Packet250CustomPayload packet, EntityPlayer player, ByteArrayDataInput dataStream) { try { this.mode = dataStream.readInt(); } catch (Exception e) { System.out.println("[RotaryCraft] Error while handling tile entity packet."); e.printStackTrace(); } } Gui: public GuiBorer(InventoryPlayer par1InventoryPlayer, TileEntityBorer par2TileEntityBorer, EntityPlayer par5player) { super(new ContainerBorer(par1InventoryPlayer, par2TileEntityBorer)); borer = par2TileEntityBorer; this.ySize = 215; dropstatus = "Drops On"; player = par5player; drops = borer.drops; mode = borer.mode; } @Override public void initGui() { int j = (width - xSize) / 2; int k = (height - ySize) / 2; this.controlList.add(new GuiButton(0, j+8, -1+k+32, 72, 20, "1x1 Square")); this.controlList.add(new GuiButton(1, j+8, -1+k+52, 72, 20, "1x2 Hallway")); this.controlList.add(new GuiButton(2, j+8, -1+k+72, 72, 20, "2x2 Square")); this.controlList.add(new GuiButton(3, j+8, -1+k+92, 72, 20, "3x3 Square")); this.controlList.add(new GuiButton(4, j+8, -1+k+112, 72, 20, "5x5 Circle")); this.controlList.add(new GuiButton(5, j+8, -1+k+132, 72, 20, "7x4 Archway")); this.controlList.add(new GuiButton(6, j+8, -1+k+152, 72, 20, "4x4 Tunnel")); if (drops) this.controlList.add(new GuiButton(7, j+95, -1+k+32, 72, 20, "Drops On")); else this.controlList.add(new GuiButton(7, j+95, -1+k+32, 72, 20, "Drops Off")); } public void toggleDrops() { if (drops) { dropstatus = "Drops Off"; drops = false; } else { dropstatus = "Drops On"; drops = true; } this.sendPacket(1); } public void updateMode(int mode) { borer.mode = (byte)mode; } /** * Returns true if this GUI should pause the game when it is displayed in single-player */ public boolean doesGuiPauseGame() { return true; } @Override public void actionPerformed(GuiButton button) { if (button.id == 7) { this.toggleDrops(); } if (button.id < 7) { //this.updateMode(button.id); mode = button.id; } this.sendPacket(2); this.refreshScreen(); } public void sendPacket(int a) { ByteArrayOutputStream bos = new ByteArrayOutputStream(; DataOutputStream outputStream = new DataOutputStream(bos); try { if (a == 1) outputStream.writeBoolean(drops); if (a == 2) outputStream.writeInt(mode); } catch (Exception ex) { ex.printStackTrace(); } Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "GenericRandom"; packet.data = bos.toByteArray(); packet.length = bos.size(); Side side = FMLCommonHandler.instance().getEffectiveSide(); if (side == Side.SERVER) { // We are on the server side. EntityPlayerMP player2 = (EntityPlayerMP) player; } else if (side == Side.CLIENT) { // We are on the client side. EntityClientPlayerMP player2 = (EntityClientPlayerMP) player; this.mc.getSendQueue().addToSendQueue(packet); } else { // We are on the Bukkit server. } } Container: public class ContainerBorer extends Container { private TileEntityBorer borer; public ContainerBorer(InventoryPlayer par1InventoryPlayer, TileEntityBorer par2TileEntityBorer) { borer = par2TileEntityBorer; int posX = borer.xCoord; int posY = borer.yCoord; int posZ = borer.zCoord; } public boolean canInteractWith(EntityPlayer par1EntityPlayer) { return borer.isUseableByPlayer(par1EntityPlayer); } } Packet Handler: import java.io.ByteArrayInputStream; import java.io.DataInputStream; import net.minecraft.network.INetworkManager; import net.minecraft.network.packet.Packet250CustomPayload; import cpw.mods.fml.common.network.IPacketHandler; import cpw.mods.fml.common.network.Player; public class ClientPacketHandler implements IPacketHandler { @Override public void onPacketData(INetworkManager manager, Packet250CustomPayload payload, Player player) { DataInputStream data = new DataInputStream(new ByteArrayInputStream(payload.data)); } } Excerpt from main mod class: @Mod( modid = "RotaryCraft", name="RotaryCraft", version="beta v0.1") @NetworkMod(clientSideRequired=true, serverSideRequired=false, channels={"GenericRandom"}, packetHandler = PacketHandler.class)
  9. That is what I ended up doing, yes.
  10. For your 3->1 example, yes, but not for mine, because additional code is required to ensure the order of steps is preserved. Without taking steps to do that, it would be possible to put input#4 into slot #2 and get output#4 (or even output #2!).
  11. The mod I am making has a machine that is basically a multistep furnace. That is, it has 8 slots - 4 input (where you can place items) and 4 output, one corresponding to each input slot and therefore each "stage" of the operation. Basically, I want to be able to have ore go in input #1, turn into dust in output #1, then that dust can be placed in input #2, which goes into output #2 as slurry, then that goes into input #3, turning into ore solutions in output #3, which can be placed in input#4, which turns into ore flakes in output #4. I want to make sure this order is preserved; I do not want the slots to be functionally interchangeable - I do not want one slot's recipes/item inputs being usable by another. Is there a way to do this? Also worth noting, the input and output items are all the same ID, differentiated by metadata, which is causing me problems for the addSmelting function (which does not seem to be metadata-sensitive). To make visualizing the process easier, here is the GUI image: EDIT: I got it working by sort of jury-rigging my own Slot objects, which can only have the "valid" items placed in them.
  12. That is an interesting, if rather difficult to execute, idea.
  13. Sure. There is a metadata-sensitive version of createNewTileEntity in the Block class, added by forge. And what if the metadata is used to control something totally different, like block direction, and the different "types" of Tile Entity would be determined from a variable in the "parent" tile Entity? Still possible? That is, could I have one class applicable for all the variations of the block, and depending on the state of a variable within it, another tile entity of another type?
  14. I do not really have any code, that is the problem. I tried copying most of RenderSign, and nothing happened. Rendering is FAR beyond my understanding.
  15. ...Noone?
  16. On a related note, is it feasible to combine two totally separate blocks, each with their own Tile Entities, containers, etc, into one ID, keeping the distinct tile entity classes?
  17. How would I go about rendering text on a block's surface in-world? I read TileEntitySign, TileEntitySignRenderer, and TileEntitySpecialRenderer, but beyond some obvious stuff like the use of FontRenderer.drawString(""), which did not work for me, I have no idea what any of it does.
  18. That appears to mean I have to fetch the metadata in the TileEntity and pass it back to the block, which is rather awkward, but that should work, yes.
  19. Well, I have solved my original problem, but another related one has come up. Is there any way to fetch the Tile Entity in a block file without having been passed the block's x,y,z? For example, if I want a block that actually has 24 different states, each of which have a different texture on one side of the block, how can I get the Tile Entity into getBlockTextureFromSideAndMetadata(int s, int dmg)? Simply using TileEntity**** tile = (TileEntity****)world.getBlockTileEntity does not work, as there is no way for this function to determine the coordinates of its "parent" block, or the world it is in. There is a "getBlockTileEntity" function in Block.java I can access, but it "will fall back to BlockContainer.getBlockEntity if this block is a BlockContainer", in the words of the documentation, and thus will return a new TileEntity, not the existing one. Now, I could of course just declare three integer variables x,y,z and one world variable and set them in onBlockAdded, but can I do it without creating additional variables (and thus more resources)? EDIT: No, even that does not work; it returns null every single time.
  20. Only if you use a TileEntitySpecialRenderer to do the rendering. You don't have to do that -- you can use an ordinary block renderer that uses information from the tile entity to decide what to draw. Given that I plan to use custom models - an issue for another time; function is going to be completed first - then I may well need to worry about that.
  21. Perhaps, yes. Back on topic, I tried the ItemBlock approach and it works. Basically, the itemblock places the block at the coordinates, then sets an internal tile entity variable, which is used by the code. Here is the code for my "dummy/test" block to do it: (No, my source is not normally this messy. I just did not care to keep this tidy, as it is a test.) ItemBlock: public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7) { if (par3World.getBlockId(par4, par5, par6) != Block.snow.blockID && par3World.getBlockId(par4, par5, par6) != Block.waterMoving.blockID && par3World.getBlockId(par4, par5, par6) != Block.lavaStill.blockID && par3World.getBlockId(par4, par5, par6) != Block.lavaMoving.blockID && par3World.getBlockId(par4, par5, par6) != Block.waterStill.blockID) { if (par7 == 0) --par5; if (par7 == 1) ++par5; if (par7 == 2) --par6; if (par7 == 3) ++par6; if (par7 == 4) --par4; if (par7 == 5) ++par4; if (!par3World.isAirBlock(par4, par5, par6) && par3World.getBlockMaterial(par4, par5, par6) != Material.water && par3World.getBlockMaterial(par4, par5, par6) != Material.lava) return false; } if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6)) { return false; } else { if (!par2EntityPlayer.capabilities.isCreativeMode) --par1ItemStack.stackSize; par3World.setBlockWithNotify(par4, par5, par6, mod_LearningMultiblocks.testblock.blockID); TileEntityTest te = (TileEntityTest)par3World.getBlockTileEntity(par4, par5, par6); if (te != null) { par3World.playSoundEffect(par4+0.5, par5+0.5, par6+0.5, "step.stone", 1F, 1F); te.type = par5-60; } return true; } } Tile Entity: package net.minecraft.src; public class TileEntityTest extends TileEntity { public int type; public void updateEntity() { //ModLoader.getMinecraftInstance().ingameGUI.addChatMessage(String.format("%d", this.type)); } /** * Writes a tile entity to NBT. */ public void writeToNBT(NBTTagCompound par1NBTTagCompound) { super.writeToNBT(par1NBTTagCompound); par1NBTTagCompound.setInteger("type", this.type); } /** * Reads a tile entity from NBT. */ public void readFromNBT(NBTTagCompound par1NBTTagCompound) { super.readFromNBT(par1NBTTagCompound); this.type = par1NBTTagCompound.getInteger("type"); } }
  22. http://i257.photobucket.com/albums/hh240/RadicalOne/AnnunakiSmileys/Vector_Smiley.png[/img] I do hope it succeeds as well. My fear is that it will, like 99% of mods, maybe get a few downloads then get forgotten forever. So I am trying to delay that as long as I can (ideally to infinity) by making this mod as big, advanced, and "still-to-get-better" as possible within my abilities and my ideas. Not a usual approach for someone's first mod, that is for certain...
  23. My concern was borne from the fact he says "retrieve the tile entity", which calls to my mind the this.worldObj.getBlockTileEntity() function. This would, in the case of using the same class for each one, always return the same result, resulting in no ability to differentiate them. But combining his idea with the previous poster's idea about NBT tags and it may well work. As for issues with lag, if a computer can Minecraft decently well (> 30 fps), then this mod should not have a drastic impact. Mine, though stronger than most, takes no performance hit at all (so far). These Tile Entities are not likely to exist in too large of quantities (as they will be expensive and for a specific purpose, not "decorative"/"world composition" like sand/dirt/stone/wood/bricks/etc). As for the rendering distance, thank you for the heads-up. While this is not a severe issue - if I do not find a solution I can still release the mod and put the issue on the "to do" list without impacting the mod's usability - it is good to be aware of.
  24. Now that definitely sounds like an interesting, feasible, and effective idea; I will try that, and will post my results soon. One side question: Will the fact that all of these separate block types share the same TileEntity class (differing only in internal control variables) be a stumbling block (no pun intended)?
  25. That would still be rather sloppy programming. Please elaborate. I have dug into those tile entities before, but not seen anything related to this. Also worth noting is that these blocks are going to be far more different than simply different textures - think along the lines of RedPower logic gates or subblocks. Yes, but that does not solve the problem of other Tile Entities being able to distinguish these blocks from each other ingame.

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.