1
1
package me .hsgamer .morefoworld ;
2
2
3
3
import com .google .common .collect .ImmutableList ;
4
- import com .mojang .datafixers .util .Pair ;
5
- import com .mojang .serialization .DynamicOps ;
4
+ import com .mojang .serialization .Dynamic ;
6
5
import com .mojang .serialization .Lifecycle ;
7
6
import net .minecraft .core .registries .Registries ;
8
- import net .minecraft .nbt .NbtOps ;
9
- import net .minecraft .nbt .Tag ;
10
- import net .minecraft .resources .RegistryOps ;
7
+ import net .minecraft .nbt .NbtException ;
8
+ import net .minecraft .nbt .ReportedNbtException ;
11
9
import net .minecraft .resources .ResourceKey ;
10
+ import net .minecraft .server .MinecraftServer ;
12
11
import net .minecraft .server .WorldLoader ;
13
12
import net .minecraft .server .dedicated .DedicatedServer ;
14
13
import net .minecraft .server .dedicated .DedicatedServerProperties ;
27
26
import net .minecraft .world .level .levelgen .PhantomSpawner ;
28
27
import net .minecraft .world .level .levelgen .WorldDimensions ;
29
28
import net .minecraft .world .level .levelgen .WorldOptions ;
29
+ import net .minecraft .world .level .storage .LevelDataAndDimensions ;
30
30
import net .minecraft .world .level .storage .LevelStorageSource ;
31
31
import net .minecraft .world .level .storage .PrimaryLevelData ;
32
- import net .minecraft .world .level .storage . WorldData ;
32
+ import net .minecraft .world .level .validation . ContentValidationException ;
33
33
import org .bukkit .Bukkit ;
34
34
import org .bukkit .GameMode ;
35
35
import org .bukkit .World ;
36
36
import org .bukkit .WorldCreator ;
37
- import org .bukkit .craftbukkit .v1_20_R2 .CraftServer ;
38
- import org .bukkit .craftbukkit .v1_20_R2 .CraftWorld ;
39
- import org .bukkit .craftbukkit .v1_20_R2 .generator .CraftWorldInfo ;
37
+ import org .bukkit .craftbukkit .v1_20_R3 .CraftServer ;
38
+ import org .bukkit .craftbukkit .v1_20_R3 .CraftWorld ;
39
+ import org .bukkit .craftbukkit .v1_20_R3 .generator .CraftWorldInfo ;
40
40
import org .bukkit .generator .BiomeProvider ;
41
41
import org .bukkit .generator .ChunkGenerator ;
42
42
import org .bukkit .generator .WorldInfo ;
46
46
import java .util .List ;
47
47
import java .util .Locale ;
48
48
49
+ /**
50
+ * @see net.minecraft.server.MinecraftServer#loadWorld0(String)
51
+ * @see CraftServer#createWorld(WorldCreator)
52
+ */
49
53
public final class WorldUtil {
50
54
public static FeedbackWorld addWorld (WorldCreator creator ) {
51
55
CraftServer craftServer = (CraftServer ) Bukkit .getServer ();
@@ -54,11 +58,19 @@ public static FeedbackWorld addWorld(WorldCreator creator) {
54
58
String name = creator .name ();
55
59
56
60
String levelName = console .getProperties ().levelName ;
57
- if (name .equals (levelName )
58
- || (console .isNetherEnabled () && name .equals (levelName + "_nether" ))
59
- || (craftServer .getAllowEnd () && name .equals (levelName + "_the_end" ))
60
- ) {
61
+ ResourceKey <net .minecraft .world .level .Level > worldKey = null ;
62
+ if (name .equals (levelName )) {
61
63
return Feedback .WORLD_DEFAULT .toFeedbackWorld ();
64
+ } else if (name .equals (levelName + "_nether" )) {
65
+ if (console .isNetherEnabled ()) {
66
+ return Feedback .WORLD_DEFAULT .toFeedbackWorld ();
67
+ }
68
+ worldKey = net .minecraft .world .level .Level .NETHER ;
69
+ } else if (name .equals (levelName + "_the_end" )) {
70
+ if (craftServer .getAllowEnd ()) {
71
+ return Feedback .WORLD_DEFAULT .toFeedbackWorld ();
72
+ }
73
+ worldKey = net .minecraft .world .level .Level .END ;
62
74
}
63
75
64
76
ChunkGenerator generator = creator .generator ();
@@ -94,30 +106,67 @@ public static FeedbackWorld addWorld(WorldCreator creator) {
94
106
95
107
LevelStorageSource .LevelStorageAccess worldSession ;
96
108
try {
97
- worldSession = LevelStorageSource .createDefault (craftServer .getWorldContainer ().toPath ()).createAccess (name , actualDimension );
98
- } catch (IOException ex ) {
109
+ worldSession = LevelStorageSource .createDefault (craftServer .getWorldContainer ().toPath ()).validateAndCreateAccess (name , actualDimension );
110
+ } catch (IOException | ContentValidationException ex ) {
99
111
throw new RuntimeException (ex );
100
112
}
101
113
114
+ Dynamic <?> dynamic ;
115
+ if (worldSession .hasWorldData ()) {
116
+ net .minecraft .world .level .storage .LevelSummary worldinfo ;
117
+
118
+ try {
119
+ dynamic = worldSession .getDataTag ();
120
+ worldinfo = worldSession .getSummary (dynamic );
121
+ } catch (NbtException | ReportedNbtException | IOException ioexception ) {
122
+ LevelStorageSource .LevelDirectory convertable_b = worldSession .getLevelDirectory ();
123
+
124
+ MinecraftServer .LOGGER .warn ("Failed to load world data from {}" , convertable_b .dataFile (), ioexception );
125
+ MinecraftServer .LOGGER .info ("Attempting to use fallback" );
126
+
127
+ try {
128
+ dynamic = worldSession .getDataTagFallback ();
129
+ worldinfo = worldSession .getSummary (dynamic );
130
+ } catch (NbtException | ReportedNbtException | IOException ioexception1 ) {
131
+ MinecraftServer .LOGGER .error ("Failed to load world data from {}" , convertable_b .oldDataFile (), ioexception1 );
132
+ MinecraftServer .LOGGER .error ("Failed to load world data from {} and {}. World files may be corrupted. Shutting down." , convertable_b .dataFile (), convertable_b .oldDataFile ());
133
+ return Feedback .WORLD_FOLDER_INVALID .toFeedbackWorld ();
134
+ }
135
+
136
+ worldSession .restoreLevelDataFromOld ();
137
+ }
138
+
139
+ if (worldinfo .requiresManualConversion ()) {
140
+ MinecraftServer .LOGGER .info ("This world must be opened in an older version (like 1.6.4) to be safely converted" );
141
+ return Feedback .WORLD_FOLDER_INVALID .toFeedbackWorld ();
142
+ }
143
+
144
+ if (!worldinfo .isCompatible ()) {
145
+ MinecraftServer .LOGGER .info ("This world was created by an incompatible version." );
146
+ return Feedback .WORLD_FOLDER_INVALID .toFeedbackWorld ();
147
+ }
148
+ } else {
149
+ dynamic = null ;
150
+ }
151
+
102
152
boolean hardcore = creator .hardcore ();
103
153
104
154
PrimaryLevelData worlddata ;
105
155
WorldLoader .DataLoadContext worldloader_a = console .worldLoader ;
106
156
net .minecraft .core .Registry <LevelStem > iregistry = worldloader_a .datapackDimensions ().registryOrThrow (Registries .LEVEL_STEM );
107
- DynamicOps < Tag > dynamicops = RegistryOps . create ( NbtOps . INSTANCE , worldloader_a . datapackWorldgen ());
108
- Pair < WorldData , WorldDimensions . Complete > pair = worldSession . getDataTag ( dynamicops , worldloader_a .dataConfiguration (), iregistry , worldloader_a .datapackWorldgen (). allRegistriesLifecycle ());
157
+ if ( dynamic != null ) {
158
+ LevelDataAndDimensions leveldataanddimensions = LevelStorageSource . getLevelDataAndDimensions ( dynamic , worldloader_a .dataConfiguration (), iregistry , worldloader_a .datapackWorldgen ());
109
159
110
- if (pair != null ) {
111
- worlddata = (PrimaryLevelData ) pair .getFirst ();
112
- iregistry = pair .getSecond ().dimensions ();
160
+ worlddata = (PrimaryLevelData ) leveldataanddimensions .worldData ();
161
+ iregistry = leveldataanddimensions .dimensions ().dimensions ();
113
162
} else {
114
163
LevelSettings worldsettings ;
115
164
WorldOptions worldoptions = new WorldOptions (creator .seed (), creator .generateStructures (), false );
116
165
WorldDimensions worlddimensions ;
117
166
118
167
DedicatedServerProperties .WorldDimensionData properties = new DedicatedServerProperties .WorldDimensionData (GsonHelper .parse ((creator .generatorSettings ().isEmpty ()) ? "{}" : creator .generatorSettings ()), creator .type ().name ().toLowerCase (Locale .ROOT ));
119
168
120
- worldsettings = new LevelSettings (name , getGameType ( GameMode . SURVIVAL ), hardcore , Difficulty .EASY , false , new GameRules (), worldloader_a .dataConfiguration ());
169
+ worldsettings = new LevelSettings (name , GameType . byId ( craftServer . getDefaultGameMode (). getValue () ), hardcore , Difficulty .EASY , false , new GameRules (), worldloader_a .dataConfiguration ());
121
170
worlddimensions = properties .create (worldloader_a .datapackWorldgen ());
122
171
123
172
WorldDimensions .Complete worlddimensions_b = worlddimensions .bake (iregistry );
@@ -130,11 +179,11 @@ public static FeedbackWorld addWorld(WorldCreator creator) {
130
179
worlddata .checkName (name );
131
180
worlddata .setModdedInfo (console .getServerModName (), console .getModdedStatus ().shouldReportAsModified ());
132
181
133
- long j = BiomeManager .obfuscateSeed (creator .seed ());
182
+ long j = BiomeManager .obfuscateSeed (worlddata . worldGenOptions () .seed ());
134
183
List <CustomSpawner > list = ImmutableList .of (new PhantomSpawner (), new PatrolSpawner (), new CatSpawner (), new VillageSiege (), new WanderingTraderSpawner (worlddata ));
135
184
LevelStem worlddimension = iregistry .get (actualDimension );
136
185
137
- WorldInfo worldInfo = new CraftWorldInfo (worlddata , worldSession , creator .environment (), worlddimension .type ().value (), worlddimension .generator (), craftServer . getHandle (). getServer (). registryAccess ()); // Paper
186
+ WorldInfo worldInfo = new CraftWorldInfo (worlddata , worldSession , creator .environment (), worlddimension .type ().value (), worlddimension .generator (), console . registryAccess ());
138
187
if (biomeProvider == null && generator != null ) {
139
188
biomeProvider = generator .getDefaultBiomeProvider (worldInfo );
140
189
}
@@ -145,13 +194,15 @@ public static FeedbackWorld addWorld(WorldCreator creator) {
145
194
);
146
195
}
147
196
148
- ResourceKey <net .minecraft .world .level .Level > worldKey ;
149
- worldKey = ResourceKey .create (Registries .DIMENSION , new net .minecraft .resources .ResourceLocation (creator .key ().getNamespace ().toLowerCase (java .util .Locale .ENGLISH ), creator .key ().getKey ().toLowerCase (java .util .Locale .ENGLISH ))); // Paper
197
+ if (worldKey == null ) {
198
+ worldKey = ResourceKey .create (Registries .DIMENSION , new net .minecraft .resources .ResourceLocation (creator .key ().getNamespace ().toLowerCase (java .util .Locale .ENGLISH ), creator .key ().getKey ().toLowerCase (java .util .Locale .ENGLISH ))); // Paper
199
+ }
150
200
151
201
ServerLevel internal = new ServerLevel (console , console .executor , worldSession , worlddata , worldKey , worlddimension , console .progressListenerFactory .create (11 ),
152
202
worlddata .isDebugWorld (), j , creator .environment () == World .Environment .NORMAL ? list : ImmutableList .of (), true , null , creator .environment (), generator , biomeProvider );
153
203
154
204
console .addLevel (internal );
205
+
155
206
int loadRegionRadius = ((32 ) >> 4 );
156
207
internal .randomSpawnSelection = new ChunkPos (internal .getChunkSource ().randomState ().sampler ().findSpawnPosition ());
157
208
for (int currX = -loadRegionRadius ; currX <= loadRegionRadius ; ++currX ) {
@@ -165,7 +216,7 @@ public static FeedbackWorld addWorld(WorldCreator creator) {
165
216
166
217
internal .setSpawnSettings (true , true );
167
218
168
- internal .keepSpawnInMemory = creator .keepSpawnLoaded ().toBooleanOrElse (internal .getWorld ().getKeepSpawnInMemory ()); // Paper
219
+ internal .keepSpawnInMemory = creator .keepSpawnLoaded ().toBooleanOrElse (internal .getWorld ().getKeepSpawnInMemory ());
169
220
170
221
return Feedback .SUCCESS .toFeedbackWorld (internal .getWorld ());
171
222
}
0 commit comments