Jump to content

Recommended Posts

Posted

Hi all, i'm currently adding a block that has editable sides. It is very complicated, and ive got it mostly working. Only problem is, is that im using integer values in the TileEntity as values for each side. Clicking on each side with the tool cycles the values, which in turn changes the model texture on that side. Now my problem: When each side is changed, it changes both values for the integer, being the !world.isRemote, and the world.isRemote values, as rendering the block uses the client side, but storing the values is serverside. When reading from NBT it successfully updates the SERVER side value, but not the CLIENT side value. So i need to snyc them somewhere, either in the tile entity, or the block. Im in deep here!

 

The second gui accesses all sides and edits the side textures based on a button press, using packets. FYI

 

TileEntity class:

 

  Reveal hidden contents

 

 

Block class:

  Reveal hidden contents

 

Posted

You shouldn't change data of client tileentity, rather than that sync the data from server.

I answered about syncing here.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted
  On 5/17/2017 at 12:00 AM, Zeher_Monkey said:

Minecraft.getMinecraft().renderGlobal.markBlockRangeForRenderUpdate(pos.getX(), pos.getY(), pos.getZ(), pos.getX(), pos.getY(), pos.getZ());

Expand  

Why is this client-side-only reference in common code?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
  On 5/17/2017 at 12:38 AM, Zeher_Monkey said:

The mark render is for updating the texure/model when the side is changed. Without that the texture doesn't change without a block update

 

Expand  

You should not call the client code directly.

Look at what World#setBlock-blockstate version- calls to update the rendering.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted (edited)
  On 5/17/2017 at 12:44 AM, Abastro said:

You should not call the client code directly.

Look at what World#setBlock-blockstate version- calls to update the rendering.

Expand  

I'll take a look. I'm busy right now. I've got a basic packet set up, but I can't think of how to use packets to load items/ integers. You don't happen to have an example lying around? I've been at this for hours xD I see the methods you suggested to override in TileEntity

Edited by Zeher_Monkey
Posted
  On 5/17/2017 at 12:47 AM, Zeher_Monkey said:

but I can't think of how to use packets to load items/ integers

Expand  

You don't, tileentity has a built-in logic for client-server synchronization.

Look at my first reply.

 

Regardless, you need to let game know that your TE is updated - similar case with World#setBlock.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted
  On 5/17/2017 at 12:51 AM, Abastro said:

You don't, tileentity has a built-in logic for client-server synchronization.

Look at my first reply.

 

Regardless, you need to let game know that your TE is updated - similar case with World#setBlock.

Expand  

Alright, I'll take a look when I can. Cheers for the help :)

 

Posted (edited)
  On 5/17/2017 at 12:51 AM, Abastro said:

You don't, tileentity has a built-in logic for client-server synchronization.

Look at my first reply.

 

Regardless, you need to let game know that your TE is updated - similar case with World#setBlock.

Expand  

Ive looked at the vanila code, but cant make any sense of it. Im not sure what to actually do in those functions TileEntity:getUpdatePacket/onDataPacket. I should know this :D but its new for me 

 

--EDIT--

Starting to understand...

Edited by Zeher_Monkey
Posted (edited)
  On 5/17/2017 at 12:51 AM, Abastro said:

You don't, tileentity has a built-in logic for client-server synchronization.

Look at my first reply.

 

Regardless, you need to let game know that your TE is updated - similar case with World#setBlock.

Expand  

So like this? :

  Reveal hidden contents

 

And would i keep the original load/write NBT functions?

Edited by Zeher_Monkey
Posted

You shouldn't need to mess with packets. As long as your TE writes and reads NBT consistantly, you should only need to mark the TE after changing its data. The vanilla logic should then handle the rest.

 

If you're curious to learn what "the rest" is, then the best way to see it is in the debugger as it executes rather than by trying to trace static code. It's way more difficult to sort the client versus server paths in static code. It's way easier to see how the paths work when you can actually step through the real thing.

 

Set a couple break points and let the debugger take you on a guided tour.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted
  On 5/17/2017 at 8:46 PM, jeffryfisher said:

You shouldn't need to mess with packets. As long as your TE writes and reads NBT consistantly, you should only need to mark the TE after changing its data. The vanilla logic should then handle the rest.

 

If you're curious to learn what "the rest" is, then the best way to see it is in the debugger as it executes rather than by trying to trace static code. It's way more difficult to sort the client versus server paths in static code. It's way easier to see how the paths work when you can actually step through the real thing.

 

Set a couple break points and let the debugger take you on a guided tour.

Expand  

