forked from Minestom/Minestom
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BiomeManager.java
145 lines (122 loc) · 4.59 KB
/
BiomeManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package net.minestom.server.world.biomes;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntObjectPair;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTType;
import java.util.*;
/**
* Allows servers to register custom dimensions. Also used during player joining to send the list of all existing dimensions.
* <p>
* Contains {@link Biome#PLAINS} by default but can be removed.
*/
public final class BiomeManager {
private volatile Maps maps = new Maps(new HashMap<>(), new Int2ObjectOpenHashMap<>(),
new Object2IntOpenHashMap<>());
private final Object lock = new Object();
private record Maps(Map<NamespaceID, Biome> nameToBiome, Int2ObjectMap<Biome> idToBiome,
Object2IntMap<Biome> biomeToId) {
private Maps copy() {
return new Maps(new HashMap<>(nameToBiome), new Int2ObjectOpenHashMap<>(idToBiome),
new Object2IntOpenHashMap<>(biomeToId));
}
}
public BiomeManager() {
addBiome(0, Biome.PLAINS);
}
/**
* Adds a new biome. This does NOT send the new list to players.
*
* @param biome the biome to add
*/
public void addBiome(int id, Biome biome) {
synchronized (lock) {
Maps maps = this.maps;
Maps newMaps = maps.copy();
newMaps.nameToBiome.put(biome.name(), biome);
newMaps.idToBiome.put(id, biome);
newMaps.biomeToId.put(biome, id);
this.maps = newMaps;
}
}
/**
* Adds multiple biomes to the manager. This does NOT send the new list to players.
*
* @param biomes the biomes to add, along with their identifiers.
*/
public void addBiomes(@NotNull Collection<IntObjectPair<Biome>> biomes) {
synchronized (lock) {
Maps maps = this.maps;
Maps newMaps = maps.copy();
for (IntObjectPair<Biome> pair : biomes) {
newMaps.nameToBiome.put(pair.right().name(), pair.right());
newMaps.idToBiome.put(pair.firstInt(), pair.right());
newMaps.biomeToId.put(pair.right(), pair.firstInt());
}
this.maps = newMaps;
}
}
/**
* Removes a biome. This does NOT send the new list to players.
*
* @param biome the biome to remove
*/
public void removeBiome(Biome biome) {
synchronized (lock) {
Maps maps = this.maps;
Maps newMaps = maps.copy();
int id = newMaps.biomeToId.removeInt(biome);
newMaps.nameToBiome.remove(biome.name());
newMaps.idToBiome.remove(id);
this.maps = newMaps;
}
}
/**
* Returns an immutable copy of the biomes already registered.
*
* @return an immutable copy of the biomes already registered
*/
public Collection<Biome> unmodifiableCollection() {
return Collections.unmodifiableCollection(maps.idToBiome.values());
}
/**
* Gets a biome by its id.
*
* @param id the id of the biome
* @return the {@link Biome} linked to this id
*/
public Biome getById(int id) {
return maps.idToBiome.get(id);
}
public Biome getByName(NamespaceID namespaceID) {
return this.maps.nameToBiome.get(namespaceID);
}
public int getId(NamespaceID namespaceID) {
Maps maps = this.maps;
Biome biome = maps.nameToBiome.get(namespaceID);
return maps.biomeToId.getInt(biome);
}
public int getIdOrDefault(NamespaceID namespaceID, int id) {
Maps maps = this.maps;
Biome biome = maps.nameToBiome.get(namespaceID);
return biome == null ? id : maps.biomeToId.getInt(biome);
}
public int getId(Biome biome) {
return this.maps.biomeToId.getInt(biome);
}
public NBTCompound toNBT() {
Maps maps = this.maps;
List<NBTCompound> biomeNBT = new ArrayList<>(maps.idToBiome.size());
for (Int2ObjectMap.Entry<Biome> entry : maps.idToBiome.int2ObjectEntrySet()) {
biomeNBT.add(entry.getValue().toNbt(entry.getIntKey()));
}
return NBT.Compound(Map.of(
"type", NBT.String("minecraft:worldgen/biome"),
"value", NBT.List(NBTType.TAG_Compound, biomeNBT)));
}
}