Jump to content

ErnstLustig

Members
  • Posts

    25
  • Joined

  • Last visited

Everything posted by ErnstLustig

  1. Try looking for a packet. I added packets and it solved the problem. Thanks.
  2. I wanted to look into packets now, but before that I wondered if this is even a client and server sync issue. Because I open the GUI only on the server side, right? But it still doesn't recognize the fluids correctly. Is this how this works? Is there maybe a command to force a block to synchronize with server and client, just to check if this is even the problem? Or what would be the best way to debug that?
  3. Man, I'm not sure. I get what you are saying, but I have a hard time believing this is needed to implement it like that. I just tried to look at the EnderIO Tank code which also renders the tank content in the GUI and I couldn't find any code like that in there. It just accesses the TE's FluidStack directly and renders it, just like I did it (at least it looks like it). I must be missing something totally terribly.
  4. I just only saw your edit. Makes sense. But where is the code actually used. As the GuiFurnace doesn't actually use it, that's my question.
  5. Ah, I named it GuiProxy, forgot that it implements GuiHandler. @Override public Object getServerGuiElement( int ID, EntityPlayer player, World world, int x, int y, int z ){ BlockPos pos = new BlockPos( x, y, z ); TileEntity te = world.getTileEntity( pos ); //other stuff if( te instanceof TileEntitySqueezer ){ return new ContainerSqueezer( player.inventory, (TileEntitySqueezer) te ); } } @Override public Object getClientGuiElement( int ID, EntityPlayer player, World world, int x, int y, int z ){ BlockPos pos = new BlockPos( x, y, z ); TileEntity te = world.getTileEntity( pos ); //other stuff if( te instanceof TileEntitySqueezer ){ TileEntitySqueezer containerTileEntity = (TileEntitySqueezer) te; return new GuiSqueezer( containerTileEntity, new ContainerSqueezer( player.inventory, containerTileEntity ) ); } }
  6. Yeah, but what is the advantage of that? If you look in the GuiFurnace code, it accesses as I said the fields directly from the TileEntity, not from the container. Why two containers and sync the data of them there when they are never used (or I at least can't find the use)? Also it works in my code just fine without those, only the fluidstack is giving me problems. Before I blindly try to implement listeners and such, I like to understand first what they are useful for as I don't see the use for them now. Also not sure what you mean with GuiHandler as I can't find a mention of that in the code.
  7. Well, I looked into it and I'm not sure how this should help me. In my TEs ItemStacks get updated correctly no matter if input manually or with Hoppers or Item Conduits, also the progress bars I implemented in my machines work fine even without adding listeners (beside that I don't understand the code in ContainerFurnace, the listeners basically update local variable copies for the progress bar, but GuiFurnace accesses the variables from the TE directly not from the Container, not sure what the Container variables are even there for). So ItemStacks and progress bars works fine for, only the FluidStack doesn't get synced correctly. I'm not really understanding.
  8. So, I'm still having troubles figuring out the syncing between server and client. I added a block with a tank and to try it out I added the funcionality to right click a bucket to add/get fluids to/from the tank. I adapted the code mostly from TiCo. And it works. Now I tried EnderIO Fluid conduits and if fluids get added or removed the GUI doesn't get updated. But the fluid is in there as I can still get it out with a bucket. I'm guessing because this only done server-side and I have to tell the client something has changed. Not sure how to do that though. Do I have to use packets for that? Here the most relevant code: public class BlockSqueezer extends BlockFaeries implements ITileEntityProvider { @Override public boolean onBlockActivated( World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ ){ TileEntity te = world.getTileEntity( pos ); if ( !( te instanceof TileEntitySqueezer ) ) { return false; } if( te.hasCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side ) ){ IFluidHandler fluidHandler = te.getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side ); boolean success = FluidUtil.interactWithFluidHandler( heldItem, fluidHandler, player ); if( success ){ return true; } } if( !world.isRemote ){ player.openGui( Faeries.instance, GUI_ID, world, pos.getX(), pos.getY(), pos.getZ() ); } return true; } } public class TileEntitySqueezer extends TileEntity implements ITickable { private FluidTank tank = new FluidTank( CAPACITY ) { @Override protected void onContentsChanged(){ TileEntitySqueezer.this.markDirty(); } }; @Override public void readFromNBT( NBTTagCompound compound ){ super.readFromNBT( compound ); if( compound.hasKey( "input" ) ){ inputStack.deserializeNBT( (NBTTagCompound) compound.getTag( "input" ) ); } tank.readFromNBT( compound ); } public NBTTagCompound getUpdateTag() { return this.writeToNBT( new NBTTagCompound() ); } @Override public NBTTagCompound writeToNBT( NBTTagCompound compound ){ super.writeToNBT( compound ); compound.setTag( "input", inputStack.serializeNBT() ); tank.writeToNBT( compound ); return compound; } @Override public boolean hasCapability( Capability<?> capability, EnumFacing facing ){ if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ){ return true; } return super.hasCapability( capability, facing ); } @Override public <T> T getCapability( Capability<T> capability, EnumFacing facing ){ if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ){ if( facing == null ){ return (T) inputStack; } return (T) new InsertItemStackHandler( inputStack ); } if( capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ){ return (T) tank; } return super.getCapability( capability, facing ); } public FluidTank getFluidTank(){ return tank; } } public class GuiSqueezer extends GuiContainer { public static final int WIDTH = 180; public static final int HEIGHT = 152; private final TileEntitySqueezer te; private static final ResourceLocation background = new ResourceLocation( Reference.MOD_ID, "textures/gui/guisqueezer.png" ); public GuiSqueezer( TileEntitySqueezer tileEntity, ContainerSqueezer container ){ super( container ); xSize = WIDTH; ySize = HEIGHT; te = tileEntity; } @Override protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY ){ mc.getTextureManager().bindTexture( background ); drawTexturedModalRect( guiLeft, guiTop, 0, 0, xSize, ySize ); FluidStack fluid = te.getFluidTank().getFluid(); if( fluid != null && fluid.amount != 0 ) { ResourceLocation location = te.getFluidTank().getFluid().getFluid().getStill(); TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite( location.toString() ); mc.renderEngine.bindTexture( TextureMap.LOCATION_BLOCKS_TEXTURE ); float filllevel = (float)fluid.amount * 48 / te.CAPACITY; drawTexturedModalRect( guiLeft + 82, guiTop + 54 - Math.round( filllevel ), sprite, 16, Math.round( filllevel ) ); } } }
  9. Ugh, this is terrible. I didn't know that. What would be an example of that?
  10. Well I don't know how to do it better, that's why I asked. I needed two StackHandlers because I need one to be a subclass of the other with the added restriction of not extracting items, but I can't copy the StackHandler because I can't access the ItemStacks. So I need to add the method of getStacks. Not sure what you mean with not using the capability at all, you mean in the Container to access the ItemStacks? But that seems like even more work to me.
  11. Well I implemented this now and it seems to work. I tried a block where for the input only a certain item type is allowed (both manual and automatic), but it can be removed manually, but not automatically. But it seems rather hacked than a clean simple solution. I think this can be made way more simple. What do you think? public class TileEntitySqueezer extends TileEntity implements ITickable { public static final int INPUT_SIZE = 1; public static final int CAPACITY = Fluid.BUCKET_VOLUME * 8; private FluidTank tank = new FluidTank( CAPACITY ) { @Override protected void onContentsChanged(){ TileEntitySqueezer.this.markDirty(); } }; private SqueezerItemStackHandler inputStack = new SqueezerItemStackHandler( INPUT_SIZE ); [...] @Override public boolean hasCapability( Capability<?> capability, EnumFacing facing ){ if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ){ return true; } return super.hasCapability( capability, facing ); } @Override public <T> T getCapability( Capability<T> capability, EnumFacing facing ){ if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ){ if( facing == null ){ return (T) inputStack; } return (T) new InsertItemStackHandler( inputStack ); } if( capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY ){ return (T) tank; } return super.getCapability( capability, facing ); } public class SqueezerItemStackHandler extends ItemStackHandler{ public SqueezerItemStackHandler(){ super( 1 ); } public SqueezerItemStackHandler( int size ){ super( size ); } @Override protected void onContentsChanged( int slot ){ TileEntitySqueezer.this.markDirty(); } @Override public ItemStack insertItem( int slot, ItemStack stack, boolean simulate ){ if( !( stack.getItem() instanceof ItemDrop ) ){ return stack; } return super.insertItem( slot, stack, simulate ); } public ItemStack[] getStacks(){ return stacks; } } public class InsertItemStackHandler extends SqueezerItemStackHandler{ public InsertItemStackHandler( SqueezerItemStackHandler stackhandler ){ this.stacks = stackhandler.getStacks(); } @Override public ItemStack extractItem( int slot, int amount, boolean simulate ){ return null; } }
  12. Ah I didn't know that. Thanks I will try to do that.
  13. I'm still not fully understanding the new Capability system. I know how to define what to access from which side, but what I care about is what to access depending on input or output. What I mean by that is that I might want to allow to put items in with a hopper for a specific slot, but not allow a hopper to pull the items out of that slot. How do I do that? Any examples you can point me at? I looked at a lot of code, but couldn't find the specific part where to define that. Also it doesn't seem to check isItemValid if it's inserted with a hopper. So I'm not allowed to manually put items in the slot, but disallowed items land in the slot if accessed with a hopper. For reference, here is how I define the slot in the container. IItemHandler itemHandler = this.te.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ); addSlotToContainer( new SlotItemHandler( itemHandler, 0, 18, 24 ){ @Override public boolean isItemValid( ItemStack stack ){ return stack.getItem() instanceof ItemDrop; } });
  14. Cool thanks, I'll try that.
  15. I'm currently messing with ticking Tile Entities and try to learn them. I try to copy the furnace code as best as I can. First I tried to spawn an item after a certain amount of time which worked great. Then I added the same Progress Bar of the GUI as the furnace. Works also great. But now I noticed that if I quit my single player world and rejoin, the GUI isn't in sync with the spawning anymore, the GUI Progress Bar gets reset every time I rejoin. I think this means that the Server and the Client aren't in sync. I think I'm missing some background info here. Can anyone help me? Here's part of my TileEntity Code: @Override public void update() { if( !hasFaery() ){ time = 0; flag = false; } if( time <= 0 && hasFaery() ){ if( flag && !worldObj.isRemote ){ EntityItem produce = new EntityItem( worldObj, pos.getX(), pos.getY()+1, pos.getZ(), new ItemStack( Items.STICK ) ); worldObj.spawnEntityInWorld( produce ); } time = MAX_TIME; flag = true; } time--; if( hasFaery() ){ markDirty(); } } @Override public void readFromNBT( NBTTagCompound compound ){ super.readFromNBT( compound ); if( compound.hasKey( "input" ) ){ inputStack.deserializeNBT( (NBTTagCompound) compound.getTag( "input" ) ); } if( compound.hasKey( "output" ) ){ outputStack.deserializeNBT( (NBTTagCompound) compound.getTag( "output" ) ); } if( compound.hasKey( "time" ) ){ time = compound.getInteger( "time" ); } } @Override public NBTTagCompound writeToNBT( NBTTagCompound compound ){ super.writeToNBT( compound ); compound.setTag( "input", inputStack.serializeNBT() ); compound.setTag( "output", outputStack.serializeNBT() ); compound.setInteger( "time", time ); return compound; } public int getTime(){ return time; } public boolean hasFaery(){ return ( inputStack.getStackInSlot(0) != null ); } and here my GUI code: @Override protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY ){ mc.getTextureManager().bindTexture( background ); drawTexturedModalRect( guiLeft, guiTop, 0, 0, xSize, ySize ); if( te.hasFaery() ){ float progress = 22 - ( te.getTime() * 22 / te.MAX_TIME ); drawTexturedModalRect( guiLeft + 43, guiTop + 7, 180, 0, Math.round( progress ), 15 ); } }
  16. That was very helpful. Thanks.
  17. I'm not sure if I should open another thread rather than posting here, so I hope you don't mind if I ask another question here. I now want to define if items in specific slots are extractable through hoppers/pipes. I looked into the furnace code, it uses canExtractItem, but it doesn't use the Capability system, so I can't replicate that. There is also canTakeStack in the SlotItemHandler, but that only defines manually extraction. If I set that to false, I can't take the item out anymore, but can still extract it with a hopper. I want the opposite though. Can someone give me a hint in the right direction?
  18. Ah, didn't know that I use null here, nice. I get the difference between those two methods, thanks.
  19. I'm currently learning how TileEntities work. So I implemented McJty's great example: http://modwiki.temporal-reality.com/mw/index.php/GUI-1.9 But I noticed that items don't get dropped when the block is broken. So I tried to add that functionality by myself. I noticed that there are 2 similar methods, harvestBlock and breakBlock. What is the difference? I got it working with breakBlock. I'm not fully understanding how the new Capability system works even though I read http://mcforge.readthedocs.io/en/latest/datastorage/capabilities/ So I tried it with that, not sure if it's correct and I had to define a facing I'm accessing the item, so I defaulted to the up facing, pretty sure that's not great. Can anyone help me how to do this correct? public void breakBlock( World worldIn, BlockPos pos, IBlockState state ){ TileEntity te = worldIn.getTileEntity( pos ); if( te instanceof TileEntityFaeryHouse ){ ItemStackHandler ish = (ItemStackHandler)te.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.UP ); for( int i=0; i<ish.getSlots(); i++ ){ if( ish.getStackInSlot( i ) != null ){ worldIn.spawnEntityInWorld( new EntityItem( worldIn, pos.getX(), pos.getY(), pos.getZ(), ish.getStackInSlot( i ) ) ); } } } super.breakBlock(worldIn, pos, state); }
  20. I tried to drop vanilla items as well and they had a missing texture too, but the problem is solved as described above. Initializing objects after the register phase seems like a bad idea, I got it. @Matryoshika: Yeah, that was what I was confused about. I fixed it, but it didn't make sense to me. I know now that I got the meaning of isRemote mixed up because I'm not a native speaker. I thought isRemote==true means Server side, but it's vice versa, right? This means now that if( !world.isRemote ) is the correct thing to check for server side and this is how I accidently fixed it. Not sure what you mean with "if not client" though. Doesn't !world.isRemote already check for server side only?
  21. Nevermind I figured it out. Instead of new ItemSaddle() for example I need to use Items.SADDLE. Makes sense. But then I noticed that it spawns 2 copies of that item, one of which is not really there. I fixed it with if( !world.isRemote ), but I'm not sure if that's correct. Shouldn't the server know about that item?
  22. I'm still new to modding, so sorry if this is a stupid question. I want to drop a new item when I right click with a tool. I think you do that with spawnEntityInWorld if I figured that out correctly. But if I do that I get the item, but it has no texture. Apparently it doesn't get initialized correctly. What do I have to do instead? @Override public ActionResult<ItemStack> onItemRightClick(ItemStack stack, World world, EntityPlayer playerIn, EnumHand hand) { world.spawnEntityInWorld( new EntityItem( world, playerIn.posX, playerIn.posY, playerIn.posZ, new ItemStack( new ItemTest() ) ) ); return new ActionResult<>(EnumActionResult.SUCCESS, stack); }
  23. That makes sense, thanks for the quick response.
  24. Thanks Ernio, yeah I should use override, I'm just testing things out, but that's a good habit. I added that line and it works now, but I just don't understand why it's needed. I changed textures based on connected blocks without changing the metadata, but here it seems needed. Do you know why?
  25. Hey everyone, I looked into the Stairs and Furnace code to create a block that faces you when you place it, but it somehow doesn't work. public class BlockCupboard extends BlockTutorial { public static final PropertyDirection FACING = PropertyDirection.create( "facing", EnumFacing.Plane.HORIZONTAL ); public BlockCupboard(){ super( new Material( MapColor.brownColor ) ); this.setUnlocalizedName("cupboard"); this.setDefaultState( this.blockState.getBaseState().withProperty( FACING, EnumFacing.NORTH ) ); } public int getMetaFromState( IBlockState state ) { return 0; } protected BlockState createBlockState() { return new BlockState( this, new IProperty[] {FACING} ); } public IBlockState onBlockPlaced( World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer ) { return this.getDefaultState().withProperty( FACING, placer.getHorizontalFacing().getOpposite() ); } } Do I need to set a Metavalue depending on the facing of the block? I didn't need it when I changed the texture of a different block depending what is adjacent to a block. What is weird is that my blocks always face east, although the default facing is set to north, at least that is what F3 is telling me.
×
×
  • Create New...

Important Information

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