izofar Posted September 27, 2021 Share Posted September 27, 2021 (edited) Goal My goal is to replace naturally spawning iron golems with my modded clay golems, but still allowing for players to build their own iron golems. I have the following SubscribeEvent: Code @SubscribeEvent public static void onIronGolemJoinWorld(EntityJoinWorldEvent event) { if(event.getEntity() instanceof IronGolemEntity) { if(event.getWorld() instanceof ServerWorld) { IronGolemEntity entity = (IronGolemEntity) event.getEntity(); ServerWorld world = (ServerWorld)event.getWorld(); if(!entity.isPlayerCreated()) { ExampleMod.LOGGER.info("Iron Golem Found!"); ModEntities.CLAY_GOLEM.spawn(world, null, null, entity.blockPosition(), SpawnReason.MOB_SUMMONED, false, false); ExampleMod.LOGGER.info("Spawned Clay Golem"); } } event.setCanceled(true); ExampleMod.LOGGER.info("Removed Iron Golem"); } } Context I Hope This Isn't a Duplicate Question, I have read the link but still do not understand what I've done wrong. I have read the vanilla code and understand that in order to call the private World#addEntity, I must call ServerWorld#addFreshEntity (true for spawning golems with pumpkins, and silverfish blocks, etc.). Alternatively, spawn eggs call EntityType<?>#spawn, but check that the world parameter is a ServerWorld. The result of the code above is the same as when I use: ClayGolemEntity claygolementity = ModEntities.CLAY_GOLEM.create(world); ExampleMod.LOGGER.info("Created Clay Golem"); claygolementity.moveTo(entity.position()); ExampleMod.LOGGER.info("Moved Clay Golem"); world.addFreshEntity(claygolementity); ExampleMod.LOGGER.info("Spawned Clay Golem"); Results My issue is that the following occurs: (1) using /summon examplemod:iron_golem spawns in a clay golem. Not ideal, but I'm fine with this at the moment. (2) Constructing Iron Golems constructs and iron golem, as intended (3) Any naturally spawning golems in villages lags out the game to the point of needing to force quit. (4) using /summon to spawn an iron golem (with the event.canceled(true) commented out) and then reloading the world lags out as well. The last print statement is either "Iron Golem Found" as in the first code example, or "Moved Clay Golem" as in the second code example. I appreciate the help. I haven't yet been able to spawn an entity in the world in code yet. Edited September 28, 2021 by izofar Quote Link to comment Share on other sites More sharing options...
ChampionAsh5357 Posted September 27, 2021 Share Posted September 27, 2021 Reading the javadoc on the event tells you: "Note: This event may be called before the underlying Chunk is promoted to ChunkStatus#FULL. You will cause chunk loading deadlocks if you don't delay your world interactions." As such, you should probably keep a queue of entities added along with the world and position you would like it to spawn at. Then, on the next tick in probably WorldTickEvent, check if the chunk is loaded at the position of spawning and if so spawn the entity. Otherwise, recycle into the queue until next tick. 1 Quote Link to comment Share on other sites More sharing options...
izofar Posted September 28, 2021 Author Share Posted September 28, 2021 3 hours ago, ChampionAsh5357 said: Reading the javadoc on the event tells you: "Note: This event may be called before the underlying Chunk is promoted to ChunkStatus#FULL. You will cause chunk loading deadlocks if you don't delay your world interactions." As such, you should probably keep a queue of entities added along with the world and position you would like it to spawn at. Then, on the next tick in probably WorldTickEvent, check if the chunk is loaded at the position of spawning and if so spawn the entity. Otherwise, recycle into the queue until next tick. Is there an easier way to do this? How would the iron golem have spawned in the first place without chunk deadlocks? Is it easier to modify the villager behavior to spawn the modded entity instead? Quote Link to comment Share on other sites More sharing options...
ChampionAsh5357 Posted September 28, 2021 Share Posted September 28, 2021 9 hours ago, izofar said: Is there an easier way to do this? How would the iron golem have spawned in the first place without chunk deadlocks? Is it easier to modify the villager behavior to spawn the modded entity instead? 1. Not afaik. 2. The entity is was already added and deferred to load at the correct time already. Follow the event call and you'll see that entities are loaded at a very specific point when processing. Trying to add your own entity at any point in this process would mean you could be loading a chunk that's already loading. 3. No, that is much more difficult. 1 Quote Link to comment Share on other sites More sharing options...
Luis_ST Posted September 28, 2021 Share Posted September 28, 2021 16 hours ago, ChampionAsh5357 said: Then, on the next tick in probably WorldTickEvent, check if the chunk is loaded at the position of spawning and if so spawn the entity. would this also be possible in LivingUpdateEvent? Quote Link to comment Share on other sites More sharing options...
izofar Posted September 28, 2021 Author Share Posted September 28, 2021 (edited) 20 hours ago, ChampionAsh5357 said: check if the chunk is loaded at the position of spawning The Chunk#isLoaded seems to be depreciated, nor is there a ChunkLoader#chunkExists (my research)... what's the new way of doing this? The Chunk#loaded field is private, and the Chunk#getStatus method always returns ChunkStatus.FULL... I can get the chunk with entity.level.getChunk(entity.getBlockPosition()), but what then? Must I use reflection for this? Surely there's a cleaner way. What was previously isChunkLoaded (which Jabelar said World#isAreaLoaded utilizes) seems to be hasChunksAt, which is marked depreciated. Any guidance on this? Edited September 28, 2021 by izofar Quote Link to comment Share on other sites More sharing options...
Luis_ST Posted September 28, 2021 Share Posted September 28, 2021 you can use Level#isAreaLoaded 1 Quote Link to comment Share on other sites More sharing options...
izofar Posted September 28, 2021 Author Share Posted September 28, 2021 7 minutes ago, Luis_ST said: you can use Level#isAreaLoaded worked for me! Thanks! Quote Link to comment Share on other sites More sharing options...
ChampionAsh5357 Posted September 28, 2021 Share Posted September 28, 2021 4 hours ago, Luis_ST said: would this also be possible in LivingUpdateEvent? No, that is applied for every living entity so essentially you would be checking as many times as there are entities instead of once per tick. Quote 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.