Jump to content

[Solved] [1.14.3] Entity Renderer not rendering


PhilipChonacky

Recommended Posts

I have a fairly simple laser entity based on Arrow abstract classes which I have been trying to troubleshoot to no avail.

The entity is spawned, but the renderer does not fire on the client.

No errors are thrown, it just doesn't appear.

 

Laser cannon (Item) fires Laser (Entity) on a right-click (similar to an arrow, but no pre-load)

ItemLaserCannon is extended from Item

EntityLaser is extended from AbstractArrowEntity

RenderLaser is extended from ArrowRenderer

 

So far I have determined the following

1. The entity is being created and runs in Server Thread (caught breakpoint in Tick method, confirmed interaction with player)

2. The renderer appears to be successfully registered (caught breakpoint registry event injection)

3. No errors or anomalies are being registered in the logs.

4. Renderer does not appear to be running in Client Thread (breakpoint in "doRender" method is not caught)

 

I think I have registered everything correctly, another entity I created in the same mod is functioning as expected.

I used this Item/Entity in 1.12 and it worked fine, but in that case I copied the rendering code instead of extending an existing class 

 

My Code 

 

TIA

/P

 

Edited by PhilipChonacky
Link to comment
Share on other sites

19 hours ago, diesieben07 said:

By extending AbstractArrowEntity the game uses SSpawnObjectPacket as the spawn packet. This packet can only handle a set few vanilla entities.

You need to override Entity#createSpawnPacket and return a custom packet which will spawn your entity on the client.

Stop me if I'm going down a rabbit hole, but using SSpawnObjectPacket as a reference, I need to implement IPacket<IClientPlayNetHandler> which has a limited set of handlers for vanilla SpawnPackets (Object, Mob, etc.)

Can I extend something simple like SSpawnGlobalEntityPacket (which has a method in IClientPlayNetHandler) or would it be better to implement a Client Side spawning method [in place of implementing IClientPlayNetHandler?]

 

I may be getting in over my head as IClientPlayNetHandler seems to implement several Thread safeguards that I'm not familiar with.

 

Bonus question: SSpawnObjectPacket seems to use a deprecated methods for identifying/retrieving the EntityEntry  so it can be serialized and sent to the Client - is there a preferred method? The only thing I could come up with is retrieving the entire map from the [Forge] Registry and transmitting the key for lookup on the Client side (which could be just reinventing the wheel)

 

thanks again.

/P

Link to comment
Share on other sites

OK, I read through the SimpleChannel documentation [several times], and have some idea about how it operates.  I also read some of the code example here, with the understanding that since IMessage no longer exists, it is not required to implement it in the custom packet classes. (just create the required methods and register them through the registerMessage method).

 

The question I still have is whether I need to create a handler (or not) to spawn the Entity on the client.   The docs say that it is handled in Forge, but don’t specify whether some method needs to be invoked (or event caught).  A further question if Forge handles the client-side spawn is  which data do I need to send.

 

TIA

/P

Edited by PhilipChonacky
embellishment
Link to comment
Share on other sites

Do I need to spawn the custom entity using my custom packet handler, or is there already a process within Forge that will handle that

(and if so, which process is it and what data do I need to send).

 

Apologies if this sounds like a stupid question, but much of the networking process is a bit over my head, and I haven't as of yet found any other code examples for spawning custom entities in 1.13/1.14].  I tend to learn much better by example

 

Thanks again.

/P 

Link to comment
Share on other sites

The more I'm thinking about this, the more I'm thinking that my custom packet 'handle' method needs a spawn [LaserEntity] in it.  The only remaining question would be what I data would I need (UUID?) in order to keep it associated with the copy on the server so that it properly receives tracking updates.

 

Comments?

 

