2021-03-15 23:00:00 +01:00
--- a/net/minecraft/server/level/WorldServer.java
+++ b/net/minecraft/server/level/WorldServer.java
2021-07-11 01:05:59 +02:00
@@ -152,6 +152,19 @@
2014-11-25 22:32:16 +01:00
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+// CraftBukkit start
2021-03-15 23:00:00 +01:00
+import net.minecraft.world.entity.monster.EntityDrowned;
+import net.minecraft.world.level.storage.WorldDataServer;
2019-04-23 04:00:00 +02:00
+import org.bukkit.Bukkit;
2014-11-25 22:32:16 +01:00
+import org.bukkit.WeatherType;
2019-04-23 04:00:00 +02:00
+import org.bukkit.craftbukkit.event.CraftEventFactory;
2020-06-25 02:00:00 +02:00
+import org.bukkit.craftbukkit.util.WorldUUID;
2019-04-23 04:00:00 +02:00
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.server.MapInitializeEvent;
2014-11-25 22:32:16 +01:00
+import org.bukkit.event.weather.LightningStrikeEvent;
2019-12-21 02:06:18 +01:00
+import org.bukkit.event.world.TimeSkipEvent;
2014-11-25 22:32:16 +01:00
+// CraftBukkit end
+
2020-06-25 02:00:00 +02:00
public class WorldServer extends World implements GeneratorAccessSeed {
2021-06-11 07:00:00 +02:00
public static final BlockPosition END_SPAWN_POINT = new BlockPosition(100, 50, 0);
2021-07-11 01:05:59 +02:00
@@ -160,7 +173,7 @@
2021-06-11 07:00:00 +02:00
final List<EntityPlayer> players;
private final ChunkProviderServer chunkSource;
2020-06-25 02:00:00 +02:00
private final MinecraftServer server;
2021-06-11 07:00:00 +02:00
- public final IWorldDataServer serverLevelData;
+ public final WorldDataServer serverLevelData; // CraftBukkit - type
final EntityTickList entityTickList;
2021-07-06 16:00:00 +02:00
public final PersistentEntitySectionManager<Entity> entityManager;
2021-06-11 07:00:00 +02:00
public boolean noSave;
2021-07-11 01:05:59 +02:00
@@ -180,31 +193,52 @@
2021-06-11 07:00:00 +02:00
private final StructureManager structureFeatureManager;
private final boolean tickTime;
2020-06-25 02:00:00 +02:00
2020-08-11 23:00:00 +02:00
- public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1) {
2021-06-11 07:00:00 +02:00
- Objects.requireNonNull(minecraftserver);
2020-08-11 23:00:00 +02:00
- super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i);
2020-06-25 02:00:00 +02:00
+
2015-02-26 23:41:06 +01:00
+ // CraftBukkit start
2019-04-23 04:00:00 +02:00
+ private int tickPosition;
2020-06-25 02:00:00 +02:00
+ public final Convertable.ConversionSession convertable;
+ public final UUID uuid;
2014-11-25 22:32:16 +01:00
+
2020-06-25 02:00:00 +02:00
+ public Chunk getChunkIfLoaded(int x, int z) {
2021-06-11 07:00:00 +02:00
+ return this.chunkSource.getChunkAt(x, z, false);
2020-06-25 02:00:00 +02:00
+ }
2019-04-23 04:00:00 +02:00
+
2020-06-25 02:00:00 +02:00
+ // Add env and gen to constructor, WorldData -> WorldDataServer
SPIGOT-5880, SPIGOT-5567: New ChunkGenerator API
## **Current API**
The current world generation API is very old and limited when you want to make more complex world generation. Resulting in some hard to fix bugs such as that you cannot modify blocks outside the chunk in the BlockPopulator (which should and was per the docs possible), or strange behavior such as SPIGOT-5880.
## **New API**
With the new API, the generation is more separate in multiple methods and is more in line with Vanilla chunk generation. The new API is designed to as future proof as possible. If for example a new generation step is added it can easily also be added as a step in API by simply creating the method for it. On the other side if a generation step gets removed, the method can easily be called after another, which is the case with surface and bedrock. The new API and changes are also fully backwards compatible with old chunk generators.
### **Changes in the new api**
**Extra generation steps:**
Noise, surface, bedrock and caves are added as steps. With those generation steps three extra methods for Vanilla generation are also added. Those new methods provide the ChunkData instead of returning one. The reason for this is, that the ChunkData is now backed by a ChunkAccess. With this, each step has the information of the step before and the Vanilla information (if chosen by setting a 'should' method to true). The old method is deprecated.
**New class BiomeProvider**
The BiomeProvider acts as Biome source and wrapper for the NMS class WorldChunkManager. With this the underlying Vanilla ChunkGeneration knows which Biome to use for the structure and decoration generation. (Fixes: SPIGOT-5880). Although the List of Biomes which is required in BiomeProvider, is currently not much in use in Vanilla, I decided to add it to future proof the API when it may be required in later versions of Minecraft.
The BiomeProvider is also separated from the ChunkGenerator for plugins which only want to change the biome map, such as single Biome worlds or if some biomes should be more present than others.
**Deprecated isParallelCapable**
Mojang has and is pushing to a more multi threaded chunk generation. This should also be the case for custom chunk generators. This is why the new API only supports multi threaded generation. This does not affect the old API, which is still checking this.
**Base height method added**
This method was added to also bring the Minecraft generator and Bukkit generator more in line. With this it is possible to return the max height of a location (before decorations). This is useful to let most structures know were to place them. This fixes SPIGOT-5567. (This fixes not all structures placement, desert pyramids for example are still way up at y-level 64, This however is more a vanilla bug and should be fixed at Mojangs end).
**WorldInfo Class**
The World object was swapped for a WorldInfo object. This is because many methods of the World object won't work during world generation and would mostly likely result in a deadlock. It contains any information a plugin should need to identify the world.
**BlockPopulator Changes**
Instead of directly manipulating a chunk, changes are now made to a new class LimitedRegion, this class provides methods to populated the chunk and its surrounding area. The wrapping is done so that the population can be moved into the place where Minecraft generates decorations. Where there is no chunk to access yet. By moving it into this place the generation is now async and the surrounding area of the chunk can also be used.
For common methods between the World and LimitedRegion a RegionAccessor was added.
By: DerFrZocker <derrieple@gmail.com>
2021-08-15 00:08:16 +02:00
+ public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey<World> resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<MobSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) {
2021-06-11 07:00:00 +02:00
+ // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
SPIGOT-5880, SPIGOT-5567: New ChunkGenerator API
## **Current API**
The current world generation API is very old and limited when you want to make more complex world generation. Resulting in some hard to fix bugs such as that you cannot modify blocks outside the chunk in the BlockPopulator (which should and was per the docs possible), or strange behavior such as SPIGOT-5880.
## **New API**
With the new API, the generation is more separate in multiple methods and is more in line with Vanilla chunk generation. The new API is designed to as future proof as possible. If for example a new generation step is added it can easily also be added as a step in API by simply creating the method for it. On the other side if a generation step gets removed, the method can easily be called after another, which is the case with surface and bedrock. The new API and changes are also fully backwards compatible with old chunk generators.
### **Changes in the new api**
**Extra generation steps:**
Noise, surface, bedrock and caves are added as steps. With those generation steps three extra methods for Vanilla generation are also added. Those new methods provide the ChunkData instead of returning one. The reason for this is, that the ChunkData is now backed by a ChunkAccess. With this, each step has the information of the step before and the Vanilla information (if chosen by setting a 'should' method to true). The old method is deprecated.
**New class BiomeProvider**
The BiomeProvider acts as Biome source and wrapper for the NMS class WorldChunkManager. With this the underlying Vanilla ChunkGeneration knows which Biome to use for the structure and decoration generation. (Fixes: SPIGOT-5880). Although the List of Biomes which is required in BiomeProvider, is currently not much in use in Vanilla, I decided to add it to future proof the API when it may be required in later versions of Minecraft.
The BiomeProvider is also separated from the ChunkGenerator for plugins which only want to change the biome map, such as single Biome worlds or if some biomes should be more present than others.
**Deprecated isParallelCapable**
Mojang has and is pushing to a more multi threaded chunk generation. This should also be the case for custom chunk generators. This is why the new API only supports multi threaded generation. This does not affect the old API, which is still checking this.
**Base height method added**
This method was added to also bring the Minecraft generator and Bukkit generator more in line. With this it is possible to return the max height of a location (before decorations). This is useful to let most structures know were to place them. This fixes SPIGOT-5567. (This fixes not all structures placement, desert pyramids for example are still way up at y-level 64, This however is more a vanilla bug and should be fixed at Mojangs end).
**WorldInfo Class**
The World object was swapped for a WorldInfo object. This is because many methods of the World object won't work during world generation and would mostly likely result in a deadlock. It contains any information a plugin should need to identify the world.
**BlockPopulator Changes**
Instead of directly manipulating a chunk, changes are now made to a new class LimitedRegion, this class provides methods to populated the chunk and its surrounding area. The wrapping is done so that the population can be moved into the place where Minecraft generates decorations. Where there is no chunk to access yet. By moving it into this place the generation is now async and the surrounding area of the chunk can also be used.
For common methods between the World and LimitedRegion a RegionAccessor was added.
By: DerFrZocker <derrieple@gmail.com>
2021-08-15 00:08:16 +02:00
+ super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, biomeProvider, env);
2014-11-25 22:32:16 +01:00
+ this.pvpMode = minecraftserver.getPVP();
2020-06-25 02:00:00 +02:00
+ convertable = convertable_conversionsession;
2021-06-11 07:00:00 +02:00
+ uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile());
2014-11-25 22:32:16 +01:00
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
this.players = Lists.newArrayList();
this.entityTickList = new EntityTickList();
- Predicate predicate = (block) -> {
+ Predicate<Block> predicate = (block) -> { // CraftBukkit - decompile eror
2018-07-15 02:00:00 +02:00
return block == null || block.getBlockData().isAir();
2021-06-11 07:00:00 +02:00
};
RegistryBlocks registryblocks = IRegistry.BLOCK;
Objects.requireNonNull(registryblocks);
- this.blockTicks = new TickListServer<>(this, predicate, registryblocks::getKey, this::b);
- predicate = (fluidtype) -> {
+ this.blockTicks = new TickListServer<>(this, predicate, IRegistry.BLOCK::getKey, this::b); // CraftBukkit - decompile error
+ Predicate<FluidType> predicate2 = (fluidtype) -> { // CraftBukkit - decompile error
return fluidtype == null || fluidtype == FluidTypes.EMPTY;
};
registryblocks = IRegistry.FLUID;
Objects.requireNonNull(registryblocks);
- this.liquidTicks = new TickListServer<>(this, predicate, registryblocks::getKey, this::a);
+ this.liquidTicks = new TickListServer<>(this, predicate2, IRegistry.FLUID::getKey, this::a); // CraftBukkit - decompile error
this.navigatingMobs = new ObjectOpenHashSet();
this.blockEvents = new ObjectLinkedOpenHashSet();
this.dragonParts = new Int2ObjectOpenHashMap();
this.tickTime = flag1;
2020-06-25 02:00:00 +02:00
this.server = minecraftserver;
2021-06-11 07:00:00 +02:00
this.customSpawners = list;
- this.serverLevelData = iworlddataserver;
2020-06-25 02:00:00 +02:00
+ // CraftBukkit start
2021-06-11 07:00:00 +02:00
+ this.serverLevelData = (WorldDataServer) iworlddataserver;
+ serverLevelData.world = this;
2020-06-25 02:00:00 +02:00
+ if (gen != null) {
+ chunkgenerator = new org.bukkit.craftbukkit.generator.CustomChunkGenerator(this, chunkgenerator, gen);
+ }
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
boolean flag2 = minecraftserver.isSyncChunkWrites();
DataFixer datafixer = minecraftserver.getDataFixer();
EntityPersistentStorage<Entity> entitypersistentstorage = new EntityStorage(this, new File(convertable_conversionsession.a(resourcekey), "entities"), datafixer, flag2, minecraftserver);
2021-07-11 01:05:59 +02:00
@@ -231,14 +265,15 @@
2020-07-17 00:56:56 +02:00
iworlddataserver.setGameType(minecraftserver.getGamemode());
}
2021-06-11 07:00:00 +02:00
- this.structureFeatureManager = new StructureManager(this, minecraftserver.getSaveData().getGeneratorSettings());
+ this.structureFeatureManager = new StructureManager(this, this.serverLevelData.getGeneratorSettings()); // CraftBukkit
2020-07-17 00:56:56 +02:00
if (this.getDimensionManager().isCreateDragonBattle()) {
2021-06-11 07:00:00 +02:00
- this.dragonFight = new EnderDragonBattle(this, minecraftserver.getSaveData().getGeneratorSettings().getSeed(), minecraftserver.getSaveData().C());
+ this.dragonFight = new EnderDragonBattle(this, this.serverLevelData.getGeneratorSettings().getSeed(), this.serverLevelData.C()); // CraftBukkit
2020-06-25 02:00:00 +02:00
} else {
2021-06-11 07:00:00 +02:00
this.dragonFight = null;
2015-03-16 12:32:53 +01:00
}
2021-06-11 07:00:00 +02:00
this.sleepStatus = new SleepStatus();
2021-06-11 13:33:49 +02:00
+ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
2019-12-21 02:06:18 +01:00
}
2020-06-25 02:00:00 +02:00
public void a(int i, int j, boolean flag, boolean flag1) {
2021-07-11 01:05:59 +02:00
@@ -331,6 +366,7 @@
2019-05-14 02:00:00 +02:00
this.rainLevel = MathHelper.a(this.rainLevel, 0.0F, 1.0F);
2014-11-25 22:32:16 +01:00
}
2019-04-23 04:00:00 +02:00
+ /* CraftBukkit start
2021-06-11 07:00:00 +02:00
if (this.oRainLevel != this.rainLevel) {
this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel)), this.getDimensionKey());
2014-11-25 22:32:16 +01:00
}
2021-07-11 01:05:59 +02:00
@@ -349,16 +385,45 @@
2021-06-11 07:00:00 +02:00
this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.RAIN_LEVEL_CHANGE, this.rainLevel));
this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.THUNDER_LEVEL_CHANGE, this.thunderLevel));
2019-04-23 04:00:00 +02:00
}
+ // */
+ for (int idx = 0; idx < this.players.size(); ++idx) {
2021-06-11 07:00:00 +02:00
+ if (((EntityPlayer) this.players.get(idx)).level == this) {
2019-04-23 04:00:00 +02:00
+ ((EntityPlayer) this.players.get(idx)).tickWeather();
+ }
+ }
2015-02-26 23:41:06 +01:00
+
2019-04-23 04:00:00 +02:00
+ if (flag != this.isRaining()) {
+ // Only send weather packets to those affected
+ for (int idx = 0; idx < this.players.size(); ++idx) {
2021-06-11 07:00:00 +02:00
+ if (((EntityPlayer) this.players.get(idx)).level == this) {
2019-04-23 04:00:00 +02:00
+ ((EntityPlayer) this.players.get(idx)).setPlayerWeather((!flag ? WeatherType.DOWNFALL : WeatherType.CLEAR), false);
+ }
+ }
+ }
+ for (int idx = 0; idx < this.players.size(); ++idx) {
2021-06-11 07:00:00 +02:00
+ if (((EntityPlayer) this.players.get(idx)).level == this) {
+ ((EntityPlayer) this.players.get(idx)).updateWeather(this.oRainLevel, this.rainLevel, this.oThunderLevel, this.thunderLevel);
2019-04-23 04:00:00 +02:00
+ }
+ }
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
i = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
if (this.sleepStatus.a(i) && this.sleepStatus.a(i, this.players)) {
2019-12-21 02:06:18 +01:00
+ // CraftBukkit start
2021-06-11 07:00:00 +02:00
+ long l = this.levelData.getDayTime() + 24000L;
2019-12-21 02:06:18 +01:00
+ TimeSkipEvent event = new TimeSkipEvent(this.getWorld(), TimeSkipEvent.SkipReason.NIGHT_SKIP, (l - l % 24000L) - this.getDayTime());
2021-06-11 07:00:00 +02:00
if (this.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
- long l = this.levelData.getDayTime() + 24000L;
2021-06-11 13:33:49 +02:00
+ getCraftServer().getPluginManager().callEvent(event);
2019-12-21 02:06:18 +01:00
+ if (!event.isCancelled()) {
+ this.setDayTime(this.getDayTime() + event.getSkipAmount());
+ }
- this.setDayTime(l - l % 24000L);
}
2020-01-21 22:00:00 +01:00
- this.wakeupPlayers();
2019-12-21 02:06:18 +01:00
+ if (!event.isCancelled()) {
2020-01-21 22:00:00 +01:00
+ this.wakeupPlayers();
2019-12-21 02:06:18 +01:00
+ }
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE)) {
2019-12-21 02:06:18 +01:00
this.clearWeather();
}
2021-07-11 01:05:59 +02:00
@@ -380,7 +445,7 @@
2021-06-11 07:00:00 +02:00
this.aq();
this.handlingTick = false;
gameprofilerfiller.exit();
2019-04-23 04:00:00 +02:00
- boolean flag3 = !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty();
+ boolean flag3 = true || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players
if (flag3) {
this.resetEmptyTime();
2021-07-11 01:05:59 +02:00
@@ -396,7 +461,7 @@
2019-04-23 04:00:00 +02:00
2021-06-11 07:00:00 +02:00
this.entityTickList.a((entity) -> {
if (!entity.isRemoved()) {
- if (this.i(entity)) {
+ if (false && this.i(entity)) { // CraftBukkit - We prevent spawning in general, so this butchering is not needed
entity.die();
} else {
gameprofilerfiller.enter("checkDespawn");
2021-07-11 01:05:59 +02:00
@@ -461,7 +526,7 @@
2019-12-10 23:00:00 +01:00
2020-01-21 22:00:00 +01:00
private void wakeupPlayers() {
2021-06-11 07:00:00 +02:00
this.sleepStatus.a();
2019-12-10 23:00:00 +01:00
- ((List) this.players.stream().filter(EntityLiving::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> {
+ (this.players.stream().filter(EntityLiving::isSleeping).collect(Collectors.toList())).forEach((entityplayer) -> { // CraftBukkit - decompile error
entityplayer.wakeup(false, false);
});
}
2021-07-11 01:05:59 +02:00
@@ -488,14 +553,14 @@
2021-06-11 07:00:00 +02:00
entityhorseskeleton.v(true);
2019-04-23 04:00:00 +02:00
entityhorseskeleton.setAgeRaw(0);
entityhorseskeleton.setPosition((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ());
- this.addEntity(entityhorseskeleton);
+ this.addEntity(entityhorseskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit
}
2020-06-25 02:00:00 +02:00
EntityLightning entitylightning = (EntityLightning) EntityTypes.LIGHTNING_BOLT.a((World) this);
2020-08-11 23:00:00 +02:00
entitylightning.d(Vec3D.c((BaseBlockPosition) blockposition));
2020-06-25 02:00:00 +02:00
entitylightning.setEffect(flag1);
- this.addEntity(entitylightning);
+ this.strikeLightning(entitylightning, org.bukkit.event.weather.LightningStrikeEvent.Cause.WEATHER); // CraftBukkit
2019-04-23 04:00:00 +02:00
}
}
2021-07-11 01:05:59 +02:00
@@ -506,12 +571,12 @@
2019-04-23 04:00:00 +02:00
BiomeBase biomebase = this.getBiome(blockposition);
2021-06-11 07:00:00 +02:00
if (biomebase.a((IWorldReader) this, blockposition1)) {
2019-04-23 04:00:00 +02:00
- this.setTypeUpdate(blockposition1, Blocks.ICE.getBlockData());
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.getBlockData(), null); // CraftBukkit
}
2021-06-11 07:00:00 +02:00
if (flag) {
if (biomebase.b(this, blockposition)) {
- this.setTypeUpdate(blockposition, Blocks.SNOW.getBlockData());
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.getBlockData(), null); // CraftBukkit
}
2014-11-25 22:32:16 +01:00
2021-06-11 07:00:00 +02:00
IBlockData iblockdata = this.getType(blockposition1);
2021-07-11 01:05:59 +02:00
@@ -642,10 +707,22 @@
2014-11-25 22:32:16 +01:00
}
2019-04-23 04:00:00 +02:00
private void clearWeather() {
2021-06-11 07:00:00 +02:00
- this.serverLevelData.setWeatherDuration(0);
2018-07-15 02:00:00 +02:00
+ // CraftBukkit start
2021-06-11 07:00:00 +02:00
this.serverLevelData.setStorm(false);
- this.serverLevelData.setThunderDuration(0);
2015-01-04 23:50:48 +01:00
+ // If we stop due to everyone sleeping we should reset the weather duration to some other random value.
+ // Not that everyone ever manages to get the whole server to sleep at the same time....
2021-06-11 07:00:00 +02:00
+ if (!this.serverLevelData.hasStorm()) {
+ this.serverLevelData.setWeatherDuration(0);
2014-11-25 22:32:16 +01:00
+ }
2015-01-04 23:50:48 +01:00
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
this.serverLevelData.setThundering(false);
2015-01-04 23:50:48 +01:00
+ // CraftBukkit start
+ // If we stop due to everyone sleeping we should reset the weather duration to some other random value.
+ // Not that everyone ever manages to get the whole server to sleep at the same time....
2021-06-11 07:00:00 +02:00
+ if (!this.serverLevelData.isThundering()) {
+ this.serverLevelData.setThunderDuration(0);
2014-11-25 22:32:16 +01:00
+ }
+ // CraftBukkit end
}
2019-04-23 04:00:00 +02:00
public void resetEmptyTime() {
2021-07-11 01:05:59 +02:00
@@ -680,6 +757,7 @@
2021-06-11 07:00:00 +02:00
});
gameprofilerfiller.c("tickNonPassenger");
entity.tick();
+ entity.postTick(); // CraftBukkit
this.getMethodProfiler().exit();
Iterator iterator = entity.getPassengers().iterator();
2021-07-11 01:05:59 +02:00
@@ -703,6 +781,7 @@
2019-04-23 04:00:00 +02:00
});
2021-06-11 07:00:00 +02:00
gameprofilerfiller.c("tickPassenger");
entity1.passengerTick();
+ entity1.postTick(); // CraftBukkit
2020-01-21 22:00:00 +01:00
gameprofilerfiller.exit();
2021-06-11 07:00:00 +02:00
Iterator iterator = entity1.getPassengers().iterator();
2014-11-25 22:32:16 +01:00
2021-07-11 01:05:59 +02:00
@@ -727,6 +806,7 @@
2018-12-13 01:00:00 +01:00
ChunkProviderServer chunkproviderserver = this.getChunkProvider();
2014-11-25 22:32:16 +01:00
2019-04-23 04:00:00 +02:00
if (!flag1) {
2014-12-03 20:35:33 +01:00
+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit
2014-11-25 22:32:16 +01:00
if (iprogressupdate != null) {
2020-06-25 02:00:00 +02:00
iprogressupdate.a(new ChatMessage("menu.savingLevel"));
2014-12-03 20:35:33 +01:00
}
2021-07-11 01:05:59 +02:00
@@ -744,11 +824,19 @@
2021-06-11 07:00:00 +02:00
}
2019-06-25 13:02:13 +02:00
}
+
+ // CraftBukkit start - moved from MinecraftServer.saveChunks
+ WorldServer worldserver1 = this;
+
2021-06-11 07:00:00 +02:00
+ serverLevelData.a(worldserver1.getWorldBorder().t());
+ serverLevelData.setCustomBossEvents(this.server.getBossBattleCustomData().save());
+ convertable.a(this.server.registryHolder, this.serverLevelData, this.server.getPlayerList().save());
2019-06-25 13:02:13 +02:00
+ // CraftBukkit end
}
2021-06-11 07:00:00 +02:00
private void ap() {
if (this.dragonFight != null) {
- this.server.getSaveData().a(this.dragonFight.a());
+ this.serverLevelData.a(this.dragonFight.a()); // CraftBukkit
2020-07-17 00:56:56 +02:00
}
this.getChunkProvider().getWorldPersistentData().a();
2021-07-11 01:05:59 +02:00
@@ -794,15 +882,34 @@
2014-11-25 22:32:16 +01:00
2019-04-23 04:00:00 +02:00
@Override
public boolean addEntity(Entity entity) {
- return this.addEntity0(entity);
+ // CraftBukkit start
+ return this.addEntity0(entity, CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ @Override
+ public boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
+ return this.addEntity0(entity, reason);
+ // CraftBukkit end
2016-10-16 08:20:12 +02:00
}
2019-04-23 04:00:00 +02:00
public boolean addEntitySerialized(Entity entity) {
- return this.addEntity0(entity);
+ // CraftBukkit start
+ return this.addEntitySerialized(entity, CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ public boolean addEntitySerialized(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
+ return this.addEntity0(entity, reason);
+ // CraftBukkit end
2016-10-16 08:20:12 +02:00
}
2019-04-23 04:00:00 +02:00
public void addEntityTeleport(Entity entity) {
2021-06-11 07:00:00 +02:00
- this.addEntity0(entity);
+ // CraftBukkit start
+ this.addEntity0(entity, CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ public void addEntityTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
+ this.addEntity0(entity, reason);
+ // CraftBukkit end
}
public void addPlayerCommand(EntityPlayer entityplayer) {
2021-07-11 01:05:59 +02:00
@@ -830,27 +937,39 @@
2021-06-11 07:00:00 +02:00
this.a((EntityPlayer) entity, Entity.RemovalReason.DISCARDED);
}
- this.entityManager.a((EntityAccess) entityplayer);
+ this.entityManager.a(entityplayer); // CraftBukkit - decompile error
2019-04-23 04:00:00 +02:00
}
2016-02-29 22:32:46 +01:00
2019-04-23 04:00:00 +02:00
- private boolean addEntity0(Entity entity) {
+ // CraftBukkit start
+ private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
2021-06-11 07:00:00 +02:00
if (entity.isRemoved()) {
2019-04-25 04:00:00 +02:00
- WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType()));
+ // WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit
2019-04-23 04:00:00 +02:00
return false;
2016-02-29 22:32:46 +01:00
} else {
2021-06-11 07:00:00 +02:00
- return this.entityManager.a((EntityAccess) entity);
2019-04-23 04:00:00 +02:00
+ if (!CraftEventFactory.doEntityAddEventCalling(this, entity, spawnReason)) {
+ return false;
+ }
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
+
+ return this.entityManager.a(entity); // CraftBukkit - decompile error
2019-04-23 04:00:00 +02:00
}
}
2020-08-11 23:00:00 +02:00
public boolean addAllEntitiesSafely(Entity entity) {
2021-06-11 07:00:00 +02:00
- Stream stream = entity.recursiveStream().map(Entity::getUniqueID);
2020-08-11 23:00:00 +02:00
+ // CraftBukkit start
+ return this.addAllEntitiesSafely(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ public boolean addAllEntitiesSafely(Entity entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
+ Stream<UUID> stream = entity.recursiveStream().map(Entity::getUniqueID); // CraftBukkit - decompile error
PersistentEntitySectionManager persistententitysectionmanager = this.entityManager;
Objects.requireNonNull(this.entityManager);
if (stream.anyMatch(persistententitysectionmanager::a)) {
2020-08-11 23:00:00 +02:00
return false;
} else {
- this.addAllEntities(entity);
2020-11-17 03:41:47 +01:00
+ this.addAllEntities(entity, reason); // CraftBukkit
return true;
2020-08-11 23:00:00 +02:00
}
}
2021-07-11 01:05:59 +02:00
@@ -863,10 +982,32 @@
2021-06-11 07:00:00 +02:00
entityplayer.a(entity_removalreason);
2014-11-25 22:32:16 +01:00
}
2020-06-25 02:00:00 +02:00
+ // CraftBukkit start
+ public boolean strikeLightning(Entity entitylightning) {
+ return this.strikeLightning(entitylightning, LightningStrikeEvent.Cause.UNKNOWN);
2018-09-15 11:16:42 +02:00
+ }
+
2020-06-25 02:00:00 +02:00
+ public boolean strikeLightning(Entity entitylightning, LightningStrikeEvent.Cause cause) {
2021-05-09 08:33:34 +02:00
+ LightningStrikeEvent lightning = CraftEventFactory.callLightningStrikeEvent((org.bukkit.entity.LightningStrike) entitylightning.getBukkitEntity(), cause);
2014-11-25 22:32:16 +01:00
+
+ if (lightning.isCancelled()) {
2020-06-25 02:00:00 +02:00
+ return false;
2014-11-25 22:32:16 +01:00
+ }
2020-06-25 02:00:00 +02:00
+
+ return this.addEntity(entitylightning);
+ }
+ // CraftBukkit end
+
@Override
2019-04-23 04:00:00 +02:00
public void a(int i, BlockPosition blockposition, int j) {
Iterator iterator = this.server.getPlayerList().getPlayers().iterator();
+ // CraftBukkit start
+ EntityHuman entityhuman = null;
+ Entity entity = this.getEntity(i);
+ if (entity instanceof EntityHuman) entityhuman = (EntityHuman) entity;
+ // CraftBukkit end
+
while (iterator.hasNext()) {
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
2021-07-11 01:05:59 +02:00
@@ -875,6 +1016,12 @@
2019-12-10 23:00:00 +01:00
double d1 = (double) blockposition.getY() - entityplayer.locY();
double d2 = (double) blockposition.getZ() - entityplayer.locZ();
2019-04-23 04:00:00 +02:00
+ // CraftBukkit start
+ if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) {
+ continue;
+ }
+ // CraftBukkit end
+
if (d0 * d0 + d1 * d1 + d2 * d2 < 1024.0D) {
2021-06-11 07:00:00 +02:00
entityplayer.connection.sendPacket(new PacketPlayOutBlockBreakAnimation(i, blockposition, j));
2019-04-23 04:00:00 +02:00
}
2021-07-11 01:05:59 +02:00
@@ -923,7 +1070,18 @@
2021-06-11 07:00:00 +02:00
Iterator iterator = this.navigatingMobs.iterator();
2021-02-14 00:08:27 +01:00
while (iterator.hasNext()) {
2021-06-11 07:00:00 +02:00
- EntityInsentient entityinsentient = (EntityInsentient) iterator.next();
2021-02-14 00:08:27 +01:00
+ // CraftBukkit start - fix SPIGOT-6362
2021-06-11 07:00:00 +02:00
+ EntityInsentient entityinsentient;
2021-02-14 00:08:27 +01:00
+ try {
2021-06-11 07:00:00 +02:00
+ entityinsentient = (EntityInsentient) iterator.next();
2021-02-14 00:08:27 +01:00
+ } catch (java.util.ConcurrentModificationException ex) {
+ // This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register
+ // In this case we just run the update again across all the iterators as the chunk will then be loaded
+ // As this is a relative edge case it is much faster than copying navigators (on either read or write)
+ notify(blockposition, iblockdata, iblockdata1, i);
+ return;
+ }
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
NavigationAbstract navigationabstract = entityinsentient.getNavigation();
2021-02-14 00:08:27 +01:00
if (!navigationabstract.i()) {
2021-07-11 01:05:59 +02:00
@@ -946,10 +1104,20 @@
2014-11-25 22:32:16 +01:00
2019-04-23 04:00:00 +02:00
@Override
2020-06-25 02:00:00 +02:00
public Explosion createExplosion(@Nullable Entity entity, @Nullable DamageSource damagesource, @Nullable ExplosionDamageCalculator explosiondamagecalculator, double d0, double d1, double d2, float f, boolean flag, Explosion.Effect explosion_effect) {
2014-11-25 22:32:16 +01:00
+ // CraftBukkit start
2020-06-25 02:00:00 +02:00
+ Explosion explosion = super.createExplosion(entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, explosion_effect);
2014-11-25 22:32:16 +01:00
+
+ if (explosion.wasCanceled) {
+ return explosion;
+ }
2015-02-26 23:41:06 +01:00
+
2014-11-25 22:32:16 +01:00
+ /* Remove
2020-06-25 02:00:00 +02:00
Explosion explosion = new Explosion(this, entity, damagesource, explosiondamagecalculator, d0, d1, d2, f, flag, explosion_effect);
2018-07-15 02:00:00 +02:00
2014-11-25 22:32:16 +01:00
explosion.a();
explosion.a(false);
+ */
+ // CraftBukkit end - TODO: Check if explosions are still properly implemented
2019-04-23 04:00:00 +02:00
if (explosion_effect == Explosion.Effect.NONE) {
2014-11-25 22:32:16 +01:00
explosion.clearBlocks();
}
2021-07-11 01:05:59 +02:00
@@ -1023,13 +1191,20 @@
2014-11-25 22:32:16 +01:00
}
2018-07-15 02:00:00 +02:00
public <T extends ParticleParam> int a(T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6) {
2019-12-10 23:00:00 +01:00
- PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, false, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i);
2014-11-25 22:32:16 +01:00
+ // CraftBukkit - visibility api support
2018-08-26 10:26:09 +02:00
+ return sendParticles(null, t0, d0, d1, d2, i, d3, d4, d5, d6, false);
2014-11-25 22:32:16 +01:00
+ }
2015-02-26 23:41:06 +01:00
+
2018-08-26 10:26:09 +02:00
+ public <T extends ParticleParam> int sendParticles(EntityPlayer sender, T t0, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, boolean force) {
2019-12-10 23:00:00 +01:00
+ PacketPlayOutWorldParticles packetplayoutworldparticles = new PacketPlayOutWorldParticles(t0, force, d0, d1, d2, (float) d3, (float) d4, (float) d5, (float) d6, i);
2014-11-25 22:32:16 +01:00
+ // CraftBukkit end
2018-07-15 02:00:00 +02:00
int j = 0;
2014-11-25 22:32:16 +01:00
2018-07-15 02:00:00 +02:00
for (int k = 0; k < this.players.size(); ++k) {
EntityPlayer entityplayer = (EntityPlayer) this.players.get(k);
2014-12-28 15:56:18 +01:00
+ if (sender != null && !entityplayer.getBukkitEntity().canSee(sender.getBukkitEntity())) continue; // CraftBukkit
2014-11-25 22:32:16 +01:00
2018-08-26 10:26:09 +02:00
- if (this.a(entityplayer, false, d0, d1, d2, packetplayoutworldparticles)) {
+ if (this.a(entityplayer, force, d0, d1, d2, packetplayoutworldparticles)) { // CraftBukkit
2018-07-15 02:00:00 +02:00
++j;
2018-08-26 10:26:09 +02:00
}
}
2021-07-11 01:05:59 +02:00
@@ -1079,7 +1254,7 @@
2020-06-30 02:29:41 +02:00
@Nullable
public BlockPosition a(StructureGenerator<?> structuregenerator, BlockPosition blockposition, int i, boolean flag) {
- return !this.server.getSaveData().getGeneratorSettings().shouldGenerateMapFeatures() ? null : this.getChunkProvider().getChunkGenerator().findNearestMapFeature(this, structuregenerator, blockposition, i, flag);
2021-06-11 07:00:00 +02:00
+ return !this.serverLevelData.getGeneratorSettings().shouldGenerateMapFeatures() ? null : this.getChunkProvider().getChunkGenerator().findNearestMapFeature(this, structuregenerator, blockposition, i, flag); // CraftBukkit
2020-06-30 02:29:41 +02:00
}
@Nullable
2021-07-11 01:05:59 +02:00
@@ -1116,11 +1291,21 @@
2021-06-11 07:00:00 +02:00
@Nullable
2019-04-23 04:00:00 +02:00
@Override
public WorldMap a(String s) {
2021-07-06 16:00:00 +02:00
- return (WorldMap) this.getMinecraftServer().E().getWorldPersistentData().a(WorldMap::b, s);
+ return (WorldMap) this.getMinecraftServer().E().getWorldPersistentData().a((nbttagcompound) -> {
2019-04-23 04:00:00 +02:00
+ // CraftBukkit start
+ // We only get here when the data file exists, but is not a valid map
2021-06-11 07:00:00 +02:00
+ WorldMap newMap = WorldMap.b(nbttagcompound);
+ newMap.id = s;
2019-04-23 04:00:00 +02:00
+ MapInitializeEvent event = new MapInitializeEvent(newMap.mapView);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ return newMap;
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
+ }, s);
2019-04-23 04:00:00 +02:00
}
2021-06-11 07:00:00 +02:00
@Override
public void a(String s, WorldMap worldmap) {
+ worldmap.id = s; // CraftBukkit
2021-07-06 16:00:00 +02:00
this.getMinecraftServer().E().getWorldPersistentData().a(s, (PersistentBase) worldmap);
2021-03-15 23:00:00 +01:00
}
2021-07-11 01:05:59 +02:00
@@ -1432,6 +1617,11 @@
2020-06-25 02:00:00 +02:00
@Override
public void update(BlockPosition blockposition, Block block) {
if (!this.isDebugWorld()) {
+ // CraftBukkit start
+ if (populating) {
+ return;
+ }
+ // CraftBukkit end
this.applyPhysics(blockposition, block);
}
2021-07-11 01:05:59 +02:00
@@ -1451,12 +1641,12 @@
2020-06-25 02:00:00 +02:00
}
public boolean isFlatWorld() {
- return this.server.getSaveData().getGeneratorSettings().isFlatWorld();
2021-06-11 07:00:00 +02:00
+ return this.serverLevelData.getGeneratorSettings().isFlatWorld(); // CraftBukkit
2020-06-25 02:00:00 +02:00
}
@Override
public long getSeed() {
- return this.server.getSaveData().getGeneratorSettings().getSeed();
2021-06-11 07:00:00 +02:00
+ return this.serverLevelData.getGeneratorSettings().getSeed(); // CraftBukkit
2020-06-25 02:00:00 +02:00
}
@Nullable
2021-07-11 01:05:59 +02:00
@@ -1484,7 +1674,7 @@
2021-06-11 07:00:00 +02:00
private static <T> String a(Iterable<T> iterable, Function<T, String> function) {
2020-11-02 21:00:00 +01:00
try {
2021-06-11 07:00:00 +02:00
Object2IntOpenHashMap<String> object2intopenhashmap = new Object2IntOpenHashMap();
- Iterator iterator = iterable.iterator();
+ Iterator<T> iterator = iterable.iterator(); // CraftBukkit - decompile error
2020-11-02 21:00:00 +01:00
while (iterator.hasNext()) {
T t0 = iterator.next();
2021-07-11 01:05:59 +02:00
@@ -1493,7 +1683,7 @@
2021-06-11 07:00:00 +02:00
object2intopenhashmap.addTo(s, 1);
2020-11-02 21:00:00 +01:00
}
2021-06-11 07:00:00 +02:00
- return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Entry::getIntValue).reversed()).limit(5L).map((entry) -> {
+ return (String) object2intopenhashmap.object2IntEntrySet().stream().sorted(Comparator.comparing(Entry<String>::getIntValue).reversed()).limit(5L).map((entry) -> { // CraftBukkit - decompile error
String s1 = (String) entry.getKey();
return s1 + ":" + entry.getIntValue();
2021-07-11 01:05:59 +02:00
@@ -1504,17 +1694,33 @@
2020-06-25 02:00:00 +02:00
}
public static void a(WorldServer worldserver) {
+ // CraftBukkit start
+ WorldServer.a(worldserver, null);
+ }
+
+ public static void a(WorldServer worldserver, Entity entity) {
+ // CraftBukkit end
2021-06-11 07:00:00 +02:00
BlockPosition blockposition = WorldServer.END_SPAWN_POINT;
2020-06-25 02:00:00 +02:00
int i = blockposition.getX();
int j = blockposition.getY() - 2;
int k = blockposition.getZ();
+ // CraftBukkit start
+ org.bukkit.craftbukkit.util.BlockStateListPopulator blockList = new org.bukkit.craftbukkit.util.BlockStateListPopulator(worldserver);
BlockPosition.b(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((blockposition1) -> {
- worldserver.setTypeUpdate(blockposition1, Blocks.AIR.getBlockData());
+ blockList.setTypeAndData(blockposition1, Blocks.AIR.getBlockData(), 3);
});
BlockPosition.b(i - 2, j, k - 2, i + 2, j, k + 2).forEach((blockposition1) -> {
- worldserver.setTypeUpdate(blockposition1, Blocks.OBSIDIAN.getBlockData());
+ blockList.setTypeAndData(blockposition1, Blocks.OBSIDIAN.getBlockData(), 3);
});
+ org.bukkit.World bworld = worldserver.getWorld();
+ org.bukkit.event.world.PortalCreateEvent portalEvent = new org.bukkit.event.world.PortalCreateEvent((List<org.bukkit.block.BlockState>) (List) blockList.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM);
+
2021-06-11 13:33:49 +02:00
+ worldserver.getCraftServer().getPluginManager().callEvent(portalEvent);
2020-06-25 02:00:00 +02:00
+ if (!portalEvent.isCancelled()) {
+ blockList.updateList();
+ }
+ // CraftBukkit end
}
2021-06-11 07:00:00 +02:00
@Override
2021-07-11 01:05:59 +02:00
@@ -1601,6 +1807,7 @@
2021-06-11 07:00:00 +02:00
}
}
+ entity.valid = true; // CraftBukkit
}
public void a(Entity entity) {
2021-07-11 01:05:59 +02:00
@@ -1633,6 +1840,7 @@
2021-06-11 07:00:00 +02:00
gameeventlistenerregistrar.a(entity.level);
}
+ entity.valid = false; // CraftBukkit
}
}
2020-06-25 02:00:00 +02:00
}