MarkDirty()? Ive tried it and it doesnt seem to do anything. Im having a hard time actually using NBT as it doesnt always save the value in the first place. Im not sure if its how im handling the changing of the values, but everywhere the values change, i set both values (Remote and not). I works fine for _power integer, just not the side values. The only reason i ask is because when it does work, it changes the !remote value and not the remote value, so the side doesnt render correcty.

 

Thanks for the reply, ill try the breakpoints and see where it leads me. :) 

Posted
  On 5/17/2017 at 8:46 PM, jeffryfisher said:

You shouldn't need to mess with packets. As long as your TE writes and reads NBT consistantly, you should only need to mark the TE after changing its data. The vanilla logic should then handle the rest.

Expand  

It won't. Now vanilla logic only syncs basic tileentity data(types and positions). So you need to implement those methods to sync fields, while you don't need to design a custom packet.

 

  On 5/17/2017 at 3:12 PM, Zeher_Monkey said:

So like this? :

  Reveal hidden contents

 

And would i keep the original load/write NBT functions?

Expand  

You wouldn't need getUpdateTag and handleUpdateTag. (Though I'm not sure)

The packet has a NBTTagCompound contained which can be attained by ::getCompound(). Read the data from the compound.

  On 5/17/2017 at 9:44 PM, Zeher_Monkey said:

Im not sure if its how im handling the changing of the values, but everywhere the values change, i set both values (Remote and not). I works fine for _power integer, just not the side values.

Expand  

if(!world.isRemote) means you're working on server, while the opposite does on client. You shouldn't change any data values on client if it's not constantly updated one. Also you should always sync the fields from the server when it's needed.

 

Besides, did you look into the setBlock method? It calls a method which is named updateBlock or similar. You need to call it.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted
  On 5/18/2017 at 12:22 AM, Abastro said:

Now vanilla logic only syncs basic tileentity data(types and positions).

Expand  

Yuck... That'll be a joy to fix when I do my next upgrade. I must confess I'm still in 1.10.2. I'll probably play catch-up when 1.12 has a stable Forge release.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

Im updating my mod from 1.7.10 ;D This is an experiment for me, if it world itll be implemented on every machine (hopefully) Im still trying... Im also going to see if i can use TESR instead, as it wouldnt be too much of a chore, (As i already use it for other things). Maybe that will help... Ill try both methods and see which works as intended. Thanks for all the help guys, really appreciate it :) 

Posted (edited)
  On 5/18/2017 at 12:22 AM, Abastro said:

It won't. Now vanilla logic only syncs basic tileentity data(types and positions). So you need to implement those methods to sync fields, while you don't need to design a custom packet.

 

You wouldn't need getUpdateTag and handleUpdateTag. (Though I'm not sure)

The packet has a NBTTagCompound contained which can be attained by ::getCompound(). Read the data from the compound.

if(!world.isRemote) means you're working on server, while the opposite does on client. You shouldn't change any data values on client if it's not constantly updated one. Also you should always sync the fields from the server when it's needed.

 

Besides, did you look into the setBlock method? It calls a method which is named updateBlock or similar. You need to call it.

Expand  

The only reason i'm changing it on the client, is because of the way i'm rendering the sides. I'm using basic fence code, which uses getActualState() which only runs on Client. Hence the need to sync the values when reentering the world... That's why i plan to see if TESR can help/solve the issue.

 

Also setBlock()? What for... To change the block with updated values? Or will that help sync? I know that is used for furnaces and the like to replace the block with the "active" version. Beyond that i'm not 100% sure. I realize it updates the block, but that's what i use the mark for render update line, its the model/texture that i'm looking to change, that's the only thing that depends on the side values in the TileEntity.

Edited by Zeher_Monkey
Posted (edited)

Same issue with TESR, sets the SERVER value but not the client value... It does grab the correct value on write, but is the read... Read seems to be called twice, one returning the correct value, the other returns 0 everytime.

--EDIT --

1 Im stupid, TESR wouldnt have solved much, all rendering is done on client. Duh

2 Write also seems to be called twice..

 

  Reveal hidden contents

READ is reading, WRITE is writing (to/from NBT)

Edited by Zeher_Monkey
Posted

Right so im trying out getUpdatePacket() and onDataPacket() and they arent called when the world loads, only when the block changes? Ive called the get update packet on the write to nbt function, but im not sure if thats how to do it? Also where should i be calling the setBlockState()?

Posted

Okay, so a couple of things I would like to explain:

1. Difference between TileEntity::getUpdateTag and TileEntity::getUpdatePacket.