I promise when this is all over I will write a brief tutorial for others (assuming I'm not the only one going down this road)

 

/P

Edited by PhilipChonacky
spelling
Link to comment
Share on other sites

For the past couple days, I have been attempting to make this work creating what I believe to be the correct class files.

The original reason that object entities (extended from AbstractArrowEntity and probably Snowball as well) won't spawn on the client is that the Class ClientPlayNetHandler which handles SSPawnObjectSpawnPackets is testing for specific Vanilla EntityTypes and doesn't recognize my custom entity.

 

I have created the following classes to implement a SimpleChannel spawn packet

1. LaserSpawnPacket.java which is the spawn packet class - includes encode, decode, and handle methods per the requirements.  I put the code for spawning the entity [Client Side], but I'm not clear if it should go here, or I should create an additional class (Client only) to perform the spawn.

2. ChickenModPacketHandler.java which holds the static SimpleChannel instance, and registers the spawn packet methods

 

EntityLaser.java is the [Object] Entity I am trying to spawn, it overrides the createSpawnPacket method from AbstractArrowEntity.

EntityLaser is spawned from an onRightClick method from ItemLaserCannon.java.

 

Where I'm currently stuck:

1. The Java compiler is not accepting my methods as meeting the requirements (int, Class<MSG>, BiConsumer<MSG,PacketBuffer>, Function<PacketBuffer,MSG>, BiConsumer<MSG,Supplier<NetworkEvent.Context>>) and I'm not sure why - to my knowledge (which with regards to  Java/Minecraft is somewhat limited) I have done it correctly.

[fixed, I was loading the wrong Supplier library]

 

2. As mentioned above, I'm not sure if I should spawn the client-side entity from my own method, or hand it off somehow to a Forge method

[I determined that the SpawnPacket class is responsible for this, that's why we use NetworkEvent.Context#get.enqueueWork to execute on the Main (Client) thread]

 

3. As I'm not really sure how Minecraft tracks the plurality of entities between Server and Client, I don't know if I'm successful, whether tracking from Server to Client would continue (or not).  Assigning ID?

 

Any help would be appreciated, as I have looked around, I haven't found any mention of others doing this in 1.14, and the only advise I have gotten so far is "override Entity#createSpawnPacket and return a custom packet which will spawn your entity on the client.".  Maybe I'm overlooking something obvious.  in 1.12 it was as simple as extending AbstractArrow or Snowball and it would work with relatively little coding, since 1.13, all this has changed.

Edited by PhilipChonacky
update
Link to comment
Share on other sites

Hey, so I've managed to spawn my custom entity by letting my custom spawn packet implement

IPacket<ClientPlayNetHandler>

and processing the packet in the packet class as well by using some of the code from

ClientPlayNetHandler - handleSpawnObject(SSpawnObjectPacket packetIn)

 

I also return a new packet instance in my entity class in the createSpawnPacket() method.

 

i.e.

process method in my packet class

@Override
public void processPacket(ClientPlayNetHandler handler)
{
        Entity entity = entityType.create(handler.getWorld());

        entity.func_213312_b(this.x, this.y, this.z);
        entity.rotationPitch = (float)(this.pitch * 360) / 256.0F;
        entity.rotationYaw = (float)(this.yaw * 360) / 256.0F;
        entity.setEntityId(this.entityId);
        entity.setUniqueId(this.uuid);
        handler.getWorld().addEntity(this.entityId, entity);
}

 

createSpawnPacket() in my entity class

@Override
public IPacket<?> createSpawnPacket()
{
        return new MagicModEntitySpawnPacket(MagicModRegistry.TestEntityType, this.getEntityId(), this.entityUniqueID, this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
}

 

Edited by FilUnderscore
code examples
Link to comment
Share on other sites

7 hours ago, FilUnderscore said:

Hey, so I've managed to spawn my custom entity by letting my custom spawn packet implement


IPacket<ClientPlayNetHandler>

and processing the packet in the packet class as well by using some of the code from


ClientPlayNetHandler - handleSpawnObject(SSpawnObjectPacket packetIn)

 

I also return a new packet instance in my entity class in the createSpawnPacket() method.

How did you handle the networking? ClientPlayNetHandler  usually receives the spawn packets.  Is there an event that can be subscribed to?

Do you have a GitRepo I can look at?

 

I've seen other posts advising to stay away from IPacket, so I didn't and sent the packet using SimpleChannel 

(returning super.createSpawnPacket to keep MC from crashing)

 

...not working yet, but at least it doesn't crash

 

I'll post my code when I get home

Edited by PhilipChonacky
Link to comment
Share on other sites

Update: I got the SimpleChannel system to work (mostly)

entityLaser#createSpawnPacket sends packet with PacketDistributor.TRACKING_CHUNK  which is passed and handled by LaserSpawnPacket.Handler#handle

I confirmed the new EntityLaser instance is accurately created, but for whatever reason, it doesn't get added to chunk (if I'm understanding that field entity correctly)

...need to double-check my math, I may be spawning in the wrong location

Link to comment
Share on other sites

4 hours ago, PhilipChonacky said:

Update: I got the SimpleChannel system to work (mostly)

entityLaser#createSpawnPacket sends packet with PacketDistributor.TRACKING_CHUNK  which is passed and handled by LaserSpawnPacket.Handler#handle

I confirmed the new EntityLaser instance is accurately created, but for whatever reason, it doesn't get added to chunk (if I'm understanding that field entity correctly)

...need to double-check my math, I may be spawning in the wrong location

After reading your previous responses, I've managed to do the same thing and got my entity to spawn too - following the SimpleChannel implementation, the main thing is that apparently you need to call

world.addEntity(entID, entityInstance)

instead of world.addEntity(entityInstance)

Edited by FilUnderscore
Link to comment
Share on other sites

19 hours ago, FilUnderscore said:

you need to call


world.addEntity(entID, entityInstance)

instead of world.addEntity(entityInstance)

Which version of MC are you using?  I'm using 1.14.3 [Forge 27.0.25] and that overload isn't available

Edited by PhilipChonacky
Link to comment
Share on other sites

5 hours ago, PhilipChonacky said:

Using that [ClientWorld], and I spawned the entity - now I have a thread violation (reaching across server/client).

I think the server thread is crashing or getting caught in a loop

 

Repo Updated

 

...I think I need to make sure the handler code runs only on the Client

I believe that this line:

world.addEntity(msg.shooterId,entity);

should be:

world.addEntity(entity.getEntityID(),entity);

 

I don't know whether this has anything to do with the threading?

Edited by FilUnderscore
Link to comment
Share on other sites

9 minutes ago, FilUnderscore said:

I believe that this line:


world.addEntity(msg.shooterId,entity);

should be:


world.addEntity(entity.getEntityID(),entity);

 

I don't know whether this has anything to do with the threading?

That doesn't make sense.  Entity ID is an index number given to keep track of the entity in the world.

Normally when you create a new entity, this number is incremented (so all entries are unique)

I think this is the filed that MC uses to synchronize objects between server and client side.

Using ClientWorld#addEntity(id, entity) adds the entity to the [client] world using the provided ID instead of the  ID from the entity you just created

public void addEntity(int p_217411_1_, Entity p_217411_2_) {
      this.addEntityImpl(p_217411_1_, p_217411_2_);
   }

   private void addEntityImpl(int p_217424_1_, Entity p_217424_2_) {
      if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(p_217424_2_, this))) return;
      this.removeEntityFromWorld(p_217424_1_);
      this.entitiesById.put(p_217424_1_, p_217424_2_);
      this.getChunkProvider().getChunk(MathHelper.floor(p_217424_2_.posX / 16.0D), MathHelper.floor(p_217424_2_.posZ / 16.0D), ChunkStatus.FULL, true).addEntity(p_217424_2_);
      p_217424_2_.onAddedToWorld();
   }

 

