#914: Add World#spawn with randomizeData parameter

The current implementation of World#spawn or World#spawnEntity
respectively, always prepares/finalizes the spawn of every entity
spawned through the API. While this is great to simulate natural
spawning of entities in the world through the API, it fails at
reliably creating default entities for purposes other than vanilla
gameplay.

While the caller of the API could attempt to undo all of the
customization that is applied in the prepare/finalization step, they are
numerous (reaching from sheep colour to equipment) and in some cases,
such as the chicken jockey, even spawn in other entities.

Hence this commit introduces a new overload to the World#spawn and
World#spawnEntity methods that accepts the 'randomizeData' parameter
that, when set to false, skips the prior mentioned
preparation/finalization step.
This commit is contained in:
Bjarne Koll 2021-08-18 18:04:53 +10:00 committed by md_5
parent 3cad0316e0
commit 18027d0239
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11

View File

@ -380,6 +380,11 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
return spawn(location, entityType.getEntityClass()); return spawn(location, entityType.getEntityClass());
} }
@Override
public Entity spawnEntity(Location loc, EntityType type, boolean randomizeData) {
return spawn(loc, type.getEntityClass(), null, CreatureSpawnEvent.SpawnReason.CUSTOM, randomizeData);
}
@Override @Override
public List<Entity> getEntities() { public List<Entity> getEntities() {
List<Entity> list = new ArrayList<Entity>(); List<Entity> list = new ArrayList<Entity>();
@ -472,22 +477,31 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
return spawn(location, clazz, function, CreatureSpawnEvent.SpawnReason.CUSTOM); return spawn(location, clazz, function, CreatureSpawnEvent.SpawnReason.CUSTOM);
} }
@Override
public <T extends Entity> T spawn(Location location, Class<T> clazz, boolean randomizeData, Consumer<T> function) throws IllegalArgumentException {
return spawn(location, clazz, function, CreatureSpawnEvent.SpawnReason.CUSTOM, randomizeData);
}
public <T extends Entity> T spawn(Location location, Class<T> clazz, Consumer<T> function, CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException { public <T extends Entity> T spawn(Location location, Class<T> clazz, Consumer<T> function, CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException {
return spawn(location, clazz, function, reason, true);
}
public <T extends Entity> T spawn(Location location, Class<T> clazz, Consumer<T> function, CreatureSpawnEvent.SpawnReason reason, boolean randomizeData) throws IllegalArgumentException {
net.minecraft.world.entity.Entity entity = createEntity(location, clazz); net.minecraft.world.entity.Entity entity = createEntity(location, clazz);
return addEntity(entity, reason, function); return addEntity(entity, reason, function, randomizeData);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Entity> T addEntity(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException { public <T extends Entity> T addEntity(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason) throws IllegalArgumentException {
return addEntity(entity, reason, null); return addEntity(entity, reason, null, true);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Entity> T addEntity(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason, Consumer<T> function) throws IllegalArgumentException { public <T extends Entity> T addEntity(net.minecraft.world.entity.Entity entity, CreatureSpawnEvent.SpawnReason reason, Consumer<T> function, boolean randomizeData) throws IllegalArgumentException {
Preconditions.checkArgument(entity != null, "Cannot spawn null entity"); Preconditions.checkArgument(entity != null, "Cannot spawn null entity");
if (entity instanceof EntityInsentient) { if (randomizeData && entity instanceof EntityInsentient) {
((EntityInsentient) entity).prepare(getHandle(), getHandle().getDamageScaler(entity.getChunkCoordinates()), EnumMobSpawn.COMMAND, (GroupDataEntity) null, null); ((EntityInsentient) entity).prepare(getHandle(), getHandle().getDamageScaler(entity.getChunkCoordinates()), EnumMobSpawn.COMMAND, (GroupDataEntity) null, null);
} }