They are build around the same purpose and cause a lot of confusion, but they are slightly different. getUpdateTag is appended to the ChunkData packet(the one player recieves from a server when loading a chunk/chunk data is changed). getUpdatePacket is sent in 2 circumstances: If a BlockState changes and the new one has a TileEntity(world::setBlockState is mostly the cause here) or if the amount of changes in the chunk is greater than 1 and less than 64(so a couple of blocks got thanged). Then the getUpdatePacket is sent for each changed blockstate with tile entity.

So you do need to override both in your tileentity. Override only getUpdatePacket - and the client will not recieve the data when the chunk is loaded or multiple blocks are changed at the same time. Override only getUpdateTag - and the clients will not see the changes upon blockstate changes.

2. Please use breakpoints to debug. They are so much nicer and handy, you have no idea. Writing stuff to output is messy, time-consuming and leads to situations when modmakers forget to remove their println debugging from the final product and the log gets overflown with useless debug information and slows the game down. Just launch any big modpack out there and watch the log. You will quickly see what I mean. A breakpoint is literally 2 clicks of  mouse to set, gives you all the info you need and even more and it will never end up in the final product.

3. getUpdateTag should return all your NBT information you need to sync. A couple of responses above you posted:

  On 5/17/2017 at 3:12 PM, Zeher_Monkey said:

public NBTTagCompound getUpdateTag()
    {
        return new NBTTagCompound();
    }

Expand  

That will not work. It will send an empty packet to the server upon chunk loading and your tileentity will not have any data synced. Even worse, it will completely mess everything as the tileentity will not get loaded at all! See how it is done in the base Tileentity class.

 

If you simply override both of those methods and their handlers (onDataPacket, handleUpdateTag) then your tile will get updated correctly on the client when the respective packet arrives. You still will need custom packets to sync real-time changes though.

  • Like 1
Posted (edited)
  On 5/18/2017 at 11:31 PM, V0idWa1k3r said:

Okay, so a couple of things I would like to explain:

1. Difference between TileEntity::getUpdateTag and TileEntity::getUpdatePacket.

They are build around the same purpose and cause a lot of confusion, but they are slightly different. getUpdateTag is appended to the ChunkData packet(the one player recieves from a server when loading a chunk/chunk data is changed). getUpdatePacket is sent in 2 circumstances: If a BlockState changes and the new one has a TileEntity(world::setBlockState is mostly the cause here) or if the amount of changes in the chunk is greater than 1 and less than 64(so a couple of blocks got thanged). Then the getUpdatePacket is sent for each changed blockstate with tile entity.

So you do need to override both in your tileentity. Override only getUpdatePacket - and the client will not recieve the data when the chunk is loaded or multiple blocks are changed at the same time. Override only getUpdateTag - and the clients will not see the changes upon blockstate changes.

2. Please use breakpoints to debug. They are so much nicer and handy, you have no idea. Writing stuff to output is messy, time-consuming and leads to situations when modmakers forget to remove their println debugging from the final product and the log gets overflown with useless debug information and slows the game down. Just launch any big modpack out there and watch the log. You will quickly see what I mean. A breakpoint is literally 2 clicks of  mouse to set, gives you all the info you need and even more and it will never end up in the final product.

3. getUpdateTag should return all your NBT information you need to sync. A couple of responses above you posted:

That will not work. It will send an empty packet to the server upon chunk loading and your tileentity will not have any data synced. Even worse, it will completely mess everything as the tileentity will not get loaded at all! See how it is done in the base Tileentity class.

 

If you simply override both of those methods and their handlers (onDataPacket, handleUpdateTag) then your tile will get updated correctly on the client when the respective packet arrives. You still will need custom packets to sync real-time changes though.

Expand  

Thanks for that reply. I get the idea about breakpoints, but i'g going to be honest here, ive never used them. Probably will look up a tutorial for those... Anyway i have it working! Ive changed that 

  Reveal hidden contents

 I just copied them from TileEntity.class. Its working brilliantly now, but theres only one problem. It might be the block.setBlockState() i added to onBlockActivated() in the block code, or something else im not sure, but the second gui, which uses packets to change 'both' values, now doesnt update the int. I might try adding setBlockState to the packet in some way, but so far its working great!

  Reveal hidden contents

Im also calling getUpdatePacket() anywhere the sides are changed, not sure if its nessicary, but its there. Heres my GUI and packet class.

 

GuiCapacitorBasicDirection.java:

 

  Reveal hidden contents

 

PacketCapacitorBasic.java:

  Reveal hidden contents

 

But thanks to your help im 90% of the way. Which i cant thank you enough for :)  :D 

 

EDIT -

Ive added this line to the packet code:

ctx.getServerHandler().playerEntity.world.setBlockState(pos, ctx.getServerHandler().playerEntity.world.getBlockState(pos));

 

