implement World#getConfig

This commit is contained in:
dfsek 2021-07-22 13:51:51 -07:00
parent 7f050b37a4
commit a56d1818c8
10 changed files with 69 additions and 12 deletions

View File

@ -8,6 +8,7 @@ import com.dfsek.terra.api.tectonic.LoaderHolder;
import com.dfsek.terra.api.tectonic.LoaderRegistrar; import com.dfsek.terra.api.tectonic.LoaderRegistrar;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.TerraWorld; import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider; import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider;
import com.dfsek.terra.api.world.generator.GenerationStageProvider; import com.dfsek.terra.api.world.generator.GenerationStageProvider;
@ -29,7 +30,7 @@ public interface ConfigPack extends LoaderRegistrar, LoaderHolder, RegistryHolde
return getOrCreateRegistry(type.getType()); return getOrCreateRegistry(type.getType());
} }
WorldConfig toWorldConfig(TerraWorld world); WorldConfig toWorldConfig(World world);
List<GenerationStageProvider> getStages(); List<GenerationStageProvider> getStages();

View File

@ -2,6 +2,7 @@ package com.dfsek.terra.api.config;
import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.world.TerraWorld; import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.generator.SamplerCache; import com.dfsek.terra.api.world.generator.SamplerCache;
import com.dfsek.terra.api.world.generator.TerraGenerationStage; import com.dfsek.terra.api.world.generator.TerraGenerationStage;
@ -12,7 +13,7 @@ import java.util.Map;
public interface WorldConfig { public interface WorldConfig {
<T> Registry<T> getRegistry(Class<T> clazz); <T> Registry<T> getRegistry(Class<T> clazz);
TerraWorld getWorld(); World getWorld();
SamplerCache getSamplerCache(); SamplerCache getSamplerCache();

View File

@ -3,6 +3,7 @@ package com.dfsek.terra.api.world;
import com.dfsek.terra.api.Handle; import com.dfsek.terra.api.Handle;
import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.vector.Vector3; import com.dfsek.terra.api.vector.Vector3;
@ -63,4 +64,6 @@ public interface World extends Handle {
} }
BiomeProvider getBiomeProvider(); BiomeProvider getBiomeProvider();
WorldConfig getConfig();
} }

View File

@ -2,6 +2,7 @@ package com.dfsek.terra.config.dummy;
import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.vector.Vector3; import com.dfsek.terra.api.vector.Vector3;
@ -66,4 +67,9 @@ public class DummyWorld implements World {
public BiomeProvider getBiomeProvider() { public BiomeProvider getBiomeProvider() {
throw new UnsupportedOperationException("Cannot get biome provider of DummyWorld"); throw new UnsupportedOperationException("Cannot get biome provider of DummyWorld");
} }
@Override
public WorldConfig getConfig() {
throw new UnsupportedOperationException("Cannot get config of DummyWorld");
}
} }

View File

