Skip to content

Commit e97d44f

Browse files
add biome change per player
1 parent aa2c52b commit e97d44f

File tree

7 files changed

+265
-129
lines changed

7 files changed

+265
-129
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package io.papermc.paper.event.packet;
2+
3+
import org.bukkit.BiomesSnapshot;
4+
import org.bukkit.Chunk;
5+
import org.bukkit.entity.Player;
6+
import org.bukkit.event.HandlerList;
7+
import org.bukkit.event.world.ChunkEvent;
8+
import org.jetbrains.annotations.ApiStatus;
9+
import org.jetbrains.annotations.NotNull;
10+
import org.jetbrains.annotations.Nullable;
11+
12+
/**
13+
* Is called when a {@link Player} receives {@link org.bukkit.block.Biome}s
14+
* <p>
15+
* Can for example be used for replacing Biomes when the player receives the Biome list.
16+
* <p>
17+
* Should only be used for packet/clientside related stuff.
18+
* Not intended for modifying server side state.
19+
*/
20+
public class PlayerBiomesLoadEvent extends ChunkEvent {
21+
22+
private static final HandlerList HANDLER_LIST = new HandlerList();
23+
24+
private final Player player;
25+
private BiomesSnapshot biomesSnapshot;
26+
27+
@ApiStatus.Internal
28+
public PlayerBiomesLoadEvent(@NotNull final Player player, Chunk chunk) {
29+
super(chunk);
30+
this.player = player;
31+
}
32+
33+
@NotNull
34+
@Override
35+
public HandlerList getHandlers() {
36+
return HANDLER_LIST;
37+
}
38+
39+
public static @NotNull HandlerList getHandlerList() {
40+
return HANDLER_LIST;
41+
}
42+
43+
/**
44+
* Returns the player that is receiving the biomes
45+
*
46+
* @return the player
47+
*/
48+
public @NotNull Player getPlayer() {
49+
return player;
50+
}
51+
52+
/**
53+
* Returns a biomes snapshot for the given chunk, by default it won't be set.
54+
*
55+
* @return biome snapshot if one is set
56+
*/
57+
public @Nullable BiomesSnapshot getBiomeSnapshot() {
58+
return biomesSnapshot;
59+
}
60+
61+
/**
62+
* Sets the biome snapshot for the given chunk that will be sent as an override to the player
63+
*
64+
* @param biomesSnapshot the biome override
65+
*/
66+
public void setBiomeSnapshot(@Nullable final BiomesSnapshot biomesSnapshot) {
67+
this.biomesSnapshot = biomesSnapshot;
68+
}
69+
70+
/**
71+
* Returns if chunk biomes were overridden
72+
*
73+
* @return true if override was made, else false
74+
*/
75+
public boolean hasOverrides() {
76+
return biomesSnapshot != null;
77+
}
78+
}