using addEntity(entity.getEntityID(),entity) copies the ID from  the entity you just created, which is the next sequential ID, that's why I pull the ID from the spawn packet (which has the original ID).

I resolved the cross-side [thread] issue by creating a separate client-only Class [ClientWork] and putting the spawn code there as a static method.  It works now, but the client rendered entity disappears almost immediately.  If I increment the ID, it spawns an unsynchronized client entity that just drops to the ground (can't even kill it with '/kill @e' .

Updated Code

...so close

Link to comment
Share on other sites

12 minutes ago, PhilipChonacky said:

That doesn't make sense.  Entity ID is an index number given to keep track of the entity in the world.

Normally when you create a new entity, this number is incremented (so all entries are unique)

I think this is the filed that MC uses to synchronize objects between server and client side.

Using ClientWorld#addEntity(id, entity) adds the entity to the [client] world using the provided ID instead of the  ID from the entity you just created


public void addEntity(int p_217411_1_, Entity p_217411_2_) {
      this.addEntityImpl(p_217411_1_, p_217411_2_);
   }

   private void addEntityImpl(int p_217424_1_, Entity p_217424_2_) {
      if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(p_217424_2_, this))) return;
      this.removeEntityFromWorld(p_217424_1_);
      this.entitiesById.put(p_217424_1_, p_217424_2_);
      this.getChunkProvider().getChunk(MathHelper.floor(p_217424_2_.posX / 16.0D), MathHelper.floor(p_217424_2_.posZ / 16.0D), ChunkStatus.FULL, true).addEntity(p_217424_2_);
      p_217424_2_.onAddedToWorld();
   }

 