@ -32,7 +32,7 @@ import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
import com.dfsek.terra.api.registry.meta.RegistryFactory; import com.dfsek.terra.api.registry.meta.RegistryFactory;
import com.dfsek.terra.api.util.generic.pair.ImmutablePair; import com.dfsek.terra.api.util.generic.pair.ImmutablePair;
import com.dfsek.terra.api.util.reflection.ReflectionUtil; import com.dfsek.terra.api.util.reflection.ReflectionUtil;
import com.dfsek.terra.api.world.TerraWorld; import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider; import com.dfsek.terra.api.world.generator.ChunkGeneratorProvider;
import com.dfsek.terra.api.world.generator.GenerationStageProvider; import com.dfsek.terra.api.world.generator.GenerationStageProvider;
@ -139,7 +139,7 @@ public class ConfigPackImpl implements ConfigPack {
main.logger().severe("Failed to load config pack from folder \"" + folder.getAbsolutePath() + "\""); main.logger().severe("Failed to load config pack from folder \"" + folder.getAbsolutePath() + "\"");
throw e; throw e;
} }
toWorldConfig(new TerraWorldImpl(new DummyWorld(), this, main)); // Build now to catch any errors immediately. toWorldConfig(new DummyWorld()); // Build now to catch any errors immediately.
} }
public ConfigPackImpl(ZipFile file, TerraPlugin main) throws ConfigException { public ConfigPackImpl(ZipFile file, TerraPlugin main) throws ConfigException {
@ -192,7 +192,7 @@ public class ConfigPackImpl implements ConfigPack {
throw e; throw e;
} }
toWorldConfig(new TerraWorldImpl(new DummyWorld(), this, main)); // Build now to catch any errors immediately. toWorldConfig(new DummyWorld()); // Build now to catch any errors immediately.
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -353,7 +353,7 @@ public class ConfigPackImpl implements ConfigPack {
@Override @Override
public WorldConfigImpl toWorldConfig(TerraWorld world) { public WorldConfigImpl toWorldConfig(World world) {
return new WorldConfigImpl(world, this, main); return new WorldConfigImpl(world, this, main);
} }

View File

@ -4,6 +4,7 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.WorldConfig; import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.world.TerraWorld; import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.generator.SamplerCache; import com.dfsek.terra.api.world.generator.SamplerCache;
import com.dfsek.terra.registry.LockedRegistryImpl; import com.dfsek.terra.registry.LockedRegistryImpl;
@ -18,12 +19,12 @@ public class WorldConfigImpl implements WorldConfig {
private final BiomeProvider provider; private final BiomeProvider provider;
private final TerraWorld world; private final World world;
private final ConfigPackImpl pack; private final ConfigPackImpl pack;
private final Map<Type, Registry<?>> registryMap = new HashMap<>(); private final Map<Type, Registry<?>> registryMap = new HashMap<>();
public WorldConfigImpl(TerraWorld world, ConfigPackImpl pack, TerraPlugin main) { public WorldConfigImpl(World world, ConfigPackImpl pack, TerraPlugin main) {
this.world = world; this.world = world;
this.pack = pack; this.pack = pack;
this.samplerCache = new SamplerCacheImpl(main, world); this.samplerCache = new SamplerCacheImpl(main, world);
@ -40,7 +41,7 @@ public class WorldConfigImpl implements WorldConfig {
} }
@Override @Override
public TerraWorld getWorld() { public World getWorld() {
return world; return world;
} }

View File

@ -3,6 +3,7 @@ package com.dfsek.terra.world;
import com.dfsek.terra.api.TerraPlugin; import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.util.MathUtil; import com.dfsek.terra.api.util.MathUtil;
import com.dfsek.terra.api.world.TerraWorld; import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.generator.Sampler; import com.dfsek.terra.api.world.generator.Sampler;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
@ -13,14 +14,14 @@ import org.jetbrains.annotations.NotNull;
public class SamplerCacheImpl implements com.dfsek.terra.api.world.generator.SamplerCache { public class SamplerCacheImpl implements com.dfsek.terra.api.world.generator.SamplerCache {
private final LoadingCache<Long, Sampler> cache; private final LoadingCache<Long, Sampler> cache;
public SamplerCacheImpl(TerraPlugin main, TerraWorld world) { public SamplerCacheImpl(TerraPlugin main, World world) {
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache()) cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache())
.build(new CacheLoader<>() { .build(new CacheLoader<>() {
@Override @Override
public Sampler load(@NotNull Long key) { public Sampler load(@NotNull Long key) {
int cx = (int) (key >> 32); int cx = (int) (key >> 32);
int cz = (int) key.longValue(); int cz = (int) key.longValue();
return world.getWorld().getTerraGenerator().createSampler(cx, cz, world.getWorld().getBiomeProvider(), world.getWorld(), world.getConfig().elevationBlend()); return world.getTerraGenerator().createSampler(cx, cz, world.getBiomeProvider(), world, world.getConfig().elevationBlend());
} }
}); });
} }

View File

@ -17,7 +17,7 @@ public class TerraWorldImpl implements TerraWorld {
public TerraWorldImpl(World w, ConfigPack c, TerraPlugin main) { public TerraWorldImpl(World w, ConfigPack c, TerraPlugin main) {
if(!w.isTerraWorld()) throw new IllegalArgumentException("World " + w + " is not a Terra World!"); if(!w.isTerraWorld()) throw new IllegalArgumentException("World " + w + " is not a Terra World!");
this.world = w; this.world = w;
config = (WorldConfigImpl) c.toWorldConfig(this); config = (WorldConfigImpl) c.toWorldConfig(w);
main.getEventManager().callEvent(new TerraWorldLoadEvent(this, c)); main.getEventManager().callEvent(new TerraWorldLoadEvent(this, c));
} }

View File

@ -2,6 +2,7 @@ package com.dfsek.terra.fabric.mixin.implementations.world;
import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.vector.Vector3; import com.dfsek.terra.api.vector.Vector3;
@ -23,16 +24,24 @@ import net.minecraft.world.ChunkRegion;
import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.TickScheduler; import net.minecraft.world.TickScheduler;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
import net.minecraft.world.chunk.ChunkStatus;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@Mixin(ChunkRegion.class) @Mixin(ChunkRegion.class)
@Implements(@Interface(iface = World.class, prefix = "terraWorld$", remap = Interface.Remap.NONE)) @Implements(@Interface(iface = World.class, prefix = "terraWorld$", remap = Interface.Remap.NONE))
public abstract class ChunkRegionMixin { public abstract class ChunkRegionMixin {
private WorldConfig config;
@Shadow @Shadow
@Final @Final
private ServerWorld world; private ServerWorld world;
@ -51,6 +60,11 @@ public abstract class ChunkRegionMixin {
return (((ChunkRegion) (Object) this).getBottomY()) + ((ChunkRegion) (Object) this).getHeight(); return (((ChunkRegion) (Object) this).getBottomY()) + ((ChunkRegion) (Object) this).getHeight();
} }
@Inject(at = @At("RETURN"), method = "<init>(Lnet/minecraft/server/world/ServerWorld;Ljava/util/List;Lnet/minecraft/world/chunk/ChunkStatus;I)V")
public void injectConstructor(ServerWorld world, List<net.minecraft.world.chunk.Chunk> list, ChunkStatus chunkStatus, int i, CallbackInfo ci) {
this.config = ((World) world).getConfig();
}
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public ChunkGenerator terraWorld$getGenerator() { public ChunkGenerator terraWorld$getGenerator() {
return (ChunkGenerator) ((ChunkRegion) (Object) this).toServerWorld().getChunkManager().getChunkGenerator(); return (ChunkGenerator) ((ChunkRegion) (Object) this).toServerWorld().getChunkManager().getChunkGenerator();
@ -114,6 +128,10 @@ public abstract class ChunkRegionMixin {
return ((TerraBiomeSource) ((ChunkRegion) (Object) this).toServerWorld().getChunkManager().getChunkGenerator().getBiomeSource()).getProvider(); return ((TerraBiomeSource) ((ChunkRegion) (Object) this).toServerWorld().getChunkManager().getChunkGenerator().getBiomeSource()).getProvider();
} }
public WorldConfig terraWorld$getConfig() {
return config;
}
/** /**
* We need regions delegating to the same world * We need regions delegating to the same world
* to have the same hashcode. This * to have the same hashcode. This

View File

@ -2,6 +2,7 @@ package com.dfsek.terra.fabric.mixin.implementations.world;
import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.vector.Vector3; import com.dfsek.terra.api.vector.Vector3;
@ -15,23 +16,44 @@ import com.dfsek.terra.fabric.block.FabricBlockState;
import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper;
import com.dfsek.terra.fabric.generation.TerraBiomeSource; import com.dfsek.terra.fabric.generation.TerraBiomeSource;
import com.dfsek.terra.fabric.util.FabricUtil; import com.dfsek.terra.fabric.util.FabricUtil;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldGenerationProgressListener;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.ChunkRegion; import net.minecraft.world.ChunkRegion;
import net.minecraft.world.ServerWorldAccess; import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.Spawner;
import net.minecraft.world.level.ServerWorldProperties;
import net.minecraft.world.level.storage.LevelStorage;
import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Intrinsic;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
import java.util.concurrent.Executor;
@Mixin(ServerWorld.class) @Mixin(ServerWorld.class)
@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) @Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ServerWorldMixin { public abstract class ServerWorldMixin {
private WorldConfig config;
@Shadow @Shadow
public abstract long getSeed(); public abstract long getSeed();
@Inject(at = @At("RETURN"), method = "<init>(Lnet/minecraft/server/MinecraftServer;Ljava/util/concurrent/Executor;Lnet/minecraft/world/level/storage/LevelStorage$Session;Lnet/minecraft/world/level/ServerWorldProperties;Lnet/minecraft/util/registry/RegistryKey;Lnet/minecraft/world/dimension/DimensionType;Lnet/minecraft/server/WorldGenerationProgressListener;Lnet/minecraft/world/gen/chunk/ChunkGenerator;ZJLjava/util/List;Z)V")
public void injectConstructor(MinecraftServer server, Executor workerExecutor, LevelStorage.Session session, ServerWorldProperties properties, RegistryKey<net.minecraft.world.World> worldKey, DimensionType dimensionType, WorldGenerationProgressListener worldGenerationProgressListener, net.minecraft.world.gen.chunk.ChunkGenerator chunkGenerator, boolean debugWorld, long seed, List<Spawner> spawners, boolean shouldTickTime, CallbackInfo ci) {
if(chunkGenerator instanceof FabricChunkGeneratorWrapper) {
config = ((FabricChunkGeneratorWrapper) chunkGenerator).getPack().toWorldConfig((World) this);
}
}
public int terra$getMaxHeight() { public int terra$getMaxHeight() {
return (((ServerWorld) (Object) this).getBottomY()) + ((ServerWorld) (Object) this).getHeight(); return (((ServerWorld) (Object) this).getBottomY()) + ((ServerWorld) (Object) this).getHeight();
} }
@ -90,6 +112,10 @@ public abstract class ServerWorldMixin {
return ((TerraBiomeSource) ((ServerWorld) (Object) this).getChunkManager().getChunkGenerator().getBiomeSource()).getProvider(); return ((TerraBiomeSource) ((ServerWorld) (Object) this).getChunkManager().getChunkGenerator().getBiomeSource()).getProvider();
} }
public WorldConfig terra$getConfig() {
return config;
}
/** /**
* Overridden in the same manner as {@link ChunkRegionMixin#hashCode()} * Overridden in the same manner as {@link ChunkRegionMixin#hashCode()}
* *