add legacy support for <= 0.0.2 worlds :/

This commit is contained in:
dags- 2020-03-10 08:35:24 +00:00
parent 3982553360
commit 49af504485
10 changed files with 137 additions and 44 deletions

View File

@ -48,6 +48,7 @@ public class Region implements Extent {
private final int chunkZ; private final int chunkZ;
private final int blockX; private final int blockX;
private final int blockZ; private final int blockZ;
private final int border;
private final Size blockSize; private final Size blockSize;
private final Size chunkSize; private final Size chunkSize;
private final GenCell[] blocks; private final GenCell[] blocks;
@ -60,6 +61,7 @@ public class Region implements Extent {
this.chunkZ = regionZ << size; this.chunkZ = regionZ << size;
this.blockX = Size.chunkToBlock(chunkX); this.blockX = Size.chunkToBlock(chunkX);
this.blockZ = Size.chunkToBlock(chunkZ); this.blockZ = Size.chunkToBlock(chunkZ);
this.border = borderChunks;
this.chunkSize = Size.chunks(size, borderChunks); this.chunkSize = Size.chunks(size, borderChunks);
this.blockSize = Size.blocks(size, borderChunks); this.blockSize = Size.blocks(size, borderChunks);
this.blocks = new GenCell[blockSize.total * blockSize.total]; this.blocks = new GenCell[blockSize.total * blockSize.total];
@ -82,6 +84,10 @@ public class Region implements Extent {
return blockZ; return blockZ;
} }
public int getOffsetChunks() {
return border;
}
public int getChunkCount() { public int getChunkCount() {
return chunks.length; return chunks.length;
} }
@ -292,8 +298,8 @@ public class Region implements Extent {
this.regionBlockX = regionChunkX << 4; this.regionBlockX = regionChunkX << 4;
this.regionBlockZ = regionChunkZ << 4; this.regionBlockZ = regionChunkZ << 4;
// the real coordinate of this chunk within the world // the real coordinate of this chunk within the world
this.chunkX = Region.this.chunkX + regionChunkX - chunkSize.border; this.chunkX = Region.this.chunkX + regionChunkX - getOffsetChunks();
this.chunkZ = Region.this.chunkZ + regionChunkZ - chunkSize.border; this.chunkZ = Region.this.chunkZ + regionChunkZ - getOffsetChunks();
// the real block coordinate of this chunk within the world // the real block coordinate of this chunk within the world
this.blockX = chunkX << 4; this.blockX = chunkX << 4;
this.blockZ = chunkZ << 4; this.blockZ = chunkZ << 4;

View File

@ -0,0 +1,6 @@
package com.terraforged.core.region;
public interface RegionFactory {
Region create(int regionX, int regionZ, int size, int borderChunks);
}

View File

@ -25,6 +25,7 @@
package com.terraforged.core.region; package com.terraforged.core.region;
import com.terraforged.core.region.legacy.LegacyRegion;
import com.terraforged.core.util.concurrent.ObjectPool; import com.terraforged.core.util.concurrent.ObjectPool;
import com.terraforged.core.util.concurrent.ThreadPool; import com.terraforged.core.util.concurrent.ThreadPool;
import com.terraforged.core.util.concurrent.batcher.Batcher; import com.terraforged.core.util.concurrent.batcher.Batcher;
@ -38,6 +39,7 @@ public class RegionGenerator implements RegionExtent {
private final int factor; private final int factor;
private final int border; private final int border;
private final RegionFactory regions;
private final ThreadPool threadPool; private final ThreadPool threadPool;
private final ObjectPool<WorldGenerator> genPool; private final ObjectPool<WorldGenerator> genPool;
@ -45,6 +47,7 @@ public class RegionGenerator implements RegionExtent {
this.factor = builder.factor; this.factor = builder.factor;
this.border = builder.border; this.border = builder.border;
this.threadPool = builder.threadPool; this.threadPool = builder.threadPool;
this.regions = builder.regionFactory;
this.genPool = new ObjectPool<>(50, builder.factory); this.genPool = new ObjectPool<>(50, builder.factory);
} }
@ -82,7 +85,7 @@ public class RegionGenerator implements RegionExtent {
public Region generateRegion(int regionX, int regionZ) { public Region generateRegion(int regionX, int regionZ) {
try (ObjectPool.Item<WorldGenerator> item = genPool.get()) { try (ObjectPool.Item<WorldGenerator> item = genPool.get()) {
WorldGenerator generator = item.getValue(); WorldGenerator generator = item.getValue();
Region region = new Region(regionX, regionZ, factor, border); Region region = regions.create(regionX, regionZ, factor, border);
try (Batcher batcher = threadPool.batcher(region.getChunkCount())) { try (Batcher batcher = threadPool.batcher(region.getChunkCount())) {
region.generate(generator.getHeightmap(), batcher); region.generate(generator.getHeightmap(), batcher);
} }
@ -99,7 +102,7 @@ public class RegionGenerator implements RegionExtent {
public Region generateRegion(float centerX, float centerZ, float zoom, boolean filter) { public Region generateRegion(float centerX, float centerZ, float zoom, boolean filter) {
try (ObjectPool.Item<WorldGenerator> item = genPool.get()) { try (ObjectPool.Item<WorldGenerator> item = genPool.get()) {
WorldGenerator generator = item.getValue(); WorldGenerator generator = item.getValue();
Region region = new Region(0, 0, factor, border); Region region = regions.create(0, 0, factor, border);
try (Batcher batcher = threadPool.batcher(region.getChunkCount())) { try (Batcher batcher = threadPool.batcher(region.getChunkCount())) {
region.generateZoom(generator.getHeightmap(), centerX, centerZ, zoom, batcher); region.generateZoom(generator.getHeightmap(), centerX, centerZ, zoom, batcher);
} }
@ -126,6 +129,7 @@ public class RegionGenerator implements RegionExtent {
private int border = 0; private int border = 0;
private ThreadPool threadPool; private ThreadPool threadPool;
private WorldGeneratorFactory factory; private WorldGeneratorFactory factory;
private RegionFactory regionFactory = Region::new;
public Builder size(int factor, int border) { public Builder size(int factor, int border) {
return factor(factor).border(border); return factor(factor).border(border);
@ -146,6 +150,18 @@ public class RegionGenerator implements RegionExtent {
return this; return this;
} }
public Builder regions(RegionFactory factory) {
this.regionFactory = factory;
return this;
}
public Builder legacy(boolean legacy) {
if (legacy) {
return regions(LegacyRegion::new);
}
return this;
}
public Builder factory(WorldGeneratorFactory factory) { public Builder factory(WorldGeneratorFactory factory) {
this.factory = factory; this.factory = factory;
return this; return this;

View File

@ -0,0 +1,26 @@
package com.terraforged.core.region.legacy;
import com.terraforged.core.region.Region;
/**
* This is here to provide compatibility for versions 0.0.2 and below which contained a
* bug where Regions generated with an x,z offset equal to the size of the chunk border
* around the region (x16) ie 32 blocks
*/
public class LegacyRegion extends Region {
public LegacyRegion(int regionX, int regionZ, int size, int borderChunks) {
super(regionX, regionZ, size, borderChunks);
}
/**
* This is used when calculating the 'real world' chunk position of the chunk-view
* and subsequently the 'real world' block start position. In versions 0.0.2 and
* below, no offset was being deducted, so return 0 here to maintain that broken
* behaviour... RIP :/
*/
@Override
public int getOffsetChunks() {
return 0;
}
}

View File

@ -30,6 +30,7 @@ import com.terraforged.core.util.concurrent.ThreadPool;
import com.terraforged.feature.FeatureManager; import com.terraforged.feature.FeatureManager;
import com.terraforged.mod.data.DataGen; import com.terraforged.mod.data.DataGen;
import com.terraforged.mod.feature.tree.SaplingManager; import com.terraforged.mod.feature.tree.SaplingManager;
import com.terraforged.mod.settings.SettingsHelper;
import com.terraforged.mod.util.Environment; import com.terraforged.mod.util.Environment;
import net.minecraft.world.gen.feature.Feature; import net.minecraft.world.gen.feature.Feature;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
@ -67,7 +68,7 @@ public class TerraForgedMod {
@SubscribeEvent @SubscribeEvent
public static void server(FMLDedicatedServerSetupEvent event) { public static void server(FMLDedicatedServerSetupEvent event) {
Log.info("Setting dedicated server"); Log.info("Setting dedicated server");
TerraWorld.setDedicatedServer(); SettingsHelper.setDedicatedServer();
} }
@SubscribeEvent @SubscribeEvent

View File

@ -25,7 +25,6 @@
package com.terraforged.mod; package com.terraforged.mod;
import com.google.gson.Gson;
import com.terraforged.core.world.terrain.Terrains; import com.terraforged.core.world.terrain.Terrains;
import com.terraforged.mod.biome.provider.BiomeProvider; import com.terraforged.mod.biome.provider.BiomeProvider;
import com.terraforged.mod.chunk.ChunkGeneratorFactory; import com.terraforged.mod.chunk.ChunkGeneratorFactory;
@ -34,11 +33,11 @@ import com.terraforged.mod.chunk.TerraContext;
import com.terraforged.mod.chunk.TerraGenSettings; import com.terraforged.mod.chunk.TerraGenSettings;
import com.terraforged.mod.chunk.test.TestChunkGenerator; import com.terraforged.mod.chunk.test.TestChunkGenerator;
import com.terraforged.mod.gui.SettingsScreen; import com.terraforged.mod.gui.SettingsScreen;
import com.terraforged.mod.settings.SettingsHelper;
import com.terraforged.mod.settings.TerraSettings; import com.terraforged.mod.settings.TerraSettings;
import com.terraforged.mod.util.nbt.NBTHelper; import com.terraforged.mod.util.nbt.NBTHelper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.CreateWorldScreen; import net.minecraft.client.gui.screen.CreateWorldScreen;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldType; import net.minecraft.world.WorldType;
@ -49,23 +48,16 @@ import net.minecraft.world.gen.OverworldGenSettings;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
public class TerraWorld extends WorldType { public class TerraWorld extends WorldType {
public static final int VERSION = 1;
public static final String SETTINGS_FILE_NAME = "terraforged-generator.json";
private static final Set<WorldType> types = new HashSet<>(); private static final Set<WorldType> types = new HashSet<>();
public static final TerraWorld TERRA = new TerraWorld("terraforged", TerraChunkGenerator::new); public static final TerraWorld TERRA = new TerraWorld("terraforged", TerraChunkGenerator::new);
public static final TerraWorld TEST = new TerraWorld("terratest", TestChunkGenerator::new); public static final TerraWorld TEST = new TerraWorld("terratest", TestChunkGenerator::new);
private static boolean dedicated = false;
private final ChunkGeneratorFactory<?> factory; private final ChunkGeneratorFactory<?> factory;
public TerraWorld(String name, ChunkGeneratorFactory<?> factory) { public TerraWorld(String name, ChunkGeneratorFactory<?> factory) {
@ -93,13 +85,13 @@ public class TerraWorld extends WorldType {
Log.debug("Creating {} generator", world.getDimension().getType()); Log.debug("Creating {} generator", world.getDimension().getType());
TerraSettings settings = getSettings(world); int version = SettingsHelper.getVersion(world.getWorldInfo());
settings.generator.seed = world.getSeed(); TerraSettings settings = SettingsHelper.getSettings(world);
SettingsHelper.syncSettings(world.getWorldInfo(), settings, version);
Terrains terrains = Terrains.create(settings); Terrains terrains = Terrains.create(settings);
OverworldGenSettings genSettings = new TerraGenSettings(settings.structures); OverworldGenSettings genSettings = new TerraGenSettings(settings.structures);
OverworldBiomeProviderSettings biomeSettings = new OverworldBiomeProviderSettings(world.getWorldInfo()); OverworldBiomeProviderSettings biomeSettings = new OverworldBiomeProviderSettings(world.getWorldInfo());
biomeSettings.setGeneratorSettings(genSettings); biomeSettings.setGeneratorSettings(genSettings);
world.getWorldInfo().setGeneratorOptions(NBTHelper.serializeCompact(settings)); world.getWorldInfo().setGeneratorOptions(NBTHelper.serializeCompact(settings));
@ -120,34 +112,10 @@ public class TerraWorld extends WorldType {
return factory; return factory;
} }
private static TerraSettings getSettings(IWorld world) {
if (dedicated) {
try (Reader reader = new BufferedReader(new FileReader(new File("config", SETTINGS_FILE_NAME)))) {
Log.info("Loading generator settings from json");
return new Gson().fromJson(reader, TerraSettings.class);
} catch (Throwable ignored) {
return getSettings(world.getWorldInfo().getGeneratorOptions());
}
}
return getSettings(world.getWorldInfo().getGeneratorOptions());
}
private static TerraSettings getSettings(CompoundNBT root) {
TerraSettings settings = new TerraSettings();
if (!root.isEmpty()) {
NBTHelper.deserialize(root, settings);
}
return settings;
}
public static void init() { public static void init() {
Log.info("Registered world type(s)"); Log.info("Registered world type(s)");
} }
public static void setDedicatedServer() {
dedicated = true;
}
public static boolean isTerraWorld(IWorld world) { public static boolean isTerraWorld(IWorld world) {
if (world instanceof World) { if (world instanceof World) {
return types.contains(((World) world).getWorldType()); return types.contains(((World) world).getWorldType());

View File

@ -368,6 +368,7 @@ public class TerraChunkGenerator extends ObfHelperChunkGenerator<GenerationSetti
protected RegionCache createRegionCache(TerraContext context) { protected RegionCache createRegionCache(TerraContext context) {
return RegionGenerator.builder() return RegionGenerator.builder()
.legacy(context.terraSettings.version == 0)
.pool(ThreadPool.getFixed()) .pool(ThreadPool.getFixed())
.factory(context.factory) .factory(context.factory)
.size(3, 2) .size(3, 2)

View File

@ -28,7 +28,6 @@ package com.terraforged.mod.gui;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.terraforged.core.settings.Settings; import com.terraforged.core.settings.Settings;
import com.terraforged.mod.TerraWorld;
import com.terraforged.mod.gui.element.TerraLabel; import com.terraforged.mod.gui.element.TerraLabel;
import com.terraforged.mod.gui.page.FeaturePage; import com.terraforged.mod.gui.page.FeaturePage;
import com.terraforged.mod.gui.page.FilterPage; import com.terraforged.mod.gui.page.FilterPage;
@ -38,6 +37,7 @@ import com.terraforged.mod.gui.page.RiverPage;
import com.terraforged.mod.gui.page.StructurePage; import com.terraforged.mod.gui.page.StructurePage;
import com.terraforged.mod.gui.page.TerrainPage; import com.terraforged.mod.gui.page.TerrainPage;
import com.terraforged.mod.gui.preview.PreviewPage; import com.terraforged.mod.gui.preview.PreviewPage;
import com.terraforged.mod.settings.SettingsHelper;
import com.terraforged.mod.settings.TerraSettings; import com.terraforged.mod.settings.TerraSettings;
import com.terraforged.mod.util.nbt.NBTHelper; import com.terraforged.mod.util.nbt.NBTHelper;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -246,7 +246,7 @@ public class SettingsScreen extends OverlayScreen {
CompoundNBT tag = NBTHelper.serializeCompact(settings); CompoundNBT tag = NBTHelper.serializeCompact(settings);
JsonElement json = NBTHelper.toJson(tag); JsonElement json = NBTHelper.toJson(tag);
File config = new File(Minecraft.getInstance().gameDir, "config"); File config = new File(Minecraft.getInstance().gameDir, "config");
File file = new File(config, TerraWorld.SETTINGS_FILE_NAME); File file = new File(config, SettingsHelper.SETTINGS_FILE_NAME);
try (Writer writer = new BufferedWriter(new FileWriter(file))) { try (Writer writer = new BufferedWriter(new FileWriter(file))) {
new GsonBuilder().setPrettyPrinting().create().toJson(json, writer); new GsonBuilder().setPrettyPrinting().create().toJson(json, writer);
Util.getOSType().openURI(file.getParentFile().toURI()); Util.getOSType().openURI(file.getParentFile().toURI());

View File

@ -0,0 +1,67 @@
package com.terraforged.mod.settings;
import com.google.gson.Gson;
import com.terraforged.mod.Log;
import com.terraforged.mod.TerraWorld;
import com.terraforged.mod.util.nbt.NBTHelper;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.world.IWorld;
import net.minecraft.world.storage.WorldInfo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
public class SettingsHelper {
public static final String SETTINGS_FILE_NAME = "terraforged-generator.json";
private static boolean dedicated = false;
public static void setDedicatedServer() {
dedicated = true;
}
public static int getVersion(WorldInfo info) {
if (info.getGeneratorOptions().isEmpty()) {
// if options have not been set then the world has been created
// during the current runtime .: is not legacy
return TerraWorld.VERSION;
}
CompoundNBT version = info.getGeneratorOptions().getCompound("version");
if (version.isEmpty()) {
// version tag is absent in legacy worlds .: is legacy
return 0;
}
return version.getInt("value");
}
public static TerraSettings getSettings(IWorld world) {
if (dedicated) {
try (Reader reader = new BufferedReader(new FileReader(new File("config", SETTINGS_FILE_NAME)))) {
Log.info("Loading generator settings from json");
return new Gson().fromJson(reader, TerraSettings.class);
} catch (Throwable ignored) {
return getSettings(world.getWorldInfo());
}
}
return getSettings(world.getWorldInfo());
}
public static TerraSettings getSettings(WorldInfo info) {
TerraSettings settings = new TerraSettings();
if (!info.getGeneratorOptions().isEmpty()) {
NBTHelper.deserialize(info.getGeneratorOptions(), settings);
}
return settings;
}
public static void syncSettings(WorldInfo info, TerraSettings settings, int version) {
settings.version = version;
settings.generator.seed = info.getSeed();
CompoundNBT options = NBTHelper.serialize(settings);
info.setGeneratorOptions(options);
}
}

View File

@ -31,6 +31,8 @@ import com.terraforged.core.util.serialization.annotation.Serializable;
@Serializable @Serializable
public class TerraSettings extends Settings { public class TerraSettings extends Settings {
public int version = 1;
public FeatureSettings features = new FeatureSettings(); public FeatureSettings features = new FeatureSettings();
public StructureSettings structures = new StructureSettings(); public StructureSettings structures = new StructureSettings();