Which hasnt worked -_-

 

EDIT 2

Its all working!!!!! Chopped some of the code and it works perfectly. Again i cant thank you all enough for your help! One silly coder to another, cheers. :D

 

Edited by Zeher_Monkey
Posted
  On 5/19/2017 at 12:05 AM, Zeher_Monkey said:

tile.getUpdatePacket();

Expand  

FYI: you do not need to do that. That method only creates the packet, it does not actually send it or do anything with it. So your NetUtils and MessageHandler simply create a new packet object and immidiately discard it as you are not doing anyhing with it.

Also your getUpdatePacket implementation in your tile does a lot of redundant work. It sets the values of the sides and then calls writeToNBT which

does the same. Well, at least it is doing that in the code you have posted, but you might have changed it already.

Posted (edited)

Yeah... Ive just discovered that writeToNBT isnt always called. A block update by placing and destroying a block next to it will force write to nbt, is there a way i can do that when a side is set?

 

Also what ive got now actually works in most instances, so i dont want to change too much in case it breaks again :D 

 

Ive tried these :

worldIn.setBlockState(pos, state);
worldIn.notifyBlockUpdate(pos, state, state, 3);

With no luck
        

Edited by Zeher_Monkey
Posted (edited)

Well, if something changes as the block nearby gets updated it does not mean that there is an issue with writeToNBT, it means that if you are using extended block state to render changes made to the block you need to call World::markBlockRangeForRenderUpdate to re-render it in the world in your packet as it is handled on the client

Edited by V0idWa1k3r
Misunderstood the question a bit
Posted

I hate asking so many questions but what would i call in that packet? When a side is changed to update the block using notifyBlockUpdate(), or call it when the player hits ESC, to call the writeToNbt Directly? Short of spawning a block next to is and destroying it i cant think of what to do to get that to happen.

Posted

I have misunderstood your initial question a bit. I have edited my reply to adress that:

  On 5/19/2017 at 12:33 AM, V0idWa1k3r said:

Well, if something changes as the block nearby gets updated it does not mean that there is an issue with writeToNBT, it means that if you are using extended block state to render changes made to the block you need to call World::markBlockRangeForRenderUpdate to re-render it in the world in your packet as it is handled on the client

Expand  

 

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Keep on using the original Launcher Run Vanilla 1.12.2 once and close the game Download Optifine and run optifine as installer (click on the optifine jar) Start the launcher and make sure the Optifine profile is selected - then test it again  
    • Hi everyone, I’m hoping to revisit an old version of Minecraft — specifically around Beta 1.7.3 — for nostalgia’s sake. I’ve heard you can do this through the official Minecraft Launcher, but I’m unsure how to do it safely without affecting my current installation or save files. Are there any compatibility issues I should watch out for when switching between versions? Would really appreciate any tips or advice from anyone who’s done this before! – Adam
    • hello! i was trying to recreate item-in-hand feature for my custom mob. i figured out that my mob needs a custom iteminhandlayer. i created it - but the main problem is.. well.. you can see all on screenshots any idea how i can fix that? is there any implemented method to render the item perfect to hand? public void render(@NotNull PoseStack pPoseStack, @NotNull MultiBufferSource pBufferSource, int pPackedLight, @NotNull TuneGolemRenderState pRenderState, float pYRot, float pXRot) { ItemStackRenderState item = pRenderState.heldItem; if (!item.isEmpty()) { pPoseStack.pushPose(); ModelPart leftArm = this.getParentModel().leftArm; pPoseStack.translate(0.35,0.5,-1.25); pPoseStack.mulPose(Axis.XP.rotationDegrees(180.0F)); pPoseStack.mulPose(Axis.YP.rotationDegrees(90.0F)); leftArm.translateAndRotate(pPoseStack); // pPoseStack.translate(0,0,0); leftArm.translateAndRotate(pPoseStack); if (TuneGolemRenderState.hornPlaying) { pPoseStack.translate(0, -0.5, 0.65); pPoseStack.scale(1.25F,1.25F,1.25F); } // Minecraft.getInstance().player.displayClientMessage(Component.literal(leftArm.xRot + " " + leftArm.yRot + " " + leftArm.zRot), true); item.render(pPoseStack, pBufferSource, pPackedLight, OverlayTexture.NO_OVERLAY); pPoseStack.popPose(); // -1.0F, -2.0F, -3.0F } }  
    • I checked for any driver updates, but no new updates were found
    • Maybe it refers to an issue with the system - check for CPU/GPU driver updates
  • Topics

  • Who's Online (See full list)

    • There are no registered users currently online
×
×
  • Create New...

Important Information

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