mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-10 09:46:24 +00:00
implement beardification on Bukkit (closes #370)
This commit is contained in:
@@ -5,8 +5,10 @@ import ca.solostudios.strata.version.Version;
|
||||
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
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.world.biome.Biome;
|
||||
import com.dfsek.terra.bukkit.config.PreLoadCompatibilityOptions;
|
||||
import com.dfsek.terra.bukkit.config.VanillaBiomeProperties;
|
||||
|
||||
|
||||
@@ -21,6 +23,12 @@ public class BukkitAddon implements BaseAddon {
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
terraBukkitPlugin.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(this, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions())))
|
||||
.global();
|
||||
|
||||
terraBukkitPlugin.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(this, ConfigurationLoadEvent.class)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of Terra.
|
||||
*
|
||||
* Terra is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Terra is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.bukkit.config;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.ConfigTemplate;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties {
|
||||
@Value("minecraft.use-vanilla-biomes")
|
||||
@Default
|
||||
private boolean vanillaBiomes = false;
|
||||
|
||||
@Value("minecraft.beard.enable")
|
||||
@Default
|
||||
private boolean beard = true;
|
||||
|
||||
@Value("minecraft.beard.threshold")
|
||||
@Default
|
||||
private double beardThreshold = 0.5;
|
||||
|
||||
@Value("minecraft.beard.air-threshold")
|
||||
@Default
|
||||
private double airThreshold = -0.5;
|
||||
|
||||
public boolean useVanillaBiomes() {
|
||||
return vanillaBiomes;
|
||||
}
|
||||
|
||||
public boolean isBeard() {
|
||||
return beard;
|
||||
}
|
||||
|
||||
public double getBeardThreshold() {
|
||||
return beardThreshold;
|
||||
}
|
||||
|
||||
public double getAirThreshold() {
|
||||
return airThreshold;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import com.dfsek.terra.bukkit.config.PreLoadCompatibilityOptions;
|
||||
|
||||
import com.dfsek.terra.bukkit.world.BukkitWorldProperties;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.Codec;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
@@ -10,14 +14,21 @@ import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.server.level.WorldGenRegion;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeManager;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.Beardifier;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction.FunctionContext;
|
||||
import net.minecraft.world.level.levelgen.DensityFunction.SinglePointContext;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Carving;
|
||||
import net.minecraft.world.level.levelgen.Heightmap.Types;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
@@ -103,7 +114,43 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
|
||||
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender,
|
||||
@NotNull RandomState noiseConfig,
|
||||
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
|
||||
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk);
|
||||
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk)
|
||||
.thenApply(c -> {
|
||||
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
|
||||
BiomeProvider biomeProvider = pack.getBiomeProvider();
|
||||
PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class);
|
||||
if(compatibilityOptions.isBeard()) {
|
||||
beard(structureAccessor, chunk, new BukkitWorldProperties(level.getMinecraftWorld().getWorld()), biomeProvider, compatibilityOptions);
|
||||
}
|
||||
return c;
|
||||
});
|
||||
}
|
||||
|
||||
private void beard(StructureManager structureAccessor, ChunkAccess chunk, WorldProperties world, BiomeProvider biomeProvider,
|
||||
PreLoadCompatibilityOptions compatibilityOptions) {
|
||||
Beardifier structureWeightSampler = Beardifier.forStructuresInChunk(structureAccessor, chunk.getPos());
|
||||
double threshold = compatibilityOptions.getBeardThreshold();
|
||||
double airThreshold = compatibilityOptions.getAirThreshold();
|
||||
int xi = chunk.getPos().x << 4;
|
||||
int zi = chunk.getPos().z << 4;
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
int depth = 0;
|
||||
for(int y = world.getMaxHeight(); y >= world.getMinHeight(); y--) {
|
||||
double noise = structureWeightSampler.compute(new SinglePointContext(x + xi, y, z + zi));
|
||||
if(noise > threshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), (BlockState) delegate
|
||||
.getPalette(x + xi, y, z + zi, world, biomeProvider)
|
||||
.get(depth, x + xi, y, z + zi, world.getSeed()), false);
|
||||
depth++;
|
||||
} else if(noise < airThreshold) {
|
||||
chunk.setBlockState(new BlockPos(x, y, z), Blocks.AIR.defaultBlockState(), false);
|
||||
} else {
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package com.dfsek.terra.bukkit.nms.v1_19_R1;
|
||||
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.StructureManager;
|
||||
import xyz.jpenilla.reflectionremapper.ReflectionRemapper;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldSetter;
|
||||
import xyz.jpenilla.reflectionremapper.proxy.annotation.Proxies;
|
||||
|
||||
|
||||
public class Reflection {
|
||||
public static final MappedRegistryProxy MAPPED_REGISTRY;
|
||||
public static final StructureManagerProxy STRUCTURE_MANAGER;
|
||||
|
||||
static {
|
||||
ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar();
|
||||
@@ -16,6 +20,7 @@ public class Reflection {
|
||||
Reflection.class.getClassLoader());
|
||||
|
||||
MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class);
|
||||
STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,4 +29,10 @@ public class Reflection {
|
||||
@FieldSetter("frozen")
|
||||
void setFrozen(MappedRegistry<?> instance, boolean frozen);
|
||||
}
|
||||
|
||||
@Proxies(StructureManager.class)
|
||||
public interface StructureManagerProxy {
|
||||
@FieldGetter("level")
|
||||
LevelAccessor getLevel(StructureManager instance);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user