paper-api/src/main/java/io/papermc/paper/event/packet/PlayerChunkLoadEvent.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
* Not intended for modifying server side state.
1717
*/
1818
@NullMarked
19-
public class PlayerChunkLoadEvent extends ChunkEvent {
19+
public class PlayerChunkLoadEvent extends PlayerBiomesLoadEvent {
2020

2121
private static final HandlerList HANDLER_LIST = new HandlerList();
2222

2323
private final Player player;
2424

2525
@ApiStatus.Internal
2626
public PlayerChunkLoadEvent(final Chunk chunk, final Player player) {
27-
super(chunk);
27+
super(player, chunk);
2828
this.player = player;
2929
}
3030

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.bukkit;
2+
3+
import org.bukkit.block.Biome;
4+
import org.jetbrains.annotations.NotNull;
5+
6+
/**
7+
* Represents a static, thread-safe snapshot of chunk of biomes.
8+
* <p>
9+
* Purpose is to allow clean, efficient copy of a biome data to be made, and
10+
* then handed off for processing in another thread
11+
*/
12+
public interface BiomesSnapshot {
13+
14+
/**
15+
* Gets the X-coordinate of this chunk
16+
*
17+
* @return X-coordinate
18+
*/
19+
int getX();
20+
21+
/**
22+
* Gets the Z-coordinate of this chunk
23+
*
24+
* @return Z-coordinate
25+
*/
26+
int getZ();
27+
28+
/**
29+
* Gets name of the world containing this chunk
30+
*
31+
* @return Parent World Name
32+
*/
33+
@NotNull
34+
String getWorldName();
35+
36+
/**
37+
* Get biome at given coordinates
38+
*
39+
* @param x X-coordinate (0-15)
40+
* @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
41+
* @param z Z-coordinate (0-15)
42+
* @return Biome at given coordinate
43+
*/
44+
@NotNull
45+
Biome getBiome(int x, int y, int z);
46+
47+
/**
48+
* Get biome at given coordinates
49+
*
50+
* @param x X-coordinate (0-15)
51+
* @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
52+
* @param z Z-coordinate (0-15)
53+
* @param biome the biome to set at the give coordinate
54+
*/
55+
void setBiome(int x, int y, int z, @NotNull Biome biome);
56+
57+
/**
58+
* Get raw biome temperature at given coordinates
59+
*
60+
* @param x X-coordinate (0-15)
61+
* @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
62+
* @param z Z-coordinate (0-15)
63+
* @return temperature at given coordinate
64+
*/
65+
double getRawBiomeTemperature(int x, int y, int z);
66+
67+
/**
68+
* Tests if this chunk contains the specified biome.
69+
*
70+
* @param biome biome to test
71+
* @return if the biome is contained within
72+
*/
73+
boolean contains(@NotNull Biome biome);
74+
}

paper-api/src/main/java/org/bukkit/ChunkSnapshot.java

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,7 @@
1010
* Purpose is to allow clean, efficient copy of a chunk data to be made, and
1111
* then handed off for processing in another thread (e.g. map rendering)
1212
*/
13-
public interface ChunkSnapshot {
14-
15-
/**
16-
* Gets the X-coordinate of this chunk
17-
*
18-
* @return X-coordinate
19-
*/
20-
int getX();
21-
22-
/**
23-
* Gets the Z-coordinate of this chunk
24-
*
25-
* @return Z-coordinate
26-
*/
27-
int getZ();
28-
29-
/**
30-
* Gets name of the world containing this chunk
31-
*
32-
* @return Parent World Name
33-
*/
34-
@NotNull
35-
String getWorldName();
13+
public interface ChunkSnapshot extends BiomesSnapshot {
3614

3715
/**
3816
* Get block type for block at corresponding coordinate in the chunk
@@ -110,17 +88,6 @@ public interface ChunkSnapshot {
11088
@Deprecated(since = "1.15")
11189
Biome getBiome(int x, int z);
11290

113-
/**
114-
* Get biome at given coordinates
115-
*
116-
* @param x X-coordinate (0-15)
117-
* @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
118-
* @param z Z-coordinate (0-15)
119-
* @return Biome at given coordinate
120-
*/
121-
@NotNull
122-
Biome getBiome(int x, int y, int z);
123-
12491
/**
12592
* Get raw biome temperature at given coordinates
12693
*
@@ -132,16 +99,6 @@ public interface ChunkSnapshot {
13299
@Deprecated(since = "1.15")
133100
double getRawBiomeTemperature(int x, int z);
134101

135-
/**
136-
* Get raw biome temperature at given coordinates
137-
*
138-
* @param x X-coordinate (0-15)
139-
* @param y Y-coordinate (world minHeight (inclusive) - world maxHeight (exclusive))
140-
* @param z Z-coordinate (0-15)
141-
* @return temperature at given coordinate
142-
*/
143-
double getRawBiomeTemperature(int x, int y, int z);
144-
145102
/**
146103
* Get world full time when chunk snapshot was captured
147104
*
@@ -164,12 +121,4 @@ public interface ChunkSnapshot {
164121
* @return if the block is contained within
165122
*/
166123
boolean contains(@NotNull BlockData block);
167-
168-
/**
169-
* Tests if this chunk contains the specified biome.
170-
*
171-
* @param biome biome to test
172-
* @return if the biome is contained within
173-
*/
174-
boolean contains(@NotNull Biome biome);
175124
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package org.bukkit.craftbukkit;
2+
3+
import com.google.common.base.Preconditions;
4+
import com.google.common.base.Predicates;
5+
import java.util.Objects;
6+
import java.util.function.Predicate;
7+
import net.minecraft.core.BlockPos;
8+
import net.minecraft.core.Holder;
9+
import net.minecraft.core.Registry;
10+
import net.minecraft.world.level.chunk.PalettedContainer;
11+
import net.minecraft.world.level.chunk.PalettedContainerRO;
12+
import org.bukkit.BiomesSnapshot;
13+
import org.bukkit.block.Biome;
14+
import org.bukkit.craftbukkit.block.CraftBiome;
15+
import org.checkerframework.checker.nullness.qual.NonNull;
16+
import org.jetbrains.annotations.NotNull;
17+
18+
public class CraftBiomesSnapshot implements BiomesSnapshot {
19+
20+
private final int x, z;
21+
private final String worldname;
22+
private final int minHeight, maxHeight, seaLevel;
23+
private final Registry<net.minecraft.world.level.biome.Biome> biomeRegistry;
24+
private final PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>[] biome;
25+
26+
public CraftBiomesSnapshot(final int x, final int z, final String worldname, final int minHeight, final int maxHeight, int seaLevel, final Registry<net.minecraft.world.level.biome.Biome> registry, final PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>[] biome) {
27+
this.x = x;
28+
this.z = z;
29+
this.worldname = worldname;
30+
this.minHeight = minHeight;
31+
this.maxHeight = maxHeight;
32+
this.biomeRegistry = registry;
33+
this.biome = biome;
34+
this.seaLevel = seaLevel;
35+
}
36+
37+
@Override
38+
public int getX() {
39+
return this.x;
40+
}
41+
42+
@Override
43+
public int getZ() {
44+
return this.z;
45+
}
46+
47+
@Override
48+
public String getWorldName() {
49+
return this.worldname;
50+
}
51+
52+
@Override
53+
public void setBiome(final int x, final int y, final int z, @NotNull final Biome biome) {
54+
Preconditions.checkState(this.biome != null, "ChunkSnapshot created without biome. Please call getSnapshot with includeBiome=true");
55+
Objects.requireNonNull(biome, "biome cannot be null");
56+
this.validateChunkCoordinates(x, y, z);
57+
PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>> biomeLocal = this.biome[this.getSectionIndex(y)];
58+
biomeLocal.set(x >> 2, (y & 0xF) >> 2, z >> 2, CraftBiome.bukkitToMinecraftHolder(biome));
59+
}
60+
61+
@Override
62+
public final double getRawBiomeTemperature(int x, int y, int z) {
63+
Preconditions.checkState(this.biome != null, "ChunkSnapshot created without biome. Please call getSnapshot with includeBiome=true");
64+
this.validateChunkCoordinates(x, y, z);
65+
66+
PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>> biome = this.biome[this.getSectionIndex(y)]; // SPIGOT-7188: Don't need to convert y to biome coordinate scale since it is bound to the block chunk section
67+
return biome.get(x >> 2, (y & 0xF) >> 2, z >> 2).value().getTemperature(new BlockPos((this.x << 4) | x, y, (this.z << 4) | z), seaLevel);
68+
}
69+
70+
@Override
71+
public final Biome getBiome(int x, int y, int z) {
72+
Preconditions.checkState(this.biome != null, "ChunkSnapshot created without biome. Please call getSnapshot with includeBiome=true");
73+
this.validateChunkCoordinates(x, y, z);
74+
75+
PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>> biome = this.biome[this.getSectionIndex(y)]; // SPIGOT-7188: Don't need to convert y to biome coordinate scale since it is bound to the block chunk section
76+
return CraftBiome.minecraftHolderToBukkit(biome.get(x >> 2, (y & 0xF) >> 2, z >> 2));
77+
}
78+
79+
80+
@Override
81+
public boolean contains(@NonNull Biome biome) {
82+
Preconditions.checkArgument(biome != null, "Biome cannot be null");
83+
84+
Predicate<Holder<net.minecraft.world.level.biome.Biome>> nms = Predicates.equalTo(CraftBiome.bukkitToMinecraftHolder(biome));
85+
for (PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>> palette : this.biome) {
86+
if (palette.maybeHas(nms)) {
87+
return true;
88+
}
89+
}
90+
91+
return false;
92+
}
93+
94+
public PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>[] getBiome(){
95+
return biome;
96+
}
97+
98+
protected void validateChunkCoordinates(int x, int y, int z) {
99+
CraftChunk.validateChunkCoordinates(this.minHeight, this.maxHeight, x, y, z);
100+
}
101+
102+
protected int getSectionIndex(int y) {
103+
return (y - this.minHeight) >> 4;
104+
}
105+
}

paper-server/src/main/java/org/bukkit/craftbukkit/CraftChunk.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeB
303303
byte[][] sectionEmitLights = includeLightData ? new byte[cs.length][] : null;
304304
// Paper end - Add getChunkSnapshot includeLightData parameter
305305
boolean[] sectionEmpty = new boolean[cs.length];
306-
PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
306+
PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
307307

308308
Registry<net.minecraft.world.level.biome.Biome> iregistry = this.worldServer.registryAccess().lookupOrThrow(Registries.BIOME);
309309

0 commit comments

Comments
 (0)