Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

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 by izofar

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.

  • Author
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?

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.

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?

  • Author
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 by izofar

  • izofar changed the title to [1.16.5] Spawning Entities in ServerWorld (Solved)
  • Author
7 minutes ago, Luis_ST said:

you can use Level#isAreaLoaded

worked for me! Thanks!

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.

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...

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.