using addEntity(entity.getEntityID(),entity) copies the ID from  the entity you just created, which is the next sequential ID, that's why I pull the ID from the spawn packet (which has the original ID).

I resolved the cross-side [thread] issue by creating a separate client-only Class [ClientWork] and putting the spawn code there as a static method.  It works now, but the client rendered entity disappears almost immediately.  If I increment the ID, it spawns an unsynchronized client entity that just drops to the ground (can't even kill it with '/kill @e' .

Updated Code

...so close

I do set my client-side entity's ID and UUID through entity.setEntityID() and entity.setUniqueID() from the packet before adding it, which I notice you aren't doing?

Edited by FilUnderscore
Link to comment
Share on other sites

 

 I put in logging code to track the entity on both Server and Client, which clearly shows the Entity gets spawned on both Server & Client with matching IDs, but the rendering stops almost immediately.  The Client-side entity is

being removed after one or two ticks.   Not sure why this is happening.  

 

Edited by PhilipChonacky
Update
Link to comment
Share on other sites

This solved the problem for me

First register your entity with custom client factory like this 

 

.setCustomClientFactory((spawnEntity, world) -> new ExempleEntity(world))

 

And then use NetworkHooks#getEntitySpawningPacket to get Entity Spawning Packet

 

    @Override
    public IPacket<?> createSpawnPacket() {
        return NetworkHooks.getEntitySpawningPacket(this);
    }

 

that's it ?

Edited by xieao
  • Thanks 6
Link to comment
Share on other sites

2 hours ago, xieao said:

This solved the problem for me

First register your entity with custom client factory like this 

 


.setCustomClientFactory((spawnEntity, world) -> new ExempleEntity(world))

 

And then use forge hooks to get Entity Spawning Packet

 


    @Override
    public IPacket<?> createSpawnPacket() {
        return NetworkHooks.getEntitySpawningPacket(this);
    }

 

that's it ?

That was it! Thanks! [so simple]

 

If only that had been mentioned before, I would have had to try and reinvent the wheel.

 

Edited by PhilipChonacky
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

    • Minecraft Version: 1.8-1.20.X Forge Version: All (Tested on 49.0.27, 11.14.4.1577 and some others) Steps to Reproduce: Setup a server with IPV6 only Setup a docker container with forge Try to connect to the Forge Server Description of issue: Hello, I am reaching out to seek your expertise within this forum to clarify a technical situation I am encountering, suspecting a potential issue related to Forge in a Docker environment, specifically in an IPv6 context. Initial Configuration: Debian 12 server, configured exclusively for IPv6, with Docker installed. Using the Docker image ghcr.io/pterodactyl/yolks:java_17, launching a Minecraft Vanilla server version 1.20.4 proceeds without any issues. Problem: The issue arises when deploying a Minecraft Forge server version 1.20.4 with the same Docker image (ghcr.io/pterodactyl/yolks:java_17), where connecting to the server becomes impossible. Notably, this issue does not occur when launching outside of Docker, where the server functions as expected. Hypothesis: This situation leads me to question the interaction between Forge and Docker, particularly in an IPv6-only configuration, despite several resolution attempts (testing with different versions of Forge, adjusting container network configurations (0.0.0.0, ::/0, and the server's ipv6), trials with various network settings, and modifications of Java options). Further testing was conducted with and without the use of the Pterodactyl game panel, unsuccessfully. The parameter -Djava.net.preferIPv4Stack=false also did not provide a solution. I tried to do the same things on multiple Minecraft server (include vanilla,spigot,fabric,sponge) and this work fine. The problem only happend with Forge. This issue seem to happend on all forge versions.   I appreciate your time and assistance in advance.
    • The game crashed whilst exception ticking world Error: java.lang.NullPointerException: Cannot invoke "net.minecraft.resources.ResourceLocation.equals(Object)" because "this.lootTableId" is null Error given is above. I was already playing for around 15 minutes and wasn't doing anything specific or even breaking anything when the crashed happened. This is update 1.19.2 forge: 43.2.23 Mod list: ESSENTIAL Mod (by SparkUniverse_) Traveler's Titles (Forge) (by YUNGNICKYOUNG) Resourceful Config (by ThatGravyBoat) Dynamic Lights (by atomicstrykergrumpy) TenzinLib (by CommodoreThrawn) Nature's Compass (by Chaosyr) Library Ferret - Forge (by jtl_elisa) Cold Sweat (by Mikul) Simple Voice Chat (by henkelmax) Waystones (by BlayTheNinth) Carry On (by Tschipp) [Let's Do] Meadow (by satisfy) Creeper Overhaul (by joosh_7889) AutoRegLib (by Vazkii) Moonlight Lib (by MehVahdJukaar) AppleSkin (by squeek502) Xaero's World Map (by xaero96) Rotten Creatures (by fusionstudiomc) YUNG's API (Forge) (by YUNGNICKYOUNG) Village Artifacts (by Lothrazar) Right Click, Get Crops (by TeamCoFH) Supplementaries (by MehVahdJukaar) Automatic Tool Swap (by MelanX) Better Third Person (by Socolio) Supplementaries Squared (by plantspookable) Traveler's Backpack (by Tiviacz1337) Caelus API (Forge/NeoForge) (by TheIllusiveC4) Creatures and Beasts (by joosh_7889) Architectury API (Fabric/Forge/NeoForge) (by shedaniel) Quark Oddities (by Vazkii) Origins (Forge) (by EdwinMindcraft) Villager Names (by Serilum) GeckoLib (by Gecko) Realistic Bees (by Serilum) Illuminations Forge 🔥 (by dimadencep) Serene Seasons (by TheAdubbz) Critters and Companions (by joosh_7889) [Let's Do] Bakery (by satisfy) Falling Leaves (Forge) (by Cheaterpaul) Jade 🔍 (by Snownee) Collective (by Serilum) TerraBlender (Forge) (by TheAdubbz) [Let's Do] API (by Cristelknight) Towns and Towers (by Biban_Auriu) More Villagers (by SameDifferent) Biomes O' Plenty (by Forstride) Goblin Traders (by MrCrayfish) Corpse (by henkelmax) Tree Harvester (by Serilum) Balm (Forge Edition) (by BlayTheNinth) Mouse Tweaks (by YaLTeR) Sound Physics Remastered (by henkelmax) Xaero's Minimap (by xaero96) Just Enough Items (JEI) (by mezz) Terralith (by Starmute) Quark (by Vazkii) [Let's Do] Vinery (by satisfy) [Let's Do] Candlelight (by satisfy) Repurposed Structures (Neoforge/Forge) (by telepathicgrunt) Dusty Decorations (by flint_mischiff) Immersive Armors [Fabric/Forge] (by Conczin) Serene Seasons Fix (by Or_OS) Shutup Experimental Settings! (by Corgi_Taco) Skin Layers 3D (Fabric/Forge) (by tr7zw)
    • Make sure Java is running via Nvidia GPU https://windowsreport.com/minecraft-not-using-gpu/  
    • Also make a test with other Custom Launchers like AT Launcher, MultiMC or Technic Launcher
    • Embeddium and valkyrienskies are not working together - remove one of these mods With removing Embeddium, also remove Oculus, TexTrue's Embeddium Options and Embeddium Extras Or use Rubidium instead
  • Topics

×
×
  • Create New...

Important Information

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