bormoshka Posted September 8, 2012 Share Posted September 8, 2012 Hello again. I have a problem with saving value of TileEntity. I have items and blocks with metadata, so I can't storage angle there. When I place block - it's OK. But, when i reenter - all blocks rotated at 0 angle. Maybe I missed something. Before: After: BlockFlag.java: public class BlockFlag extends Block { private byte flagType; private Class flagEntityClass; private byte angle; public BlockFlag(int i, Class class1) { super(i, Material.cloth); flagEntityClass = class1; setHardness(1.5F); setResistance(1.5F); setStepSound(Block.soundWoodFootstep); setBlockName("Minecraft Standart"); this.setTextureFile(getTextureFile()); blockIndexInTexture = 5; this.setRequiresSelfNotify(); this.isBlockContainer = true; } public void setValue(Item anItemDrop, byte aFlagType) { flagType = aFlagType; //flagMetadata = aFlagMetadata; } public TileEntity getBlockEntity() { try { return (TileEntity)flagEntityClass.newInstance(); } catch (Exception exception) { throw new RuntimeException(exception); } } public TileEntity createTileEntity(World world, int metadata) { TileEntityFlag myTile = new TileEntityFlag(); myTile.setValues(flagType); myTile.onInventoryChanged(); return myTile; } public TileEntity createNewTileEntity(World var1) { TileEntityFlag tileEntityFlag = new TileEntityFlag(); return tileEntityFlag; } public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) { // NOT IMPORTANT } private boolean canPlaceFlagOn(World par1World, int par2, int par3, int par4) { // NOT IMPORTANT } protected int damageDropped(int par1) { return par1; } public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) { return canPlaceFlagOn(par1World, par2, par3 - 1, par4); } private boolean dropFlagIfCantStay(World par1World, int par2, int par3, int par4) { // NOT IMPORTANT } public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) { // NOT IMPORTANT } public int idDropped(int i, Random random, int j) { return UltimateExtender.itemFlag.shiftedIndex; } @SideOnly(Side.CLIENT) /** * returns a list of blocks with the same ID, but different meta (eg: wood returns 4 blocks) */ public void getSubBlocks(int par1, CreativeTabs par2CreativeTabs, List par3List) { // NOT IMPORTANT } public int quantityDropped(Random random) { return 1; } public int getRenderType() { return -1; } @Override public String getTextureFile() { return Params.TEXTURE_PATH_BLOCKS; } public boolean isOpaqueCube() { return false; } public boolean renderAsNormalBlock() { return false; } public void onBlockAdded(World par1World, int par2, int par3, int par4) { super.onBlockAdded(par1World, par2, par3, par4); TileEntityFlag myTile = (TileEntityFlag)this.createTileEntity(par1World, par1World.getBlockMetadata(par2, par3, par4)); par1World.setBlockTileEntity(par2, par3, par4, myTile); } public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) { TileEntityFlag myTile = (TileEntityFlag)par1World.getBlockTileEntity(par2, par3, par4); this.angle = (byte) (MathHelper.floor_double((double)(par5EntityLiving.rotationYaw + 180.0F) * 16.0F / 360.0F) & 15); myTile.angle = this.angle; myTile.onInventoryChanged(); } public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) { super.breakBlock(par1World, par2, par3, par4, par5, par6); par1World.removeBlockTileEntity(par2, par3, par4); } } ItemFlag.java public class ItemFlag extends Item { private int blockID; public static String[] flagNames = new String[]{"flag1","flag2","flag3","flag4","flag5","flag6","flag7","flag8", "flag9","flag10","flag11","flag12","flag13","flag14","flag15","flag16"}; public ItemFlag(int i, Block block) { super(i); blockID = block.blockID; this.setHasSubtypes(true); this.setMaxDamage(0); } public int getIconFromDamage(int par1) { int var2 = MathHelper.clamp_int(par1, 0, 15); return this.iconIndex + var2; } public String getItemNameIS(ItemStack par1ItemStack) { int var2 = MathHelper.clamp_int(par1ItemStack.getItemDamage(), 0, 15); return super.getItemName() + "." + flagNames[var2]; } @SideOnly(Side.CLIENT) /** * returns a list of items with the same ID, but different meta (eg: dye returns 16 items) */ public void getSubItems(int par1, CreativeTabs par2CreativeTabs, List par3List) { for (int var4 = 0; var4 < 16; ++var4) { par3List.add(new ItemStack(par1, 1, var4)); } } public int getMetadata(int par1) { return par1; } public int getBlockID() { return this.blockID; } public boolean tryPlaceIntoWorld(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10) { int var11 = par3World.getBlockId(par4, par5, par6); if (var11 == Block.snow.blockID) { par7 = 1; } else if (var11 != Block.vine.blockID && var11 != Block.tallGrass.blockID && var11 != Block.deadBush.blockID && (Block.blocksList[var11] == null || !Block.blocksList[var11].isBlockReplaceable(par3World, par4, par5, par6))) { 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 (par1ItemStack.stackSize == 0) { return false; } else if (!par2EntityPlayer.canPlayerEdit(par4, par5, par6)) { return false; } else if (par5 == 255 && Block.blocksList[this.blockID].blockMaterial.isSolid()) { return false; } else if (par3World.canPlaceEntityOnSide(this.blockID, par4, par5, par6, false, par7, par2EntityPlayer)) { Block var12 = Block.blocksList[this.blockID]; if (placeBlockAt(par1ItemStack, par2EntityPlayer, par3World, par4, par5, par6, par7, par8, par9, par10)) { par3World.playSoundEffect((double)((float)par4 + 0.5F), (double)((float)par5 + 0.5F), (double)((float)par6 + 0.5F), var12.stepSound.getStepSound(), (var12.stepSound.getVolume() + 1.0F) / 2.0F, var12.stepSound.getPitch() * 0.8F); --par1ItemStack.stackSize; } return true; } else { return false; } } public boolean placeBlockAt(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) { if (!world.setBlockAndMetadataWithNotify(x, y, z, this.blockID, this.getMetadata(stack.getItemDamage()))) { return false; } if (world.getBlockId(x, y, z) == this.blockID) { Block.blocksList[this.blockID].updateBlockMetadata(world, x, y, z, side, hitX, hitY, hitZ); Block.blocksList[this.blockID].onBlockPlacedBy(world, x, y, z, player); } return true; } } TileEntityFlag.java: public class TileEntityFlag extends TileEntity { public byte angle; private byte type; public void writeToNBT(NBTTagCompound par1NBTTagCompound) { super.writeToNBT(par1NBTTagCompound); par1NBTTagCompound.setByte("ang", this.angle); par1NBTTagCompound.setByte("type", this.type); } public void readFromNBT(NBTTagCompound par1NBTTagCompound) { super.readFromNBT(par1NBTTagCompound); this.type = par1NBTTagCompound.getByte("type"); this.angle = par1NBTTagCompound.getByte("ang"); } public void setAngle(byte i) { this.angle = i; } public int getAngle() { return this.angle; } public void setValues(byte i) { this.type = i; } public int getType() { return this.type; } } Quote Link to comment Share on other sites More sharing options...
atrain99 Posted September 8, 2012 Share Posted September 8, 2012 That should work. Quote So, what would happen if I did push that shiny red button over there? ... Really? ... Can I try it? ... Damn. Link to comment Share on other sites More sharing options...
bormoshka Posted September 8, 2012 Author Share Posted September 8, 2012 I don't know why, but its not. In Render i'm trying to get angle from TileEntity is it right? public void renderFlag(TileEntity tileEntity, double d, double d1, double d2, float f) { TileEntityFlag myTile = (TileEntityFlag)tileEntity; //System.out.println(myTile.getSkin()); float deg = (float)(myTile.getAngle() * 360) / 16.0F; int i = myTile.getType(); int j = myTile.getBlockMetadata(); GL11.glPushMatrix(); GL11.glTranslatef((float)d + 0.5F, (float)d1 + 1.5F, (float)d2 + 0.5F); GL11.glScalef(1.0F, 1.0F, 1.0F); GL11.glRotatef(180F, 0.0F, 0.0F, 1.0F); GL11.glRotatef(deg, 0.0F, 1.0F, 0.0F); bindTextureByName(getPath(i,j)); modelFlag.render(0.0625F); GL11.glPopMatrix(); } Quote Link to comment Share on other sites More sharing options...
DarkGuardsman Posted September 9, 2012 Share Posted September 9, 2012 Might want to send a packet to the client with the angle in it so the render can get the updated angle. Also might want to send what ever other info the client needs for the render as well. If you need help making packet stuff check out my gitup https://github.com/DarkGuardsman Quote http://i577.photobucket.com/albums/ss215/bobstrong/ModBannerMed.png[/img] Link to comment Share on other sites More sharing options...
bormoshka Posted September 9, 2012 Author Share Posted September 9, 2012 Thanks, I'll try. But I'm testing it in singleplayer and this value is saves and loads(after exit) propertly: public TileEntity createTileEntity(World world, int metadata) { TileEntityFlag myTile = new TileEntityFlag(); myTile.setValues(flagType); myTile.onInventoryChanged(); return myTile; } and this is not: public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) { TileEntityFlag myTile = (TileEntityFlag)par1World.getBlockTileEntity(par2, par3, par4); this.angle = (byte) (MathHelper.floor_double((double)(par5EntityLiving.rotationYaw + 180.0F) * 16.0F / 360.0F) & 15); myTile.angle = this.angle; myTile.onInventoryChanged(); } Quote Link to comment Share on other sites More sharing options...
DarkGuardsman Posted September 10, 2012 Share Posted September 10, 2012 Thanks, I'll try. But I'm testing it in singleplayer and this value is saves and loads(after exit) propertly: public TileEntity createTileEntity(World world, int metadata) { TileEntityFlag myTile = new TileEntityFlag(); myTile.setValues(flagType); myTile.onInventoryChanged(); return myTile; } and this is not: public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) { TileEntityFlag myTile = (TileEntityFlag)par1World.getBlockTileEntity(par2, par3, par4); this.angle = (byte) (MathHelper.floor_double((double)(par5EntityLiving.rotationYaw + 180.0F) * 16.0F / 360.0F) & 15); myTile.angle = this.angle; myTile.onInventoryChanged(); } You sure in 1.3.2 Minecraft single player is a lan server. I use to think it worked fine til a lot of my stuff stopped updating correctly. Namely the rotation of my Machines for several of my mods. Quote http://i577.photobucket.com/albums/ss215/bobstrong/ModBannerMed.png[/img] Link to comment Share on other sites More sharing options...
bormoshka Posted September 11, 2012 Author Share Posted September 11, 2012 You sure in 1.3.2 Minecraft single player is a lan server. I use to think it worked fine til a lot of my stuff stopped updating correctly. Namely the rotation of my Machines for several of my mods. Ok, maybe when i create TileEntity and change some values in createTileEntity(World world, int metadata) it works, but if I trying to change it from client side - it fails. That's why I must create proper packet exchange. So I looked in your code, made something that look pretty the same... but it fails again. So can you or someone that reads this help with this? Maybe manuals or something? Quote Link to comment Share on other sites More sharing options...
DarkGuardsman Posted September 11, 2012 Share Posted September 11, 2012 You sure in 1.3.2 Minecraft single player is a lan server. I use to think it worked fine til a lot of my stuff stopped updating correctly. Namely the rotation of my Machines for several of my mods. Ok, maybe when i create TileEntity and change some values in createTileEntity(World world, int metadata) it works, but if I trying to change it from client side - it fails. That's why I must create proper packet exchange. So I looked in your code, made something that look pretty the same... but it fails again. So can you or someone that reads this help with this? Maybe manuals or something? next chance i get i'll create a short tut on the subject, or at least raw code that can be copied. Quote http://i577.photobucket.com/albums/ss215/bobstrong/ModBannerMed.png[/img] Link to comment Share on other sites More sharing options...
Bandayd Posted September 12, 2012 Share Posted September 12, 2012 Ok, this if funny, I just went through this EXACT same problem, and for me the key lied in... signs! :-P If you look at how the signs metadata works, that's EXACTLY what you want... so, here's some of the legwork done for ya': Just look at ItemSign.java for how your ItemFlag.java should be BlockSign.java for how your BlockFlag.java should be TileEntitySign.java for how your TileEntityFlag.java should be Also, do NOT forget to do the following when your mod loads.... Make SURE you register your tileentity like this.... GameRegistry.registerTileEntity(TileEntityFlag.class, "ang"); Also, in your ItemFlag, you should probably pass the angle to it then using something like: int myAng = MathHelper.floor_double((double)((par2EntityPlayer.rotationYaw + 180.0F) * 16.0F / 360.0F) + 0.5D) & 15; (it just gets the angle from the player's angle) Now let me know if you still can't sort it out, but I believe most of what you're doing should be covered by the sign example. Also, you should really put the following line of code in your stuff so you can track what angle it's storing, and getting.... Minecraft mc = Minecraft.getMinecraft(); mc.thePlayer.sendChatMessage(""+ang); Now lastly, here's a brief overview of how your metadata should be working: When you place the flag ItemFlag gets the angle from the player, then it passes the data to the block's metadata The TileEntityFlag just handles the reading and writing of the metadata (which seems kinda repetitive and unnecessary to me, but that's how it is! :-P) The BlockFlag should then reads that metadata Now.... with all that said... are you sure you can't just extend the "Sign" class, override the render type and a few things, and call it good? :-P LOL Good luck to ya', let me know if you have any questions about my irrational ramblings! :-P I struggled with this same exact problem for a week though, and it took me that long, to reach this level of insanity (and yes, I finally got it working last night, due to registering my tileentity class) :-) Quote Link to comment Share on other sites More sharing options...
DarkGuardsman Posted September 12, 2012 Share Posted September 12, 2012 speaking of sign class there is a method in there to send a packet to the client with the sign text. You can change it up a bit to fit your needs. /** * signs and mobSpawners use this to send text and meta-data */ public Packet getAuxillaryInfoPacket() { String[] var1 = new String[4]; System.arraycopy(this.signText, 0, var1, 0, 4); return new Packet130UpdateSign(this.xCoord, this.yCoord, this.zCoord, var1); } change packet to Packet250 or what ever the custom packet is. I used this for a while till i need to update the server from the client. However if you want to do it the more reusable way, in which you can set it up to send any info to and from the server. Your packet Handler class public class PacketManager implements IPacketHandler { @Override public void onPacketData(NetworkManager network, Packet250CustomPayload packet, Player player) { try { ByteArrayDataInput data = ByteStreams.newDataInput(packet.data); int x = data.readInt(); int y = data.readInt(); int z = data.readInt(); //the following two are not used but can be for sorting packets by ID and restricting packet reading by lengths int id = data.readInt();//packet ID your welcome to set to zero int l = data.readInt(); //packet length a safety var to make sure only data is read. EntityPlayer ePlayer = (EntityPlayer) player; if(ePlayer != null) { TileEntity tileEntity = ePlayer.worldObj.getBlockTileEntity(x, y, z); if(tileEntity != null) { if(tileEntity instanceof IPacketReceiver) { ((IPacketReceiver) tileEntity). handlePacketData(network,packet.channel, data); } } } } catch(Exception e) { e.printStackTrace(); } } /** * * @param sender - TileEntity sending this packet * @param channelName - channel name "channelName" * @param id - packet id * @param sendData - list of Integers to be sent is read after main data * @param string - list of strings to be sent is read last * @return a constructed packet ready to be sent */ //If your looking for a better version check out Calclavia's PacketManager his is very well developed public static Packet TECommonPacket(TileEntity sender, String channelName,int id, int[] sendData, String[] string) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); DataOutputStream data = new DataOutputStream(bytes); try { data.writeInt(sender.xCoord); data.writeInt(sender.yCoord); data.writeInt(sender.zCoord); data.writeInt(id); data.writeInt(3+sendData.length); //only writes ints and string you can change this to write anything for(int i =0; i < sendData.length; i++) { data.writeInt(sendData[i]); } for(int i =0; i < string.length; i++) { data.writeUTF(string[i]); } } catch (IOException e) { e.printStackTrace(); } Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "ChannelName";//TODO change to registered channel for you mod packet.data = bytes.toByteArray(); packet.length = packet.data.length; packet.isChunkDataPacket = true; return packet; } } Here is the IPacketHandler interface. Implement this in every tileEntity you need to send packets with. package npc.Network; import net.minecraft.src.NetworkManager; import com.google.common.io.ByteArrayDataInput; public interface IPacketReceiver { /** * Sends the tileEntity the rest of the data */ public void handlePacketData(NetworkManager network, String channel, ByteArrayDataInput data); } Your tileEntity public class TileEntity extends TileEntity{ @Override public void updateEntity() { //highly suggest setting a timer function to only send a packet every so often, also you can change send packetToAll to sendToAll around to reduce lag furthur if(!worldObj.isRemote) { FMLCommonHandler.instance().getMinecraftServerInstance().getConfigurationManager().sendPacketToAllPlayers(getPacket()); } super.updateEntity(); } public Packet getPacket() { int[] data = this.getSendLoadInt(); ; if(data == null) { data = new int[]{}; } String[] string = this.getSendLoadStr(); ; if(string == null) { string = new String[]{}; } return PacketManager.TECommonPacket(this, "ChannelName",0, data,string );//TODO change channel name } @Override public int[] getSendLoadInt() { return new int[] {angle,type,etc}; //TODO //array that stores all int that need to be sent by packet make sure what is in here ir read in handlePacketData } @Override public void handlePacketData(NetworkManager network, String channel, ByteArrayDataInput data) { if(worldObj.isRemote) { //this.angle = (int)data.readInt(); //this.type = (int)data.readInt(); } } public void updateInfo(int[] sRange) { if(sRange.length == 5) { this.minX = sRange[1]; this.minZ = sRange[2]; this.maxX = sRange[3]; this.maxZ = sRange[4]; } } } } in you main mod class make sure you have this @NetworkMod(channels = { "ChannelName" }, clientSideRequired = true, serverSideRequired = false, packetHandler = PacketManager.class) Quote http://i577.photobucket.com/albums/ss215/bobstrong/ModBannerMed.png[/img] Link to comment Share on other sites More sharing options...
bormoshka Posted September 13, 2012 Author Share Posted September 13, 2012 Bandayd, thanks for inchat debug. I can't use metadata - its used for skin. I've used metadata for storage rotation value, but here I cant =C DarkGuardsman, Thanks! It works! For history: TileEntity public class TileEntityFlag extends TileEntity implements IPacketReceiver { public int angle; public int type; public void writeToNBT(NBTTagCompound par1NBTTagCompound) { super.writeToNBT(par1NBTTagCompound); par1NBTTagCompound.setInteger("type", this.type); par1NBTTagCompound.setInteger("ang", this.angle); } public void readFromNBT(NBTTagCompound par1NBTTagCompound) { super.readFromNBT(par1NBTTagCompound); this.type = par1NBTTagCompound.getInteger("type"); this.angle = par1NBTTagCompound.getInteger("ang"); } public int getAngle() { return this.angle; } public void setValues(byte i, byte j) { this.type = i; this.angle = j; } public int getType() { return this.type; } //method used for getting packet from PacketManager public Packet getPacket() { int[] data = this.getSendLoadInt(); ; if(data == null) { data = new int[]{}; } return PacketManager.TECommonPacket(this, "UltimateExtender", 0, data); } public int[] getSendLoadInt() { return new int[] {angle,type}; //array that stores all int that need to be sent by packet make sure what is in here ir read in handlePacketData } //is it a standard method? public Packet getAuxillaryInfoPacket() { return getPacket(); } @Override public void handlePacketData(NetworkManager network, String channel, ByteArrayDataInput data) { try { this.angle = data.readInt(); this.type = data.readInt(); } catch (Exception e) { e.printStackTrace(); } } } PacketManager public class PacketManager implements IPacketHandler { //thanks to DarkGuardsman @Override public void onPacketData(NetworkManager network, Packet250CustomPayload packet, Player player) { try { ByteArrayDataInput data = ByteStreams.newDataInput(packet.data); int x = data.readInt(); int y = data.readInt(); int z = data.readInt(); //the following two are not used but can be for sorting packets by ID and restricting packet reading by lengths int id = data.readInt();//packet ID your welcome to set to zero int l = data.readInt(); //packet length a safety var to make sure only data is read. EntityPlayer ePlayer = (EntityPlayer) player; if(ePlayer != null) { TileEntity tileEntity = ePlayer.worldObj.getBlockTileEntity(x, y, z); if(tileEntity != null) { if(tileEntity instanceof IPacketReceiver) { ((IPacketReceiver) tileEntity). handlePacketData(network,packet.channel, data); } } } } catch(Exception e) { e.printStackTrace(); } } /** * * @param sender - TileEntity sending this packet * @param channelName - channel name "channelName" * @param id - packet id * @param sendData - list of Integers to be sent is read after main data * @param string - list of strings to be sent is read last * @return a constructed packet ready to be sent */ //If your looking for a better version check out Calclavia's PacketManager his is very well developed public static Packet TECommonPacket(TileEntity sender, String channelName,int id, int[] sendData) { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); DataOutputStream data = new DataOutputStream(bytes); try { data.writeInt(sender.xCoord); data.writeInt(sender.yCoord); data.writeInt(sender.zCoord); data.writeInt(id); data.writeInt(3+sendData.length); //Here we writes our data; for(int i =0; i < sendData.length; i++) { data.writeInt(sendData[i]); } } catch (IOException e) { e.printStackTrace(); } Packet250CustomPayload packet = new Packet250CustomPayload(); packet.channel = "UltimateExtender";//TODO change to registered channel for you mod packet.data = bytes.toByteArray(); packet.length = packet.data.length; packet.isChunkDataPacket = true; return packet; } } YAY! Quote Link to comment Share on other sites More sharing options...
DarkGuardsman Posted September 13, 2012 Share Posted September 13, 2012 happy it works for you if you need anymore help just ask Quote http://i577.photobucket.com/albums/ss215/bobstrong/ModBannerMed.png[/img] Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.