mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-05-20 16:50:28 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6146c8db06 | |||
| 4388003f35 |
@@ -55,8 +55,8 @@ object Versions {
|
||||
// }
|
||||
|
||||
object Bukkit {
|
||||
const val minecraft = "1.21.4"
|
||||
const val paperBuild = "$minecraft-R0.1-20241211.212446-17"
|
||||
const val minecraft = "1.21.3"
|
||||
const val paperBuild = "$minecraft-R0.1-20241025.163321-1"
|
||||
const val paper = paperBuild
|
||||
const val paperLib = "1.0.8"
|
||||
const val reflectionRemapper = "0.1.1"
|
||||
|
||||
+27
-12
@@ -1,6 +1,11 @@
|
||||
package com.dfsek.terra.addons.generation.structure;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.addons.generation.structure.config.BiomeStructuresTemplate;
|
||||
import com.dfsek.terra.addons.generation.structure.config.StructureGenerationStageTemplate;
|
||||
import com.dfsek.terra.addons.generation.structure.config.StructureLayerGridDescription;
|
||||
import com.dfsek.terra.addons.generation.structure.config.StructureLayerGridDescription.Template;
|
||||
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
@@ -8,11 +13,17 @@ import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent;
|
||||
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
|
||||
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
import com.dfsek.terra.api.world.biome.Biome;
|
||||
import com.dfsek.terra.api.world.chunk.generation.util.provider.GenerationStageProvider;
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
public class StructureGenerationAddon implements AddonInitializer {
|
||||
public static final TypeKey<Supplier<ObjectTemplate<GenerationStage>>> STAGE_TYPE_KEY = new TypeKey<>() {
|
||||
};
|
||||
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@@ -24,20 +35,24 @@ public class StructureGenerationAddon implements AddonInitializer {
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> event.getPack()
|
||||
.getOrCreateRegistry(GenerationStageProvider.class)
|
||||
.register(addon.key("STRUCTURE"), pack -> new StructureGenerationStage(platform)))
|
||||
.failThrough();
|
||||
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigurationLoadEvent.class)
|
||||
.then(event -> {
|
||||
if(event.is(Biome.class)) {
|
||||
event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomeStructuresTemplate()).get());
|
||||
}
|
||||
event.getPack().applyLoader(StructureLayerGridDescription.class, Template::new);
|
||||
|
||||
event.getPack()
|
||||
.getOrCreateRegistry(STAGE_TYPE_KEY)
|
||||
.register(addon.key("STRUCTURE"), StructureGenerationStageTemplate::new);
|
||||
})
|
||||
.failThrough();
|
||||
|
||||
// platform.getEventManager()
|
||||
// .getHandler(FunctionalEventHandler.class)
|
||||
// .register(addon, ConfigurationLoadEvent.class)
|
||||
// .then(event -> {
|
||||
// if(event.is(Biome.class)) {
|
||||
// event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomeStructuresTemplate()).get());
|
||||
// }
|
||||
// })
|
||||
// .failThrough();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+21
-3
@@ -1,17 +1,35 @@
|
||||
package com.dfsek.terra.addons.generation.structure;
|
||||
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.StructureLayerGrid;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.WorldChunk;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
|
||||
|
||||
|
||||
public class StructureGenerationStage implements GenerationStage {
|
||||
private final Platform platform;
|
||||
private final StructureLayerGrid lastLayer;
|
||||
|
||||
public StructureGenerationStage(Platform platform) { this.platform = platform; }
|
||||
public StructureGenerationStage(StructureLayerGrid lastLayer) {
|
||||
this.lastLayer = lastLayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(ProtoWorld world) {
|
||||
int chunkX = world.centerChunkX();
|
||||
int chunkZ = world.centerChunkZ();
|
||||
System.out.printf("Populating X%d Y%d%n", chunkX, chunkZ);
|
||||
long seed = world.getSeed();
|
||||
|
||||
Chunk writeChunk = new WorldChunk(world, chunkX, chunkZ);
|
||||
Chunk populatedChunk = lastLayer.getChunk(world, chunkX, chunkZ, seed);
|
||||
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
for (int y = world.getMinHeight(); y <= world.getMaxHeight(); ++y) {
|
||||
writeChunk.setBlock(x, y, z, populatedChunk.getBlock(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.dfsek.terra.addons.generation.structure.config;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.addons.generation.structure.StructureGenerationStage;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.StructureLayerGrid;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.StructureLayerGridImpl;
|
||||
import com.dfsek.terra.addons.generation.structure.impl.WorldStructureLayerGrid;
|
||||
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class StructureGenerationStageTemplate implements ObjectTemplate<GenerationStage> {
|
||||
@Value("layers")
|
||||
@Default
|
||||
List<StructureLayerGridDescription> layers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public GenerationStage get() {
|
||||
StructureLayerGrid layer = new WorldStructureLayerGrid();
|
||||
for (StructureLayerGridDescription description : layers) {
|
||||
layer = new StructureLayerGridImpl(layer, description.size(), description.padding(), description.structures(), description.distribution());
|
||||
}
|
||||
return new StructureGenerationStage(layer);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.addons.generation.structure.config;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
|
||||
|
||||
public record StructureLayerGridDescription(int padding, int size, ProbabilityCollection<Structure> structures, NoiseSampler distribution) {
|
||||
public static class Template implements ObjectTemplate<StructureLayerGridDescription> {
|
||||
|
||||
@Value("padding")
|
||||
private int padding;
|
||||
|
||||
@Value("size")
|
||||
private int size;
|
||||
|
||||
@Value("structures.structures")
|
||||
private ProbabilityCollection<Structure> structures;
|
||||
|
||||
@Value("structures.distribution")
|
||||
private NoiseSampler distribution;
|
||||
|
||||
@Override
|
||||
public StructureLayerGridDescription get() {
|
||||
return new StructureLayerGridDescription(padding, size, structures, distribution);
|
||||
}
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class CopyOnWriteDelegatedChunk implements Chunk {
|
||||
|
||||
private Chunk delegate;
|
||||
private boolean writeOccurred;
|
||||
|
||||
public CopyOnWriteDelegatedChunk(Chunk delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
if (!writeOccurred) {
|
||||
writeOccurred = true;
|
||||
delegate = new OverlayChunk(delegate);
|
||||
}
|
||||
// TODO - Tiered caching
|
||||
// First sparse impl using hashmap, if number of set blocks exceeds certain threshold,
|
||||
// then swap delegate to vertically segmented chunk using BlockState[vertChunk][x][z][y]
|
||||
delegate.setBlock(x, y, z, data, physics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return delegate.getBlock(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return delegate.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate.getHandle();
|
||||
}
|
||||
|
||||
public static class OverlayChunk implements Chunk {
|
||||
|
||||
private final Chunk delegate;
|
||||
private final int worldMinHeight;
|
||||
private final BlockState[][][] blocks;
|
||||
|
||||
public OverlayChunk(Chunk delegate) {
|
||||
this.delegate = delegate;
|
||||
ServerWorld world = delegate.getWorld();
|
||||
this.worldMinHeight = world.getMinHeight();
|
||||
this.blocks = new BlockState[16][16][world.getMaxHeight() - worldMinHeight];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
blocks[x][z][y - worldMinHeight] = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
BlockState state = blocks[x][z][y - worldMinHeight];
|
||||
if (state == null) return delegate.getBlock(x, y, z);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return delegate.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return delegate.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return delegate.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return delegate.getHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.entity.Entity;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.util.Rotation;
|
||||
import com.dfsek.terra.api.util.cache.SeededVector2Key;
|
||||
import com.dfsek.terra.api.util.vector.Vector3Int;
|
||||
import com.dfsek.terra.api.world.WritableWorld;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a section of the world that contains at most a single structure within the structure layer
|
||||
*/
|
||||
public class StructureCell {
|
||||
|
||||
private final Chunk[][] chunks;
|
||||
private final int size;
|
||||
private final int chunkOriginX;
|
||||
|
||||
private final int chunkOriginZ;
|
||||
|
||||
public StructureCell(StructureLayerGridImpl layer, ProtoWorld world, SeededVector2Key gridPos) {
|
||||
System.out.println("Generating structure cell");
|
||||
this.size = layer.getGridSizeChunks();
|
||||
|
||||
this.chunkOriginX = gridPos.x * size;
|
||||
this.chunkOriginZ = gridPos.z * size;
|
||||
|
||||
this.chunks = new Chunk[size][size];
|
||||
|
||||
for (int x = 0; x < size; ++x) {
|
||||
for (int z = 0; z < size; ++z) {
|
||||
int chunkX = chunkOriginX + x;
|
||||
int chunkZ = chunkOriginZ + z;
|
||||
chunks[x][z] = new CopyOnWriteDelegatedChunk(layer.getPrevious().getChunk(world, chunkX, chunkZ, gridPos.seed));
|
||||
}
|
||||
}
|
||||
int minCoord = (chunkOriginX + layer.getPadding()) * 16;
|
||||
int maxCoord = (chunkOriginZ + layer.getGridSizeChunks() - layer.getPadding()) * 16;
|
||||
// TODO - Make these random within the range
|
||||
int structureX = (minCoord + maxCoord) / 2;
|
||||
int structureZ = (minCoord + maxCoord) / 2;
|
||||
int structureY = (world.getMinHeight() + world.getMaxHeight()) / 2;
|
||||
Vector3Int structureOrigin = Vector3Int.of(structureX, structureY, structureZ);
|
||||
|
||||
Structure structure = layer.getStructures().get(layer.getDistribution(), structureOrigin, gridPos.seed);
|
||||
|
||||
WorldView worldView = new WorldView(world);
|
||||
structure.generate(structureOrigin, worldView, null /* TODO */, Rotation.NONE /* TODO */);
|
||||
}
|
||||
|
||||
public Chunk getChunk(int chunkX, int chunkZ) {
|
||||
return getChunkLocal(chunkX - chunkOriginX, chunkZ - chunkOriginZ);
|
||||
}
|
||||
|
||||
private Chunk getChunkLocal(int ix, int iz) {
|
||||
if (ix < 0 || ix >= size || iz < 0 || iz >= size)
|
||||
throw new IndexOutOfBoundsException("Attempted to retrieve chunk outside of structure cell bounds");
|
||||
return chunks[ix][iz];
|
||||
}
|
||||
|
||||
class WorldView implements WritableWorld {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WorldView.class);
|
||||
|
||||
private final ProtoWorld worldDelegate;
|
||||
|
||||
private WorldView(ProtoWorld world) {
|
||||
this.worldDelegate = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
|
||||
int chunkX = x >> 4;
|
||||
int chunkZ = z >> 4;
|
||||
Chunk chunk = getChunkSafe(chunkX, chunkZ);
|
||||
int xInChunk = x - chunkX << 4;
|
||||
int zInChunk = z - chunkZ << 4;
|
||||
chunk.setBlock(xInChunk, y, zInChunk, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
|
||||
return worldDelegate.spawnEntity(x, y, z, entityType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(int x, int y, int z) {
|
||||
int chunkX = x >> 4;
|
||||
int chunkZ = z >> 4;
|
||||
Chunk chunk = getChunkSafe(chunkX, chunkZ);
|
||||
int xInChunk = x - chunkX << 4;
|
||||
int zInChunk = z - chunkZ << 4;
|
||||
return chunk.getBlock(xInChunk, y, zInChunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity getBlockEntity(int x, int y, int z) {
|
||||
return worldDelegate.getBlockEntity(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getGenerator() {
|
||||
return worldDelegate.getGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider getBiomeProvider() {
|
||||
return worldDelegate.getBiomeProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigPack getPack() {
|
||||
return worldDelegate.getPack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed() {
|
||||
return worldDelegate.getSeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxHeight() {
|
||||
return worldDelegate.getMaxHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinHeight() {
|
||||
return worldDelegate.getMinHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return worldDelegate.getHandle();
|
||||
}
|
||||
|
||||
private Chunk getChunkSafe(int chunkX, int chunkZ) {
|
||||
try {
|
||||
return getChunk(chunkX, chunkZ);
|
||||
} catch(IndexOutOfBoundsException e) {
|
||||
logger.warn("Chunk accessed outside permissible structure boundaries, this may cause unexpected behaviour");
|
||||
return new WorldChunk(worldDelegate, chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
|
||||
|
||||
public interface StructureLayerGrid {
|
||||
Chunk getChunk(ProtoWorld world, int chunkX, int chunkZ, long seed);
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.util.cache.SeededVector2Key;
|
||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
|
||||
public class StructureLayerGridImpl implements StructureLayerGrid {
|
||||
|
||||
private final StructureLayerGrid previous;
|
||||
private final Cache<SeededVector2Key, StructureCell> structureCells;
|
||||
|
||||
private final int padding;
|
||||
private final int cellSize;
|
||||
|
||||
protected ProbabilityCollection<Structure> getStructures() {
|
||||
return structures;
|
||||
}
|
||||
|
||||
protected NoiseSampler getDistribution() {
|
||||
return distribution;
|
||||
}
|
||||
|
||||
private final ProbabilityCollection<Structure> structures;
|
||||
private final NoiseSampler distribution;
|
||||
|
||||
public StructureLayerGridImpl(StructureLayerGrid previous, int size, int padding, ProbabilityCollection<Structure> structures,
|
||||
NoiseSampler distribution) {
|
||||
this.previous = previous;
|
||||
this.padding = padding;
|
||||
this.structures = structures;
|
||||
this.distribution = distribution;
|
||||
this.cellSize = 1 + (size + padding) * 2;
|
||||
this.structureCells = Caffeine.newBuilder()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk(ProtoWorld world, int chunkX, int chunkZ, long seed) {
|
||||
int cellX = Math.floorMod(chunkX, cellSize);
|
||||
int cellZ = Math.floorMod(chunkZ, cellSize);
|
||||
SeededVector2Key lookupPos = new SeededVector2Key(cellX, cellZ, seed);
|
||||
StructureCell cell = structureCells.get(lookupPos, pos -> new StructureCell(this, world, pos));
|
||||
return cell.getChunk(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
protected int getGridSizeChunks() {
|
||||
return cellSize;
|
||||
}
|
||||
|
||||
protected StructureLayerGrid getPrevious() {
|
||||
return previous;
|
||||
}
|
||||
|
||||
protected int getPadding() {
|
||||
return padding;
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.world.ServerWorld;
|
||||
import com.dfsek.terra.api.world.WritableWorld;
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
/**
|
||||
* Temp class that just delegates chunk operations to the world on a block-by-block basis
|
||||
*/
|
||||
public class WorldChunk implements Chunk {
|
||||
|
||||
private final WritableWorld world;
|
||||
private final int x;
|
||||
private final int z;
|
||||
|
||||
public WorldChunk(WritableWorld world, int x, int z) {
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
|
||||
world.setBlockState(x, y, z, data, physics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getBlock(int x, int y, int z) {
|
||||
return world.getBlockState(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerWorld getWorld() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getHandle() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.dfsek.terra.addons.generation.structure.impl;
|
||||
|
||||
import com.dfsek.terra.api.world.chunk.Chunk;
|
||||
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
|
||||
|
||||
|
||||
public class WorldStructureLayerGrid implements StructureLayerGrid {
|
||||
@Override
|
||||
public Chunk getChunk(ProtoWorld world, int chunkX, int chunkZ, long seed) {
|
||||
return new WorldChunk(world, chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
@@ -54,9 +54,6 @@ public interface Initializer {
|
||||
private static Initializer constructInitializer() {
|
||||
try {
|
||||
String packageVersion = NMS;
|
||||
if (NMS.equals("v1_21_4")) {
|
||||
packageVersion = "v1_21_3";
|
||||
}
|
||||
|
||||
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + packageVersion + ".NMSInitializer");
|
||||
try {
|
||||
|
||||
+5
-50
@@ -2,10 +2,9 @@ package com.dfsek.terra.bukkit.nms.v1_21_3;
|
||||
|
||||
import com.dfsek.terra.bukkit.nms.v1_21_3.config.VanillaBiomeProperties;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.HolderSet.Named;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.core.RegistrationInfo;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
@@ -19,11 +18,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry;
|
||||
@@ -39,10 +35,8 @@ public class AwfulBukkitHacks {
|
||||
LOGGER.info("Hacking biome registry...");
|
||||
MappedRegistry<Biome> biomeRegistry = (MappedRegistry<Biome>) RegistryFetcher.biomeRegistry();
|
||||
|
||||
// Unfreeze the biome registry to allow modification
|
||||
Reflection.MAPPED_REGISTRY.setFrozen(biomeRegistry, false);
|
||||
|
||||
// Register the terra biomes to the registry
|
||||
configRegistry.forEach(pack -> pack.getRegistry(com.dfsek.terra.api.world.biome.Biome.class).forEach((key, biome) -> {
|
||||
try {
|
||||
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
|
||||
@@ -72,8 +66,6 @@ public class AwfulBukkitHacks {
|
||||
}
|
||||
}));
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen(biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
LOGGER.info("Doing tag garbage....");
|
||||
Map<TagKey<Biome>, List<Holder<Biome>>> collect = biomeRegistry
|
||||
.getTags() // streamKeysAndEntries
|
||||
@@ -100,51 +92,14 @@ public class AwfulBukkitHacks {
|
||||
() -> LOGGER.error("No such biome: {}", tb))),
|
||||
() -> LOGGER.error("No vanilla biome: {}", vb)));
|
||||
|
||||
resetTags(biomeRegistry);
|
||||
bindTags(biomeRegistry, collect);
|
||||
biomeRegistry.bindAllTagsToEmpty();
|
||||
ImmutableMap.copyOf(collect).forEach(biomeRegistry::bindTag);
|
||||
|
||||
Reflection.MAPPED_REGISTRY.setFrozen(biomeRegistry, true); // freeze registry again :)
|
||||
|
||||
} catch(SecurityException | IllegalArgumentException exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void bindTags(MappedRegistry<T> registry, Map<TagKey<T>, List<Holder<T>>> tagEntries) {
|
||||
Map<Holder.Reference<T>, List<TagKey<T>>> map = new IdentityHashMap<>();
|
||||
Reflection.MAPPED_REGISTRY.getByKey(registry).values().forEach(entry -> map.put(entry, new ArrayList<>()));
|
||||
tagEntries.forEach((tag, entries) -> {
|
||||
for (Holder<T> holder : entries) {
|
||||
// if (!holder.canSerializeIn(registry.asLookup())) {
|
||||
// throw new IllegalStateException("Can't create named set " + tag + " containing value " + holder + " from outside registry " + this);
|
||||
// }
|
||||
|
||||
if (!(holder instanceof Holder.Reference<T> reference)) {
|
||||
throw new IllegalStateException("Found direct holder " + holder + " value in tag " + tag);
|
||||
}
|
||||
|
||||
map.get(reference).add(tag);
|
||||
}
|
||||
});
|
||||
// Set<TagKey<T>> set = Sets.difference(registry.tags.keySet(), tagEntries.keySet());
|
||||
// if (!set.isEmpty()) {
|
||||
// LOGGER.warn(
|
||||
// "Not all defined tags for registry {} are present in data pack: {}",
|
||||
// registry.key(),
|
||||
// set.stream().map(tag -> tag.location().toString()).sorted().collect(Collectors.joining(", "))
|
||||
// );
|
||||
// }
|
||||
|
||||
Map<TagKey<T>, HolderSet.Named<T>> map2 = new IdentityHashMap<>(registry.getTags().collect(Collectors.toMap(
|
||||
Named::key,
|
||||
(named) -> named
|
||||
)));
|
||||
tagEntries.forEach((tag, entries) -> Reflection.HOLDER_SET.invokeBind(map2.computeIfAbsent(tag, key -> Reflection.MAPPED_REGISTRY.invokeCreateTag(registry, key)), entries));
|
||||
map.forEach(Reflection.HOLDER_REFERENCE::invokeBindTags);
|
||||
Reflection.MAPPED_REGISTRY.setAllTags(registry, Reflection.MAPPED_REGISTRY_TAG_SET.invokeFromMap(map2));
|
||||
}
|
||||
|
||||
private static void resetTags(MappedRegistry<?> registry) {
|
||||
registry.getTags().forEach(entryList -> Reflection.HOLDER_SET.invokeBind(entryList, List.of()));
|
||||
Reflection.MAPPED_REGISTRY.getByKey(registry).values().forEach(entry -> Reflection.HOLDER_REFERENCE.invokeBindTags(entry, Set.of()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-15
@@ -32,21 +32,9 @@ public class NMSBiomeInjector {
|
||||
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
|
||||
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
|
||||
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()))
|
||||
.grassColorModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(), vanilla.getSpecialEffects().getGrassColorModifier()));
|
||||
// .grassColorOverride(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColor(), vanilla.getSpecialEffects().getGrassColorOverride().orElseGet(() -> Reflection.BIOME.invokeGrassColorFromTexture(vanilla))))
|
||||
// .foliageColorOverride(Objects.requireNonNullElse(vanillaBiomeProperties.getFoliageColor(), vanilla.getFoliageColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getGrassColor() == null) {
|
||||
vanilla.getSpecialEffects().getGrassColorOverride().ifPresent(effects::grassColorOverride);
|
||||
} else {
|
||||
effects.grassColorOverride(vanillaBiomeProperties.getGrassColor());
|
||||
}
|
||||
|
||||
if(vanillaBiomeProperties.getFoliageColor() == null) {
|
||||
vanilla.getSpecialEffects().getFoliageColorOverride().ifPresent(effects::foliageColorOverride);
|
||||
} else {
|
||||
effects.foliageColorOverride(vanillaBiomeProperties.getFoliageColor());
|
||||
}
|
||||
.grassColorModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(), vanilla.getSpecialEffects().getGrassColorModifier()))
|
||||
.grassColorOverride(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColor(), vanilla.getSpecialEffects().getGrassColorOverride().orElseGet(() -> Reflection.BIOME.invokeGrassColorFromTexture(vanilla))))
|
||||
.foliageColorOverride(Objects.requireNonNullElse(vanillaBiomeProperties.getFoliageColor(), vanilla.getFoliageColor()));
|
||||
|
||||
if(vanillaBiomeProperties.getParticleConfig() == null) {
|
||||
vanilla.getSpecialEffects().getAmbientParticleSettings().ifPresent(effects::ambientParticle);
|
||||
|
||||
-37
@@ -4,9 +4,7 @@ import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Holder.Reference;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.server.level.ChunkMap;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
@@ -17,23 +15,18 @@ import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.MethodName;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Static;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final MappedRegistryTagSetProxy MAPPED_REGISTRY_TAG_SET;
|
||||
public static final StructureManagerProxy STRUCTURE_MANAGER;
|
||||
|
||||
public static final ReferenceProxy REFERENCE;
|
||||
|
||||
|
||||
public static final ChunkMapProxy CHUNKMAP;
|
||||
public static final HolderReferenceProxy HOLDER_REFERENCE;
|
||||
public static final HolderSetNamedProxy HOLDER_SET;
|
||||
public static final BiomeProxy BIOME;
|
||||
|
||||
@@ -43,11 +36,9 @@ public class Reflection {
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
MAPPED_REGISTRY_TAG_SET = reflectionProxyFactory.reflectionProxy(MappedRegistryTagSetProxy.class);
|
||||
STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class);
|
||||
REFERENCE = reflectionProxyFactory.reflectionProxy(ReferenceProxy.class);
|
||||
CHUNKMAP = reflectionProxyFactory.reflectionProxy(ChunkMapProxy.class);
|
||||
HOLDER_REFERENCE = reflectionProxyFactory.reflectionProxy(HolderReferenceProxy.class);
|
||||
HOLDER_SET = reflectionProxyFactory.reflectionProxy(HolderSetNamedProxy.class);
|
||||
BIOME = reflectionProxyFactory.reflectionProxy(BiomeProxy.class);
|
||||
}
|
||||
@@ -55,24 +46,8 @@ public class Reflection {
|
||||
|
||||
@Proxies(MappedRegistry.class)
|
||||
public interface MappedRegistryProxy {
|
||||
@FieldGetter("byKey")
|
||||
<T> Map<ResourceKey<T>, Reference<T>> getByKey(MappedRegistry<T> instance);
|
||||
|
||||
@FieldSetter("allTags")
|
||||
<T> void setAllTags(MappedRegistry<T> instance, Object obj);
|
||||
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
|
||||
@MethodName("createTag")
|
||||
<T> HolderSet.Named<T> invokeCreateTag(MappedRegistry<T> instance, TagKey<T> tag);
|
||||
}
|
||||
|
||||
@Proxies(className = "net.minecraft.core.MappedRegistry$TagSet")
|
||||
public interface MappedRegistryTagSetProxy {
|
||||
@MethodName("fromMap")
|
||||
@Static
|
||||
<T> Object invokeFromMap(Map<TagKey<T>, HolderSet.Named<T>> map);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,9 +62,6 @@ public class Reflection {
|
||||
public interface ReferenceProxy {
|
||||
@MethodName("bindValue")
|
||||
<T> void invokeBindValue(Reference<T> instance, T value);
|
||||
|
||||
@MethodName("bindTags")
|
||||
<T> void invokeBindTags(Reference<T> instance, Collection<TagKey<T>> tags);
|
||||
}
|
||||
|
||||
@Proxies(ChunkMap.class)
|
||||
@@ -101,17 +73,8 @@ public class Reflection {
|
||||
void setWorldGenContext(ChunkMap instance, WorldGenContext worldGenContext);
|
||||
}
|
||||
|
||||
@Proxies(Holder.Reference.class)
|
||||
public interface HolderReferenceProxy {
|
||||
@MethodName("bindTags")
|
||||
<T> void invokeBindTags(Holder.Reference<T> instance, Collection<TagKey<T>> tags);
|
||||
}
|
||||
|
||||
@Proxies(HolderSet.Named.class)
|
||||
public interface HolderSetNamedProxy {
|
||||
@MethodName("bind")
|
||||
<T> void invokeBind(HolderSet.Named<T> instance, List<Holder<T>> entries);
|
||||
|
||||
@MethodName("contents")
|
||||
<T> List<Holder<T>> invokeContents(HolderSet.Named<T> instance);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user