Jump to content

Severe issues with mod on Forge 624+


WildBamaBoy

Recommended Posts

Problems with Minecraft Comes Alive:

 

Users of my mod that have Forge 7.7.1.624 and above (so far) report problems that are not present on the recommended version  that I link them to: 7.7.1.611.

 

Description

I use a certain packet to update the client with the same randomly selected information that the server selected and keep it updated.

 

This is the process:

Client entity doesn't have a texture -> Sends "sync request" packet to Server containing entity id -> Server handles "sync request" by serializing and sending back the entity with the provided id -> Client searches for entity with the same id as the one that was just received and deserialized -> ERROR. ID doesn't match any entities on the client. Client side entity is never updated. Packet is not properly handled.

 

This problem was fixed by adding the entity id to the sync packet by itself, alongside the entity that was serialized. The client side entity was successfully updated but still did not receive its texture. Instead it used the default char.png. I specifically tell my entities to write their textures and entityIds when being serialized; for some reason this data wasn't written correctly.

 

	/**
 * Writes this object to an object output stream. (Serialization)
 * 
 * @param 	out	The object output stream that this object should be written to.
 * 
 * @throws 	IOException	This exception should never happen.
 */
private void writeObject(ObjectOutputStream out) throws IOException
{
	out.defaultWriteObject();
	out.writeObject(texture);
	out.writeObject(entityId);
}

/**
 * Reads this object from an object input stream. (Deserialization)
 * 
 * @param 	in	The object input stream that this object should be read from.
 * 
 * @throws 	IOException				This exception should never happen.
 * @throws 	ClassNotFoundException	This exception should never happen.
 */
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
	in.defaultReadObject();
	texture = (String)in.readObject();
	entityId = (Integer)in.readObject();
}

 

Log verifying that some error has occurred with the entity id. They do not match when on previous versions they do! To see this output, you must use the command "/mca.debug on" before allowing a villager from the mod to spawn.

 

2013-04-03 22:04:37 [FINER] [ForgeModLoader] Minecraft Comes Alive [DEBUG] SERVER: Sync packet pre-sending data verification: entityBase = EntityVillagerAdult['entity.EntityVillagerAdult.name'/31999, l='New World', x=-829.50, y=4.00, z=270.50], data = [b@ece186, compressed data length = 1730 bytes
2013-04-03 22:04:37 [FINER] [ForgeModLoader] Minecraft Comes Alive [DEBUG] CLIENT: Received packet: MCA_SYNC. Size = 1730
2013-04-03 22:04:37 [FINER] [ForgeModLoader] Minecraft Comes Alive [DEBUG] CLIENT: Sync packet received. data length = [b@ece186
2013-04-03 22:04:37 [FINER] [ForgeModLoader] Minecraft Comes Alive [DEBUG] CLIENT: Decompressing bytes...
2013-04-03 22:04:37 [FINER] [ForgeModLoader] Minecraft Comes Alive [DEBUG] CLIENT: Decompressed data length = 3846
2013-04-03 22:04:37 [FINER] [ForgeModLoader] Minecraft Comes Alive [DEBUG] CLIENT: Received packet data verification: entityBase = EntityVillagerAdult['entity.EntityVillagerAdult.name'/32061, l='~NULL~', x=0.00, y=0.00, z=0.00], data = [b@1ca2f25, data length = 3846

 

 

After I fixed the problem with the entity ID, I also had to add the texture to the packet so that the client would actually receive the right texture data. My writeObject and readObject methods are being skipped. Why?

 

More verification that these methods are skipped: the entity's inventory must also be serialized and sent back and forth. When I try to serialize the inventory for a packet, I get a NotSerializableException on a field. I override the serialization with writeObject and readObject, and I do not allow defaultWriteObject() to run so that I won't have the problem with a field not being serializable. It only writes what I tell it to.

 

This is the error I get when trying to serialize an Inventory:

2013-04-04 23:10:27 [iNFO] [sTDERR] java.io.NotSerializableException: net.minecraft.item.ItemStack
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.io.ObjectOutputStream.writeArray(Unknown Source)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.io.ObjectOutputStream.writeObject0(Unknown Source)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.io.ObjectOutputStream.writeObject(Unknown Source)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at mods.MCA.PacketCreator.createInventoryPacket(PacketCreator.java:432)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at mods.MCA.EntityVillagerAdult.interact(EntityVillagerAdult.java:678)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at net.minecraft.entity.player.EntityPlayer.interactWith(EntityPlayer.java:1222)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at net.minecraft.client.multiplayer.PlayerControllerMP.func_78768_b(PlayerControllerMP.java:462)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at net.minecraft.client.Minecraft.clickMouse(Minecraft.java:1291)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at net.minecraft.client.Minecraft.runTick(Minecraft.java:1796)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:831)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at net.minecraft.client.Minecraft.run(Minecraft.java:756)
2013-04-04 23:10:27 [iNFO] [sTDERR] 	at java.lang.Thread.run(Unknown Source)

 

I specifically include the writeObject() method in Inventory to skip the default serialization and prevent this problem. You can view this for yourself in both versions of the source code.

Why does this happen? And why only on later versions of Forge?

 

Source Code (Broken on 624+, perfect on 611-) - https://dl.dropbox.com/u/64124307/Broken%20Source.zip

Source Code (Semi-Fixed for later Forge versions, Inventory packet kills the game. Gift a sword to a villager.) - https://dl.dropbox.com/u/64124307/Semi-Fixed%20Source.zip

 

Files of interest:

PacketHandler.java, createSyncPacket(), createSyncRequestPacket(), createInventoryPacket()

PacketCreator.java, handleSync(), handleSyncRequest(), handleInventory()

EntityVillagerAdult.java, interact()

EntityBase.java, writeObject(), readObject()

Inventory.java, writeObject(), readObject()

 

While it seems entirely wrong to blame Forge for what appears to be a problem with serialization (I have no idea how you can screw with built-in java), the exact same code works flawlessly on Forge 611 and has been working for months! I don't know what else to blame.

Link to comment
Share on other sites

Humm aside from the fact that you're doing things horribly wrong! jesus christ! We have facilities in place for extra spawn data for a reason!

Lookin at those changesets, it doesn't seem like we do anything that would effect your mod this way. However, I did test on 611 and 624, and do see the issue happening. Will do a little more testing with versions and see if I can track down to a specific build.

 

Taking a wild guess i'm gunna say it has something to do with runtime deobfusication based on the horribly method you're using for serializing your data...

Seriously dude, thats bad, you should just send enough to get the information you need across not THE ENTIRE OBJECT, it is nothing but massive network churn.

 

Alright, I was correct, you are trying to serialize the entire object. Which does not work as to maintain ModLoader compatibility we need to make all fields/methods public in all remapped classes.

So you need to look into actually determining what data you need and not relying on ObjectOutputStream, that was designed for small data objects, not large great grandchild objects.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

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

    • They were already updated, and just to double check I even did a cleanup and fresh update from that same page. I'm quite sure drivers are not the problem here. 
    • i tried downloading the drivers but it says no AMD graphics hardware has been detected    
    • Update your AMD/ATI drivers - get the drivers from their website - do not update via system  
    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
  • Topics

×
×
  • Create New...

Important Information

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