Compare commits

...

21 Commits

Author SHA1 Message Date
dfsek 952c3cf086 implement MinestomBiomeGrid 2021-04-03 18:30:03 -07:00
dfsek 468bee27ab fix buildscripts 2021-04-03 16:59:46 -07:00
dfsek c3d99eb6d9 sort of working Minestom implementation 2021-04-03 16:51:55 -07:00
dfsek 8a933609ee Merge pull request #107 from PolyhedralDev/ver/5.1.2
5.1.2 LootPopulateEvent patch
2021-04-01 15:14:14 -07:00
dfsek ba4a50e234 add getStructureScript method to LootPopulateEvent 2021-04-01 15:03:48 -07:00
dfsek f8e8ce8bc2 Bump version 2021-03-31 20:50:17 -07:00
dfsek 0013d4e682 Merge pull request #106 from PolyhedralDev/ver/5.1.2
Add LootPopulateEvent and EntitySpawnEvent
2021-03-31 20:49:44 -07:00
dfsek 9a97f1178d release modrinth to beta channel 2021-03-31 08:34:17 -07:00
dfsek e6a551d84d add getter/setter for loot table in LootPopulateEvent 2021-03-30 09:23:21 -07:00
dfsek 92921430d8 add EntitySpawnEvent 2021-03-30 00:27:16 -07:00
dfsek 20c905aae4 add LootPopulateEvent 2021-03-30 00:19:32 -07:00
dfsek ec0730ef73 test commit so version is different B) 2021-03-29 21:14:34 -07:00
dfsek e4576b3405 Add modrinth publish task 2021-03-29 21:09:36 -07:00
dfsek c5800970a8 i totally didnt forget to bump version 2021-03-29 16:39:10 -07:00
dfsek 8f88b1c156 Merge pull request #101 from PolyhedralDev/ver/5.1.1
API to add populators, Buildscript improvements
2021-03-29 16:26:59 -07:00
dfsek 1360994a67 Add options to disable default populators 2021-03-29 11:56:16 -07:00
dfsek e00b28d27e remove sysout 2021-03-29 10:07:25 -07:00
dfsek c5ff5c101d custom biome color configuration 2021-03-29 09:52:54 -07:00
dfsek b1a1001c49 clean up buildscripts 2021-03-26 08:50:58 -07:00
dfsek 77d5162e73 add API for addons to register populators 2021-03-23 11:40:22 -07:00
dfsek 2e8cd54ac2 Merge pull request #96 from PolyhedralDev/ver/5.1.0
Address several issues
2021-03-17 10:53:32 -07:00
70 changed files with 1641 additions and 215 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
import com.dfsek.terra.getGitHash
val versionObj = Version("5", "1", "0", true)
val versionObj = Version("5", "1", "2", true)
allprojects {
version = versionObj
@@ -18,4 +18,4 @@ class Version(val major: String, val minor: String, val revision: String, val pr
else //Only use git hash if it's a prerelease.
"$major.$minor.$revision-BETA+${getGitHash()}"
}
}
}
@@ -30,7 +30,7 @@ fun Project.configureCommon() {
}
fun Project.getGitHash(): String {
val stdout = java.io.ByteArrayOutputStream()
val stdout = ByteArrayOutputStream()
exec {
commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD")
standardOutput = stdout
@@ -14,13 +14,9 @@ fun Project.configureDistribution() {
apply(plugin = "java-library")
apply(plugin = "com.github.johnrengelman.shadow")
// configurations.create("shaded")
configurations {
val shaded = create("shaded")
getByName("compile").extendsFrom(shaded)
// shaded.extendsFrom(getByName("compile"))
val shadedApi = create("shadedApi")
shaded.extendsFrom(shadedApi)
getByName("api").extendsFrom(shadedApi)
@@ -29,11 +25,8 @@ fun Project.configureDistribution() {
getByName("implementation").extendsFrom(shadedImplementation)
}
// tasks.withType<JavaCompile> {
// classpath +=
// }
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
group = "terra"
doFirst {
file("${buildDir}/resources/main/packs/").deleteRecursively()
@@ -160,7 +160,6 @@ public class TerraCommandManager implements CommandManager {
if(field.isAnnotationPresent(SwitchTarget.class)) {
SwitchTarget switchTarget = field.getAnnotation(SwitchTarget.class);
if(!holder.switches.containsValue(switchTarget.value())) {
System.out.println(holder.switches);
throw new MalformedCommandException("Switch Target specifies nonexistent switch \"" + switchTarget.value() + "\"");
}
@@ -0,0 +1,20 @@
package com.dfsek.terra.api.event.events;
import com.dfsek.terra.api.util.mutable.MutableBoolean;
/**
* Abstract class containing basic {@link Cancellable} implementation.
*/
public abstract class AbstractCancellable implements Cancellable {
private final MutableBoolean cancelled = new MutableBoolean(false);
@Override
public boolean isCancelled() {
return cancelled.get();
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled.set(cancelled);
}
}
@@ -1,6 +1,5 @@
package com.dfsek.terra.api.event.events.world;
import com.dfsek.terra.api.event.events.Event;
import com.dfsek.terra.api.event.events.PackEvent;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
@@ -9,18 +8,24 @@ import com.dfsek.terra.world.TerraWorld;
/**
* Called upon initialization of a TerraWorld.
*/
public class TerraWorldLoadEvent implements Event {
public class TerraWorldLoadEvent implements PackEvent {
private final TerraWorld world;
private final ConfigPack pack;
public TerraWorldLoadEvent(TerraWorld world) {
public TerraWorldLoadEvent(TerraWorld world, ConfigPack pack) {
this.world = world;
this.pack = pack;
}
public TerraWorld getWorld() {
return world;
}
public WorldConfig getPack() {
public ConfigPack getPack() {
return pack;
}
public WorldConfig getWorldConfig() {
return world.getConfig();
}
}
@@ -0,0 +1,45 @@
package com.dfsek.terra.api.event.events.world.generation;
import com.dfsek.terra.api.event.events.PackEvent;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedEntity;
import com.dfsek.terra.config.pack.ConfigPack;
/**
* Called when an entity is spawned via {@link BufferedEntity}.
*/
public class EntitySpawnEvent implements PackEvent {
private final ConfigPack pack;
private final Entity entity;
private final Location location;
public EntitySpawnEvent(ConfigPack pack, Entity entity, Location location) {
this.pack = pack;
this.entity = entity;
this.location = location;
}
@Override
public ConfigPack getPack() {
return pack;
}
/**
* Get the entity that triggered the event.
*
* @return The entity.
*/
public Entity getEntity() {
return entity;
}
/**
* Get the location of the entity.
*
* @return Location of the entity.
*/
public Location getLocation() {
return location;
}
}
@@ -0,0 +1,80 @@
package com.dfsek.terra.api.event.events.world.generation;
import com.dfsek.terra.api.event.events.AbstractCancellable;
import com.dfsek.terra.api.event.events.Cancellable;
import com.dfsek.terra.api.event.events.PackEvent;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.state.Container;
import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication;
import com.dfsek.terra.config.pack.ConfigPack;
import org.jetbrains.annotations.NotNull;
/**
* Called when loot is populated via {@link BufferedLootApplication}.
*/
public class LootPopulateEvent extends AbstractCancellable implements PackEvent, Cancellable {
private final Block block;
private final Container container;
private LootTable table;
private final ConfigPack pack;
private final StructureScript script;
public LootPopulateEvent(Block block, Container container, LootTable table, ConfigPack pack, StructureScript script) {
this.block = block;
this.container = container;
this.table = table;
this.pack = pack;
this.script = script;
}
@Override
public ConfigPack getPack() {
return pack;
}
/**
* Get the block containing the tile entity loot is applied to.
*
* @return Block at which loot is applied.
*/
public Block getBlock() {
return block;
}
/**
* Get the {@link Container} representing the inventory.
*
* @return Inventory recieving loot.
*/
public Container getContainer() {
return container;
}
/**
* Get the loot table to be populated.
* @return Loot table.
*/
public LootTable getTable() {
return table;
}
/**
* Set the loot table to be populated.
*
* @param table New loot table.
*/
public void setTable(@NotNull LootTable table) {
this.table = table;
}
/**
* Get the script used to generate the structure.
*
* @return Structure script.
*/
public StructureScript getStructureScript() {
return script;
}
}
@@ -36,7 +36,7 @@ public class NoiseFunction2 implements NoiseFunction {
super(cacheSize);
}
public double get(NoiseSampler noise, double x, double z) {
public synchronized double get(NoiseSampler noise, double x, double z) {
double xx = x >= 0 ? x * 2 : x * -2 - 1;
double zz = z >= 0 ? z * 2 : z * -2 - 1;
double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx);
@@ -68,7 +68,7 @@ public class StructureScript {
.registerFunction("setMark", new SetMarkFunctionBuilder())
.registerFunction("getMark", new GetMarkFunctionBuilder())
.registerFunction("pull", new PullFunctionBuilder(main))
.registerFunction("loot", new LootFunctionBuilder(main, lootRegistry))
.registerFunction("loot", new LootFunctionBuilder(main, lootRegistry, this))
.registerFunction("entity", new EntityFunctionBuilder(main))
.registerFunction("getBiome", new BiomeFunctionBuilder(main))
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
@@ -3,6 +3,7 @@ package com.dfsek.terra.api.structures.script.builders;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.structures.script.functions.LootFunction;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.registry.config.LootRegistry;
@@ -12,16 +13,18 @@ import java.util.List;
public class LootFunctionBuilder implements FunctionBuilder<LootFunction> {
private final TerraPlugin main;
private final LootRegistry registry;
private final StructureScript script;
public LootFunctionBuilder(TerraPlugin main, LootRegistry registry) {
public LootFunctionBuilder(TerraPlugin main, LootRegistry registry, StructureScript script) {
this.main = main;
this.registry = registry;
this.script = script;
}
@SuppressWarnings("unchecked")
@Override
public LootFunction build(List<Returnable<?>> argumentList, Position position) {
return new LootFunction(registry, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
return new LootFunction(registry, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position, script);
}
@Override
@@ -21,9 +21,11 @@ public class EntityFunction implements Function<Void> {
private final EntityType data;
private final Returnable<Number> x, y, z;
private final Position position;
private final TerraPlugin main;
public EntityFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) throws ParseException {
this.position = position;
this.main = main;
if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition());
this.data = main.getWorldHandle().getEntity(((ConstantExpression<String>) data).getConstant());
@@ -39,7 +41,7 @@ public class EntityFunction implements Function<Void> {
RotationUtil.rotateVector(xz, arguments.getRotation());
arguments.getBuffer().addItem(new BufferedEntity(data), new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()).toLocation(arguments.getBuffer().getOrigin().getWorld()));
arguments.getBuffer().addItem(new BufferedEntity(data, main), new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null;
}
@@ -8,6 +8,7 @@ import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication;
@@ -23,8 +24,9 @@ public class LootFunction implements Function<Void> {
private final Returnable<Number> x, y, z;
private final Position position;
private final TerraPlugin main;
private final StructureScript script;
public LootFunction(LootRegistry registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) {
public LootFunction(LootRegistry registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position, StructureScript script) {
this.registry = registry;
this.position = position;
this.data = data;
@@ -32,6 +34,7 @@ public class LootFunction implements Function<Void> {
this.y = y;
this.z = z;
this.main = main;
this.script = script;
}
@Override
@@ -49,7 +52,7 @@ public class LootFunction implements Function<Void> {
return null;
}
arguments.getBuffer().addItem(new BufferedLootApplication(table, main), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
arguments.getBuffer().addItem(new BufferedLootApplication(table, main, script), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld()));
return null;
}
@@ -1,18 +1,24 @@
package com.dfsek.terra.api.structures.structure.buffer.items;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.event.events.world.generation.EntitySpawnEvent;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
public class BufferedEntity implements BufferedItem {
private final EntityType type;
private final TerraPlugin main;
public BufferedEntity(EntityType type) {
public BufferedEntity(EntityType type, TerraPlugin main) {
this.type = type;
this.main = main;
}
@Override
public void paste(Location origin) {
origin.clone().add(0.5, 0, 0.5).getWorld().spawnEntity(origin, type);
Entity entity = origin.clone().add(0.5, 0, 0.5).getWorld().spawnEntity(origin, type);
main.getEventManager().callEvent(new EntitySpawnEvent(main.getWorld(entity.getWorld()).getGenerator().getConfigPack(), entity, entity.getLocation()));
}
}
@@ -1,31 +1,42 @@
package com.dfsek.terra.api.structures.structure.buffer.items;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.event.events.world.generation.LootPopulateEvent;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.api.platform.block.state.Container;
import com.dfsek.terra.api.structures.loot.LootTable;
import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.util.FastRandom;
public class BufferedLootApplication implements BufferedItem {
private final LootTable table;
private final TerraPlugin main;
private final StructureScript structure;
public BufferedLootApplication(LootTable table, TerraPlugin main) {
public BufferedLootApplication(LootTable table, TerraPlugin main, StructureScript structure) {
this.table = table;
this.main = main;
this.structure = structure;
}
@Override
public void paste(Location origin) {
try {
BlockState data = origin.getBlock().getState();
Block block = origin.getBlock();
BlockState data = block.getState();
if(!(data instanceof Container)) {
main.logger().severe("Failed to place loot at " + origin + "; block " + data + " is not container.");
return;
}
Container container = (Container) data;
table.fillInventory(container.getInventory(), new FastRandom(origin.hashCode()));
LootPopulateEvent event = new LootPopulateEvent(block, container, table, main.getWorld(block.getLocation().getWorld()).getGenerator().getConfigPack(), structure);
main.getEventManager().callEvent(event);
if(event.isCancelled()) return;
event.getTable().fillInventory(container.getInventory(), new FastRandom(origin.hashCode()));
data.update(false);
} catch(Exception e) {
main.logger().warning("Could not apply loot at " + origin + ": " + e.getMessage());
@@ -5,6 +5,14 @@ import org.jetbrains.annotations.NotNull;
public class MutableBoolean implements MutablePrimitive<Boolean> {
private boolean value;
public MutableBoolean() {
this.value = false;
}
public MutableBoolean(boolean value) {
this.value = value;
}
@Override
public Boolean get() {
return value;
@@ -0,0 +1,7 @@
package com.dfsek.terra.api.world.generation;
/**
* Marker interface that marks a feature as "chunkified" (only modifying one chunk at a time)
*/
public interface Chunkified {
}
@@ -1,8 +0,0 @@
package com.dfsek.terra.api.world.generation;
/**
* The phase of terrain generation. Used for modifying values based on the phase of generation.
*/
public enum GenerationPhase {
BASE, POPULATE, GENERATION_POPULATE, PALETTE_APPLY, POST_GEN
}
@@ -6,10 +6,10 @@ import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkData;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Random;
public interface TerraChunkGenerator {
@@ -32,4 +32,6 @@ public interface TerraChunkGenerator {
TerraPlugin getMain();
Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth);
List<TerraBlockPopulator> getPopulators();
}
@@ -63,8 +63,6 @@ public class StructureLoadCommand implements CommandTemplate {
@Override
public void execute(CommandSender sender) {
System.out.println(rotation);
Player player = (Player) sender;
long t = System.nanoTime();
@@ -4,7 +4,10 @@ import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.util.collections.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.config.templates.BiomeTemplate;
public interface BiomeBuilder extends SeededBuilder<TerraBiome> {
ProbabilityCollection<Biome> getVanillaBiomes();
BiomeTemplate getTemplate();
}
@@ -66,4 +66,9 @@ public class UserDefinedBiomeBuilder implements BiomeBuilder {
public ProbabilityCollection<Biome> getVanillaBiomes() {
return template.getVanilla();
}
@Override
public BiomeTemplate getTemplate() {
return template;
}
}
@@ -65,7 +65,6 @@ public class ExpressionFunctionTemplate extends SamplerTemplate<ExpressionFuncti
Map<String, Function> noiseFunctionMap = new HashMap<>();
for(Map.Entry<String, FunctionTemplate> entry : expressions.entrySet()) {
System.out.println(entry);
noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), new Parser(), new Scope()));
}
@@ -73,6 +73,46 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Default
private String version = "0.1.0";
@Value("disable.carvers")
@Default
private boolean disableCarvers = false;
@Value("disable.structures")
@Default
private boolean disableStructures = false;
@Value("disable.ores")
@Default
private boolean disableOres = false;
@Value("disable.trees")
@Default
private boolean disableTrees = false;
@Value("disable.flora")
@Default
private boolean disableFlora = false;
public boolean disableCarvers() {
return disableCarvers;
}
public boolean disableFlora() {
return disableFlora;
}
public boolean disableOres() {
return disableOres;
}
public boolean disableStructures() {
return disableStructures;
}
public boolean disableTrees() {
return disableTrees;
}
public LinkedHashMap<String, FunctionTemplate> getFunctions() {
return functions;
}
@@ -190,10 +190,19 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Default
private Map<UserDefinedCarver, Integer> carvers = new HashMap<>();
@Value("colors")
@Abstractable
@Default
private Map<String, Integer> colors = new HashMap<>(); // Plain ol' map, so platforms can decide what to do with colors (if anything).
public Set<String> getTags() {
return tags;
}
public Map<String, Integer> getColors() {
return colors;
}
public Map<UserDefinedCarver, Integer> getCarvers() {
return carvers;
}
@@ -33,7 +33,7 @@ public class TerraWorld {
this.provider = config.getProvider();
profiler = new WorldProfiler(w);
air = main.getWorldHandle().createBlockData("minecraft:air");
main.getEventManager().callEvent(new TerraWorldLoadEvent(this));
main.getEventManager().callEvent(new TerraWorldLoadEvent(this, c));
safe = true;
}
@@ -10,6 +10,7 @@ import com.dfsek.terra.api.util.world.PaletteUtil;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.config.pack.ConfigPack;
@@ -21,9 +22,15 @@ import com.dfsek.terra.world.carving.NoiseCarver;
import com.dfsek.terra.world.generation.math.SamplerCache;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.dfsek.terra.world.generation.math.samplers.Sampler2D;
import com.dfsek.terra.world.population.CavePopulator;
import com.dfsek.terra.world.population.OrePopulator;
import com.dfsek.terra.world.population.StructurePopulator;
import com.dfsek.terra.world.population.TreePopulator;
import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class DefaultChunkGenerator2D implements TerraChunkGenerator {
@@ -31,12 +38,18 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator {
private final TerraPlugin main;
private final Carver carver;
private final List<TerraBlockPopulator> blockPopulators = new ArrayList<>();
private final SamplerCache cache;
public DefaultChunkGenerator2D(ConfigPack c, TerraPlugin main, SamplerCache cache) {
this.configPack = c;
this.main = main;
blockPopulators.add(new CavePopulator(main));
blockPopulators.add(new StructurePopulator(main));
blockPopulators.add(new OrePopulator(main));
blockPopulators.add(new TreePopulator(main));
blockPopulators.add(new TreePopulator(main));
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
this.cache = cache;
}
@@ -125,4 +138,9 @@ public class DefaultChunkGenerator2D implements TerraChunkGenerator {
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
return new Sampler2D(chunkX, chunkZ, provider, world, elevationSmooth);
}
@Override
public List<TerraBlockPopulator> getPopulators() {
return blockPopulators;
}
}
@@ -17,6 +17,7 @@ import com.dfsek.terra.api.util.world.PaletteUtil;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.palette.SinglePalette;
@@ -28,8 +29,15 @@ import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.carving.NoiseCarver;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.dfsek.terra.world.generation.math.samplers.Sampler3D;
import com.dfsek.terra.world.population.CavePopulator;
import com.dfsek.terra.world.population.FloraPopulator;
import com.dfsek.terra.world.population.OrePopulator;
import com.dfsek.terra.world.population.StructurePopulator;
import com.dfsek.terra.world.population.TreePopulator;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -38,14 +46,21 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
private final TerraPlugin main;
private final BlockType water;
private final SinglePalette<BlockData> blank;
private final List<TerraBlockPopulator> blockPopulators = new ArrayList<>();
private final Carver carver;
public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) {
this.configPack = c;
this.main = main;
blockPopulators.add(new CavePopulator(main));
blockPopulators.add(new StructurePopulator(main));
blockPopulators.add(new OrePopulator(main));
blockPopulators.add(new TreePopulator(main));
blockPopulators.add(new FloraPopulator(main));
carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main);
water = main.getWorldHandle().createBlockData("minecraft:water").getBlockType();
blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air"));
@@ -236,4 +251,9 @@ public class DefaultChunkGenerator3D implements TerraChunkGenerator {
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth);
}
@Override
public List<TerraBlockPopulator> getPopulators() {
return blockPopulators;
}
}
@@ -2,7 +2,6 @@ package com.dfsek.terra.world.generation.math;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.MathUtil;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.world.TerraWorld;
import com.dfsek.terra.world.generation.math.samplers.Sampler;
import com.google.common.cache.CacheBuilder;
@@ -11,10 +10,6 @@ import com.google.common.cache.LoadingCache;
import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class SamplerCache {
private final LoadingCache<Long, Sampler> cache;
@@ -9,6 +9,7 @@ import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.world.PopulationUtil;
import com.dfsek.terra.api.world.generation.Chunkified;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.pack.WorldConfig;
@@ -23,7 +24,7 @@ import java.util.Map;
import java.util.Random;
import java.util.Set;
public class CavePopulator implements TerraBlockPopulator {
public class CavePopulator implements TerraBlockPopulator, Chunkified {
private static final Map<BlockType, BlockData> shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time.
private final TerraPlugin main;
@@ -41,6 +42,7 @@ public class CavePopulator implements TerraBlockPopulator {
Random random = PopulationUtil.getRandom(chunk);
if(!tw.isSafe()) return;
WorldConfig config = tw.getConfig();
if(config.getTemplate().disableCarvers()) return;
for(UserDefinedCarver c : config.getCarvers()) {
CarverTemplate template = c.getConfig();
@@ -33,6 +33,8 @@ public class FloraPopulator implements TerraBlockPopulator {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("FloraTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
Map<Vector2, List<FloraLayer>> layers = new HashMap<>();
@@ -28,6 +28,8 @@ public class OrePopulator implements TerraBlockPopulator {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("OreTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(!tw.isSafe()) return;
for(int cx = -1; cx <= 1; cx++) {
for(int cz = -1; cz <= 1; cz++) {
@@ -9,6 +9,7 @@ import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.provider.BiomeProvider;
import com.dfsek.terra.api.world.generation.Chunkified;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.pack.WorldConfig;
@@ -20,7 +21,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Random;
public class StructurePopulator implements TerraBlockPopulator {
public class StructurePopulator implements TerraBlockPopulator, Chunkified {
private final TerraPlugin main;
public StructurePopulator(TerraPlugin main) {
@@ -32,6 +33,8 @@ public class StructurePopulator implements TerraBlockPopulator {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("StructureTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
int cx = (chunk.getX() << 4);
int cz = (chunk.getZ() << 4);
if(!tw.isSafe()) return;
@@ -33,6 +33,8 @@ public class TreePopulator implements TerraBlockPopulator {
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("TreeTime")) {
if(tw.getConfig().getTemplate().disableCarvers()) return;
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
Random random = PopulationUtil.getRandom(chunk);
@@ -21,6 +21,12 @@ public class FloraLayer extends PlaceableLayer<Flora> {
@Override
public void place(Chunk chunk, Vector2 coords) {
Flora item = layer.get(noise, (chunk.getX() << 4) + coords.getX(), (chunk.getZ() << 4) + coords.getZ());
item.getValidSpawnsAt(chunk, (int) coords.getX(), (int) coords.getZ(), level).forEach(block -> item.plant(block.getLocation()));
item.getValidSpawnsAt(chunk, (int) coords.getX(), (int) coords.getZ(), level).forEach(block -> {
try {
item.plant(block.getLocation());
} catch(Exception e) {
e.printStackTrace();
}
});
}
}
@@ -9,7 +9,6 @@ import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.data.Directional;
import com.dfsek.terra.api.platform.block.data.MultipleFacing;
import com.dfsek.terra.api.platform.block.data.Rotatable;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.util.GlueList;
@@ -94,7 +93,6 @@ public class TerraFlora implements Flora {
@Override
public boolean plant(Location location) {
WorldHandle handle = main.getWorldHandle();
boolean doRotation = testRotation.size() > 0;
int size = floraPalette.getSize();
@@ -39,6 +39,7 @@ import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiom
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.registry.config.BiomeRegistry;
import com.dfsek.terra.registry.config.NoiseRegistry;
import com.dfsek.terra.world.TerraWorld;
@@ -306,6 +307,11 @@ public class DistributionTest {
return null;
}
@Override
public BiomeTemplate getTemplate() {
return null;
}
@Override
public Generator getGenerator(World w) {
return null;
+142 -49
View File
@@ -15,6 +15,13 @@ configureCommon()
group = "com.dfsek.terra.bukkit"
val mcVersion = "1.16.5"
val testDir = "target/server/"
val testMem = "3G"
val paperURL = "https://papermc.io/api/v1/paper/%version%/latest/download/"
val purpurURL = "https://ci.pl3x.net/job/Purpur/lastSuccessfulBuild/artifact/final/purpurclip.jar"
repositories {
mavenCentral()
maven { url = uri("http://maven.enginehub.org/repo/") }
@@ -35,73 +42,160 @@ dependencies {
"shadedImplementation"("com.google.guava:guava:30.0-jre")
}
val testDir = "target/server/"
val aikarsFlags = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
"-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch",
"-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M",
"-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4",
"-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90",
"-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem",
"-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs",
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear")
val setupServer = tasks.create("setupServer") {
dependsOn("shadowJar")
doFirst {
// clean
file("${testDir}/").deleteRecursively()
file("${testDir}/plugins").mkdirs()
fun downloadPaperclip(url: String, dir: String) {
val clip = URL(url.replace("%version%", mcVersion))
val clipReadableByteChannel = Channels.newChannel(clip.openStream())
val clipFile = file("$testDir/$dir/paperclip.jar")
val clipOutputStream = clipFile.outputStream()
val clipFileChannel = clipOutputStream.channel
clipFileChannel.transferFrom(clipReadableByteChannel, 0, Long.MAX_VALUE)
}
// Downloading latest paper jar.
val paperUrl = URL("https://papermc.io/api/v1/paper/1.16.4/latest/download")
val paperReadableByteChannel = Channels.newChannel(paperUrl.openStream())
val paperFile = file("${testDir}/paper.jar")
val paperFileOutputStream = paperFile.outputStream()
val paperFileChannel = paperFileOutputStream.channel
paperFileChannel.transferFrom(paperReadableByteChannel, 0, Long.MAX_VALUE)
// Cloning test setup.
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
// Copying plugins
Files.move(Paths.get("WorldGenTestServer/plugins"),
Paths.get("$testDir/plugins"),
StandardCopyOption.REPLACE_EXISTING)
// Copying config
val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText()
file("${testDir}/server.properties").writeText(serverText)
val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText()
file("${testDir}/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT"))
File("${testDir}/eula.txt").writeText("eula=true")
// clean up
file("WorldGenTestServer").deleteRecursively()
fun copyTerra(dir: String) {
file("$testDir/$dir").walk().forEach {
if(it.name.startsWith("Terra-") && it.name.endsWith(".jar")) it.delete() // Delete old Terra jar(s)
}
copy {
from("$buildDir/libs/Terra-bukkit-$version-shaded.jar")
into("$testDir/$dir/plugins/")
}
}
val testWithPaper = task<JavaExec>(name = "testWithPaper") {
fun installServer(dir: String) {
// clean
file("$testDir/$dir").deleteRecursively()
file("$testDir/$dir/plugins").mkdirs()
// Cloning test setup.
gitClone("https://github.com/PolyhedralDev/WorldGenTestServer")
// Copying plugins
Files.move(Paths.get("WorldGenTestServer/plugins"),
Paths.get("$testDir/$dir/plugins"),
StandardCopyOption.REPLACE_EXISTING)
// Copying config
val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText()
file("$testDir/$dir/server.properties").writeText(serverText)
val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText()
file("$testDir/$dir/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT"))
println("By proceeding, you are agreeing to the Minecraft EULA: https://account.mojang.com/documents/minecraft_eula")
file("$testDir/$dir/eula.txt").writeText("eula=true")
// clean up
file("WorldGenTestServer").deleteRecursively()
}
fun deleteFolder(folder: File) {
if(folder.exists()) folder.deleteRecursively()
}
fun deleteFile(file: File) {
if(file.exists()) file.delete()
}
tasks.create("cleanWorlds") {
group = "bukkit"
doFirst {
deleteFolder(file("$testDir/paper/world"))
deleteFolder(file("$testDir/paper/world_nether"))
deleteFolder(file("$testDir/paper/world_the_end"))
deleteFolder(file("$testDir/purpur/world"))
deleteFolder(file("$testDir/purpur/world_nether"))
deleteFolder(file("$testDir/purpur/world_the_end"))
}
}
tasks.create("updatePaper") {
group = "bukkit"
doFirst {
deleteFile(file("$testDir/paper/paperclip.jar"))
downloadPaperclip(paperURL, "paper")
}
}
tasks.create("updatePurpur") {
group = "bukkit"
doFirst {
deleteFile(file("$testDir/paper/paperclip.jar"))
downloadPaperclip(purpurURL, "purpur")
}
}
tasks.create("installPaper") {
group = "bukkit"
dependsOn("shadowJar")
doFirst {
installServer("paper")
// Downloading latest paper jar.
downloadPaperclip(paperURL, "paper")
}
}
tasks.create("installPurpur") {
group = "bukkit"
dependsOn("shadowJar")
doFirst {
installServer("purpur")
// Downloading latest paper jar.
downloadPaperclip(purpurURL, "purpur")
}
}
task<JavaExec>(name = "runPaper") {
group = "bukkit"
standardInput = System.`in`
dependsOn("shadowJar")
// Copy Terra into dir
doFirst {
copy {
from("${buildDir}/libs/Terra-bukkit-${version}-shaded.jar")
into("${testDir}/plugins/")
}
copyTerra("paper")
}
main = "io.papermc.paperclip.Paperclip"
jvmArgs = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200",
"-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch",
"-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M",
"-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4",
"-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90",
"-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem",
"-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs",
"-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear")
maxHeapSize = "4G"
minHeapSize = "4G"
jvmArgs = aikarsFlags
maxHeapSize = testMem
minHeapSize = testMem
//args = listOf("nogui")
workingDir = file("${testDir}/")
classpath = files("${testDir}/paper.jar")
workingDir = file("$testDir/paper")
classpath = files("$testDir/paper/paperclip.jar")
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_1_8
}
task<JavaExec>(name = "runPurpur") {
group = "bukkit"
standardInput = System.`in`
dependsOn("shadowJar")
// Copy Terra into dir
doFirst {
copyTerra("purpur")
}
main = "io.papermc.paperclip.Paperclip"
jvmArgs = aikarsFlags
maxHeapSize = testMem
minHeapSize = testMem
//args = listOf("nogui")
workingDir = file("$testDir/purpur")
classpath = files("$testDir/purpur/paperclip.jar")
}
tasks.named<ShadowJar>("shadowJar") {
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
@@ -112,7 +206,6 @@ publishing {
repositories {
val mavenUrl = "https://repo.codemc.io/repository/maven-releases/"
val mavenSnapshotUrl = "https://repo.codemc.io/repository/maven-snapshots/"
maven(mavenUrl) {
val mavenUsername: String? by project
@@ -23,6 +23,8 @@ import org.jetbrains.annotations.NotNull;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -40,20 +42,13 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
private final TerraPlugin main;
private final List<TerraBlockPopulator> populators = new LinkedList<>();
private boolean needsLoad = true;
public BukkitChunkGeneratorWrapper(TerraChunkGenerator delegate) {
this.delegate = delegate;
this.main = delegate.getMain();
popMan = new PopulationManager(main);
popMan.attach(new OrePopulator(main));
popMan.attach(new TreePopulator(main));
popMan.attach(new FloraPopulator(main));
populators.add(new CavePopulator(main));
populators.add(new StructurePopulator(main));
populators.add(popMan);
this.popMan = new PopulationManager(delegate, main);
}
@@ -96,7 +91,7 @@ public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements Gener
@Override
public @NotNull List<BlockPopulator> getDefaultPopulators(@NotNull World world) {
return populators.stream().map(BukkitPopulatorWrapper::new).collect(Collectors.toList());
return Arrays.asList(popMan, new BukkitPopulatorWrapper(delegate));
}
@Override
@@ -1,27 +0,0 @@
package com.dfsek.terra.bukkit.generator;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.BlockPopulator;
import com.dfsek.terra.bukkit.world.BukkitChunk;
import com.dfsek.terra.bukkit.world.BukkitWorld;
import java.util.Random;
public class BukkitPopulator implements BlockPopulator {
private final org.bukkit.generator.BlockPopulator handle;
public BukkitPopulator(org.bukkit.generator.BlockPopulator handle) {
this.handle = handle;
}
@Override
public void populate(World world, Random random, Chunk chunk) {
handle.populate(((BukkitWorld) world).getHandle(), random, ((BukkitChunk) chunk).getHandle());
}
@Override
public org.bukkit.generator.BlockPopulator getHandle() {
return handle;
}
}
@@ -1,6 +1,8 @@
package com.dfsek.terra.bukkit.generator;
import com.dfsek.terra.api.world.generation.Chunkified;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import org.bukkit.Chunk;
import org.bukkit.World;
@@ -10,14 +12,18 @@ import org.jetbrains.annotations.NotNull;
import java.util.Random;
public class BukkitPopulatorWrapper extends BlockPopulator {
private final TerraBlockPopulator delegate;
private final TerraChunkGenerator delegate;
public BukkitPopulatorWrapper(TerraBlockPopulator delegate) {
public BukkitPopulatorWrapper(TerraChunkGenerator delegate) {
this.delegate = delegate;
}
@Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) {
delegate.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source));
delegate.getPopulators().forEach(populator -> {
if(populator instanceof Chunkified) {
populator.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source));
}
});
}
}
@@ -4,54 +4,35 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.world.generation.Chunkified;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.profiler.ProfileFuture;
import com.dfsek.terra.profiler.WorldProfiler;
import org.bukkit.generator.BlockPopulator;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
/**
* Cursed management class for the horrors of Bukkit population
*/
public class PopulationManager implements TerraBlockPopulator {
private final List<TerraBlockPopulator> attachedPopulators = new GlueList<>();
public class PopulationManager extends BlockPopulator {
private final TerraChunkGenerator generator;
private final HashSet<ChunkCoordinate> needsPop = new HashSet<>();
private final TerraPlugin main;
private WorldProfiler profiler;
public PopulationManager(TerraPlugin main) {
public PopulationManager(TerraChunkGenerator generator, TerraPlugin main) {
this.generator = generator;
this.main = main;
}
public void attach(TerraBlockPopulator populator) {
this.attachedPopulators.add(populator);
}
@Override
@SuppressWarnings("try")
public void populate(@NotNull World world, @NotNull Chunk chunk) {
try(ProfileFuture ignored = measure()) {
needsPop.add(new ChunkCoordinate(chunk));
int x = chunk.getX();
int z = chunk.getZ();
if(((TerraBukkitPlugin) main).isEnabled()) {
for(int xi = -1; xi <= 1; xi++) {
for(int zi = -1; zi <= 1; zi++) {
if(xi == 0 && zi == 0) continue;
if(world.isChunkGenerated(xi + x, zi + z)) checkNeighbors(xi + x, zi + z, world);
}
}
}
}
}
private ProfileFuture measure() {
if(profiler != null) return profiler.measure("PopulationManagerTime");
return null;
@@ -87,10 +68,30 @@ public class PopulationManager implements TerraBlockPopulator {
long zRand = (random.nextLong() / 2L << 1L) + 1L;
random.setSeed((long) x * xRand + (long) z * zRand ^ w.getSeed());
Chunk currentChunk = w.getChunkAt(x, z);
for(TerraBlockPopulator r : attachedPopulators) {
r.populate(w, currentChunk);
}
generator.getPopulators().forEach(populator -> {
if(!(populator instanceof Chunkified)) {
populator.populate(w, currentChunk);
}
});
needsPop.remove(c);
}
}
@Override
public void populate(org.bukkit.@NotNull World world, @NotNull Random random, org.bukkit.@NotNull Chunk source) {
try(ProfileFuture ignored = measure()) {
Chunk chunk = BukkitAdapter.adapt(source);
needsPop.add(new ChunkCoordinate(chunk));
int x = chunk.getX();
int z = chunk.getZ();
if(((TerraBukkitPlugin) main).isEnabled()) {
for(int xi = -1; xi <= 1; xi++) {
for(int zi = -1; zi <= 1; zi++) {
if(xi == 0 && zi == 0) continue;
if(world.isChunkGenerated(xi + x, zi + z)) checkNeighbors(xi + x, zi + z, BukkitAdapter.adapt(world));
}
}
}
}
}
}
+23 -1
View File
@@ -1,11 +1,13 @@
import com.dfsek.terra.configureCommon
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.modrinth.minotaur.TaskModrinthUpload
import net.fabricmc.loom.LoomGradleExtension
import net.fabricmc.loom.task.RemapJarTask
plugins {
`java-library`
id("fabric-loom").version("0.6-SNAPSHOT")
id("com.modrinth.minotaur").version("1.1.0")
}
configureCommon()
@@ -15,6 +17,11 @@ tasks.named<ShadowJar>("shadowJar") {
relocate("org.yaml", "com.dfsek.terra.lib.yaml")
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_1_8
}
group = "com.dfsek.terra.fabric"
dependencies {
@@ -39,7 +46,8 @@ configure<LoomGradleExtension> {
accessWidener("src/main/resources/terra.accesswidener")
}
tasks.register<RemapJarTask>("remapShadedJar") {
val remapped = tasks.register<RemapJarTask>("remapShadedJar") {
group = "fabric"
val shadowJar = tasks.getByName<ShadowJar>("shadowJar")
dependsOn(shadowJar)
input.set(shadowJar.archiveFile)
@@ -47,3 +55,17 @@ tasks.register<RemapJarTask>("remapShadedJar") {
addNestedDependencies.set(true)
remapAccessWidener.set(true)
}
tasks.register<TaskModrinthUpload>("publishModrinth") {
dependsOn("remapShadedJar")
group = "fabric"
token = System.getenv("MODRINTH_SECRET")
projectId = "FIlZB9L0"
versionNumber = project.version.toString()
uploadFile = remapped.get().archiveFile.get().asFile
releaseType = "beta"
addGameVersion("1.16.4")
addGameVersion("1.16.5")
addLoader("fabric")
}
@@ -35,6 +35,7 @@ import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.fabric.inventory.FabricItemHandle;
import com.dfsek.terra.fabric.mixin.GeneratorTypeAccessor;
import com.dfsek.terra.fabric.world.FabricAdapter;
@@ -150,7 +151,6 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
@Override
public TerraWorld getWorld(World world) {
if(worldMap.size() > 1) System.out.println(worldMap.size());
return worldMap.computeIfAbsent(world.getSeed(), w -> {
logger.info("Loading world " + w);
return new TerraWorld(world, ((FabricChunkGeneratorWrapper) ((FabricChunkGenerator) world.getGenerator()).getHandle()).getPack(), this);
@@ -246,6 +246,9 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
DefaultBiomeFeatures.addFarmAnimals(spawnSettings);
DefaultBiomeFeatures.addMonsters(spawnSettings, 95, 5, 100);
BiomeTemplate template = biome.getTemplate();
Map<String, Integer> colors = template.getColors();
Biome vanilla = ((FabricBiome) new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle();
GenerationSettings.Builder generationSettings = new GenerationSettings.Builder();
@@ -254,28 +257,37 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
BiomeEffects.Builder effects = new BiomeEffects.Builder()
.waterColor(vanilla.getEffects().waterColor)
.waterFogColor(vanilla.getEffects().waterFogColor)
.fogColor(vanilla.getEffects().fogColor)
.skyColor(vanilla.getEffects().skyColor)
.waterColor(colors.getOrDefault("water", vanilla.getEffects().waterColor))
.waterFogColor(colors.getOrDefault("water-fog", vanilla.getEffects().waterFogColor))
.fogColor(colors.getOrDefault("fog", vanilla.getEffects().fogColor))
.skyColor(colors.getOrDefault("sky", vanilla.getEffects().skyColor))
.grassColorModifier(vanilla.getEffects().grassColorModifier);
vanilla.getEffects().grassColor.ifPresent(effects::grassColor);
vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor);
return (new Biome.Builder())
if(colors.containsKey("grass")) {
effects.grassColor(colors.get("grass"));
} else {
vanilla.getEffects().grassColor.ifPresent(effects::grassColor);
}
vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor);
if(colors.containsKey("foliage")) {
effects.foliageColor(colors.get("foliage"));
} else {
vanilla.getEffects().foliageColor.ifPresent(effects::foliageColor);
}
return new Biome.Builder()
.precipitation(vanilla.getPrecipitation())
.category(vanilla.getCategory())
.depth(vanilla.getDepth())
.scale(vanilla.getScale())
.temperature(vanilla.getTemperature())
.downfall(vanilla.getDownfall())
.effects(vanilla.getEffects()) // TODO: configurable
.effects(effects.build())
.spawnSettings(spawnSettings.build())
.generationSettings(generationSettings.build())
.build();
}
@SuppressWarnings("unchecked")
@Override
public void onInitialize() {
instance = this;
@@ -327,10 +339,8 @@ public class TerraFabricPlugin implements TerraPlugin, ModInitializer {
CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> {
int max = manager.getMaxArgumentDepth();
System.out.println("MAX:" + max);
RequiredArgumentBuilder<ServerCommandSource, String> arg = argument("arg" + (max - 1), StringArgumentType.word());
for(int i = 0; i < max; i++) {
System.out.println("arg " + i);
RequiredArgumentBuilder<ServerCommandSource, String> next = argument("arg" + (max - i - 1), StringArgumentType.word());
arg = next.then(assemble(arg, manager));
@@ -27,11 +27,7 @@ public class PopulatorFeature extends Feature<DefaultFeatureConfig> {
FabricChunkGeneratorWrapper gen = (FabricChunkGeneratorWrapper) chunkGenerator;
FabricChunkWorldAccess chunk = new FabricChunkWorldAccess(world, pos.getX() >> 4, pos.getZ() >> 4);
FabricWorld world1 = new FabricWorld(world.toServerWorld(), new FabricChunkGenerator(chunkGenerator));
gen.getCavePopulator().populate(new FabricWorldAccess(world), chunk);
gen.getStructurePopulator().populate(new FabricWorldAccess(world), chunk);
gen.getOrePopulator().populate(world1, chunk);
gen.getTreePopulator().populate(world1, chunk);
gen.getFloraPopulator().populate(world1, chunk);
gen.getHandle().getPopulators().forEach(populator -> populator.populate(world1, chunk));
return true;
}
}
@@ -50,32 +50,6 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
return pack;
}
private final FloraPopulator floraPopulator = new FloraPopulator(TerraFabricPlugin.getInstance());
private final OrePopulator orePopulator = new OrePopulator(TerraFabricPlugin.getInstance());
private final TreePopulator treePopulator = new TreePopulator(TerraFabricPlugin.getInstance());
private final StructurePopulator structurePopulator = new StructurePopulator(TerraFabricPlugin.getInstance());
private final CavePopulator cavePopulator = new CavePopulator(TerraFabricPlugin.getInstance());
public TreePopulator getTreePopulator() {
return treePopulator;
}
public OrePopulator getOrePopulator() {
return orePopulator;
}
public FloraPopulator getFloraPopulator() {
return floraPopulator;
}
public StructurePopulator getStructurePopulator() {
return structurePopulator;
}
public CavePopulator getCavePopulator() {
return cavePopulator;
}
public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) {
super(biomeSource, new StructuresConfig(false));
this.pack = configPack;
@@ -124,6 +98,8 @@ public class FabricChunkGeneratorWrapper extends ChunkGenerator implements Gener
}
@Override
public boolean isStrongholdStartingChunk(ChunkPos chunkPos) {
return false;
+44
View File
@@ -0,0 +1,44 @@
import com.dfsek.terra.configureCommon
plugins {
java
}
group = "com.dfsek.terra.minestom"
configureCommon()
repositories {
mavenCentral()
maven { url = uri("https://repo.spongepowered.org/maven") }
maven { url = uri("https://repo.velocitypowered.com/snapshots/") }
maven { url = uri("https://libraries.minecraft.net") }
maven { url = uri("https://jitpack.io") }
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
}
dependencies {
testCompile("junit", "junit", "4.12")
"shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1")
"shadedImplementation"("org.apache.logging.log4j:log4j-core:2.14.1")
"shadedImplementation"("org.apache.logging.log4j:log4j-api:2.14.1")
"shadedImplementation"("com.github.Minestom:Minestom:4cf66fde08")
"shadedApi"(project(":common"))
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
tasks.jar {
manifest {
attributes(
"Main-Class" to "com.dfsek.terra.minestom.MinestomEntry",
"Multi-Release" to "true"
)
}
}
@@ -0,0 +1,10 @@
package com.dfsek.terra.minestom;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.minestom.world.MinestomBlock;
public final class MinestomAdapter {
public static net.minestom.server.instance.block.Block adapt(Block block) {
return ((MinestomBlock) block).getHandle();
}
}
@@ -0,0 +1,47 @@
package com.dfsek.terra.minestom;
import com.dfsek.terra.minestom.commands.TeleportCommand;
import com.dfsek.terra.minestom.generator.MinestomChunkGeneratorWrapper;
import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player;
import net.minestom.server.event.GlobalEventHandler;
import net.minestom.server.event.player.PlayerLoginEvent;
import net.minestom.server.event.player.PlayerSpawnEvent;
import net.minestom.server.instance.InstanceContainer;
import net.minestom.server.instance.InstanceManager;
import net.minestom.server.utils.Position;
public final class MinestomEntry {
public static void main(String... args) {
MinecraftServer server = MinecraftServer.init();
InstanceManager instanceManager = MinecraftServer.getInstanceManager();
InstanceContainer container = instanceManager.createInstanceContainer();
TerraMinestomPlugin plugin = new TerraMinestomPlugin();
DefaultChunkGenerator3D chunkGenerator3D = new DefaultChunkGenerator3D(plugin.getConfigRegistry().get("DEFAULT"), plugin);
container.setChunkGenerator(new MinestomChunkGeneratorWrapper(chunkGenerator3D, container));
MinecraftServer.getBiomeManager().unmodifiableCollection().forEach(biome -> System.out.println(biome.getId() + ": " + biome.toNbt()));
GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
globalEventHandler.addEventCallback(PlayerLoginEvent.class, event -> {
Player player = event.getPlayer();
event.setSpawningInstance(container);
player.setRespawnPoint(new Position(0, 64, 0));
});
MinecraftServer.getCommandManager().register(new TeleportCommand());
globalEventHandler.addEventCallback(PlayerSpawnEvent.class, event -> event.getPlayer().setGameMode(GameMode.SPECTATOR));
server.start("0.0.0.0", 25565);
}
}
@@ -0,0 +1,25 @@
package com.dfsek.terra.minestom;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.inventory.Item;
import com.dfsek.terra.api.platform.inventory.item.Enchantment;
import java.util.Collections;
import java.util.Set;
public class MinestomItemHandle implements ItemHandle {
@Override
public Item createItem(String data) {
return null;
}
@Override
public Enchantment getEnchantment(String id) {
return null;
}
@Override
public Set<Enchantment> getEnchantments() {
return Collections.emptySet();
}
}
@@ -0,0 +1,193 @@
package com.dfsek.terra.minestom;
import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.addons.TerraAddon;
import com.dfsek.terra.api.addons.annotations.Addon;
import com.dfsek.terra.api.addons.annotations.Author;
import com.dfsek.terra.api.addons.annotations.Version;
import com.dfsek.terra.api.event.EventListener;
import com.dfsek.terra.api.event.EventManager;
import com.dfsek.terra.api.event.TerraEventManager;
import com.dfsek.terra.api.event.annotations.Global;
import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.handle.ItemHandle;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.LockedRegistry;
import com.dfsek.terra.api.util.logging.DebugLogger;
import com.dfsek.terra.api.util.logging.Logger;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.PluginConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.lang.Language;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.minestom.world.MinestomBiome;
import com.dfsek.terra.minestom.world.MinestomChunkAccess;
import com.dfsek.terra.minestom.world.MinestomTree;
import com.dfsek.terra.minestom.world.MinestomWorld;
import com.dfsek.terra.minestom.world.MinestomWorldHandle;
import com.dfsek.terra.registry.master.AddonRegistry;
import com.dfsek.terra.registry.master.ConfigRegistry;
import com.dfsek.terra.world.TerraWorld;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minestom.server.instance.Instance;
import org.apache.logging.log4j.LogManager;
import java.io.File;
import java.util.Map;
public class TerraMinestomPlugin implements TerraPlugin {
private final org.apache.logging.log4j.Logger logger = LogManager.getLogger();
private final MinestomWorldHandle worldHandle = new MinestomWorldHandle();
private final PluginConfig config = new PluginConfig();
private final EventManager eventManager = new TerraEventManager(this);
private final ConfigRegistry configRegistry = new ConfigRegistry();
private final AddonRegistry addonRegistry = new AddonRegistry(new MinestomPlugin(this), this);
private final GenericLoaders genericLoaders = new GenericLoaders(this);
private final MinestomItemHandle itemHandle = new MinestomItemHandle();
private final Map<Instance, TerraWorld> instanceTerraWorldMap = new Object2ObjectOpenHashMap<>();
public TerraMinestomPlugin() {
if(!getDataFolder().exists()) {
getDataFolder().mkdirs();
}
LangUtil.load(config.getLanguage(), this);
configRegistry.loadAll(this);
addonRegistry.loadAll();
}
@Override
public void register(TypeRegistry registry) {
registry
.registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o))
.registerLoader(Biome.class, (t, o, l) -> new MinestomBiome(net.minestom.server.world.biomes.Biome.PLAINS));
genericLoaders.register(registry);
}
@Override
public WorldHandle getWorldHandle() {
return worldHandle;
}
@Override
public TerraWorld getWorld(World world) {
if(world instanceof MinestomWorld) {
return instanceTerraWorldMap.computeIfAbsent(((MinestomWorld) world).getHandle(), instance -> new TerraWorld(new MinestomWorld(instance), configRegistry.get("DEFAULT"), this));
} else {
return instanceTerraWorldMap.computeIfAbsent(((MinestomWorld) ((MinestomChunkAccess) world).getWorld()).getHandle(), instance -> new TerraWorld(new MinestomWorld(instance), configRegistry.get("DEFAULT"), this));
}
}
@Override
public Logger logger() {
return new Logger() {
@Override
public void info(String message) {
System.out.println(message);
}
@Override
public void warning(String message) {
System.out.println(message);
}
@Override
public void severe(String message) {
System.err.println(message);
}
};
}
@Override
public PluginConfig getTerraConfig() {
return config;
}
@Override
public File getDataFolder() {
return new File("Terra");
}
@Override
public boolean isDebug() {
return true;
}
@Override
public Language getLanguage() {
return LangUtil.getLanguage();
}
@Override
public CheckedRegistry<ConfigPack> getConfigRegistry() {
return new CheckedRegistry<>(configRegistry);
}
@Override
public LockedRegistry<TerraAddon> getAddons() {
return new LockedRegistry<>(addonRegistry);
}
@Override
public boolean reload() {
return true;
}
@Override
public ItemHandle getItemHandle() {
return itemHandle;
}
@Override
public void saveDefaultConfig() {
}
@Override
public String platformName() {
return "Minestom";
}
@Override
public DebugLogger getDebugLogger() {
return new DebugLogger(logger());
}
@Override
public EventManager getEventManager() {
return eventManager;
}
@Addon("Terra-Minestom")
@Author("Terra")
@Version("1.0.0")
private static final class MinestomPlugin extends TerraAddon implements EventListener {
private final TerraPlugin main;
private MinestomPlugin(TerraPlugin main) {
this.main = main;
}
@Override
public void initialize() {
main.getEventManager().registerListener(this, this);
}
@Global
public void registerTrees(ConfigPackPreLoadEvent event) {
CheckedRegistry<Tree> treeCheckedRegistry = event.getPack().getTreeRegistry();
treeCheckedRegistry.addUnchecked("BIRCH", new MinestomTree());
treeCheckedRegistry.addUnchecked("JUNGLE_BUSH", new MinestomTree());
treeCheckedRegistry.addUnchecked("SWAMP_OAK", new MinestomTree());
treeCheckedRegistry.addUnchecked("JUNGLE_COCOA", new MinestomTree());
treeCheckedRegistry.addUnchecked("RED_MUSHROOM", new MinestomTree());
treeCheckedRegistry.addUnchecked("BROWN_MUSHROOM", new MinestomTree());
}
}
}
@@ -0,0 +1,19 @@
package com.dfsek.terra.minestom.commands;
import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.Argument;
import net.minestom.server.command.builder.arguments.ArgumentType;
import net.minestom.server.entity.Entity;
import net.minestom.server.utils.Position;
public class TeleportCommand extends Command {
public TeleportCommand() {
super("teleport", "tp");
Argument<Double> x = ArgumentType.Double("x");
Argument<Double> y = ArgumentType.Double("y");
Argument<Double> z = ArgumentType.Double("z");
addSyntax((sender, context) -> ((Entity) sender).teleport(new Position(context.get(x), context.get(y), context.get(z))), x, y, z);
}
}
@@ -0,0 +1,31 @@
package com.dfsek.terra.minestom.commands;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.command.CommandManager;
import com.dfsek.terra.api.command.TerraCommandManager;
import com.dfsek.terra.api.command.exception.CommandException;
import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.ArgumentStringArray;
import net.minestom.server.command.builder.arguments.ArgumentType;
import java.util.Arrays;
import java.util.List;
public class TerraCommand extends Command {
public TerraCommand(TerraPlugin main) {
super("terra", "te");
CommandManager manager = new TerraCommandManager(main);
ArgumentStringArray argument = ArgumentType.StringArray("args");
addSyntax(((sender, context) -> {
List<String> args = Arrays.asList(context.get(argument));
try {
manager.execute(args.remove(0), null, args);
} catch(CommandException e) {
e.printStackTrace();
}
}), argument);
}
}
@@ -0,0 +1,16 @@
package com.dfsek.terra.minestom.generator;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
public class MinestomChunkGenerator implements ChunkGenerator {
private final net.minestom.server.instance.ChunkGenerator delegate;
public MinestomChunkGenerator(net.minestom.server.instance.ChunkGenerator delegate) {
this.delegate = delegate;
}
@Override
public net.minestom.server.instance.ChunkGenerator getHandle() {
return delegate;
}
}
@@ -0,0 +1,52 @@
package com.dfsek.terra.minestom.generator;
import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.minestom.world.MinestomBiomeGrid;
import com.dfsek.terra.minestom.world.MinestomBlockPopulatorWrapper;
import com.dfsek.terra.minestom.world.MinestomChunkData;
import com.dfsek.terra.minestom.world.MinestomWorld;
import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D;
import net.minestom.server.instance.ChunkGenerator;
import net.minestom.server.instance.ChunkPopulator;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class MinestomChunkGeneratorWrapper implements GeneratorWrapper, ChunkGenerator {
private final DefaultChunkGenerator3D chunkGenerator3D;
private final Instance instance;
private final List<ChunkPopulator> populators = new ArrayList<>();
public MinestomChunkGeneratorWrapper(DefaultChunkGenerator3D chunkGenerator3D, Instance instance) {
this.chunkGenerator3D = chunkGenerator3D;
this.instance = instance;
chunkGenerator3D.getPopulators().forEach(terraBlockPopulator -> populators.add(new MinestomBlockPopulatorWrapper(terraBlockPopulator, instance)));
}
@Override
public TerraChunkGenerator getHandle() {
return chunkGenerator3D;
}
@Override
public void generateChunkData(@NotNull ChunkBatch batch, int chunkX, int chunkZ) {
chunkGenerator3D.generateChunkData(new MinestomWorld(instance), new FastRandom(), chunkX, chunkZ, new MinestomChunkData(batch));
}
@Override
public void fillBiomes(@NotNull Biome[] biomes, int chunkX, int chunkZ) {
chunkGenerator3D.generateBiomes(new MinestomWorld(instance), new FastRandom(), chunkX, chunkZ, new MinestomBiomeGrid(biomes, chunkX, chunkZ));
}
@Override
public @Nullable List<ChunkPopulator> getPopulators() {
return populators;
}
}
@@ -0,0 +1,16 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.platform.world.Biome;
public class MinestomBiome implements Biome {
private final net.minestom.server.world.biomes.Biome delegate;
public MinestomBiome(net.minestom.server.world.biomes.Biome delegate) {
this.delegate = delegate;
}
@Override
public net.minestom.server.world.biomes.Biome getHandle() {
return delegate;
}
}
@@ -0,0 +1,52 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.platform.world.BiomeGrid;
import org.jetbrains.annotations.NotNull;
public class MinestomBiomeGrid implements BiomeGrid {
private final net.minestom.server.world.biomes.Biome[] biomes;
private final int chunkX;
private final int chunkZ;
public MinestomBiomeGrid(net.minestom.server.world.biomes.Biome[] biomes, int chunkX, int chunkZ) {
this.biomes = biomes;
this.chunkX = chunkX;
this.chunkZ = chunkZ;
}
@Override
public Object getHandle() {
return null;
}
@Override
public @NotNull Biome getBiome(int x, int z) {
return getBiome(x, 0, z);
}
@Override
public @NotNull Biome getBiome(int x, int y, int z) {
x -= (chunkX << 4);
z -= (chunkZ << 4);
x >>= 2;
y >>= 2;
z >>= 2;
return new MinestomBiome(biomes[(x << 8) + (y << 2) + z]);
}
@Override
public void setBiome(int x, int z, @NotNull Biome bio) {
for(int y = 0; y < 64; y++) setBiome(x, y << 2, z, bio);
}
@Override
public void setBiome(int x, int y, int z, @NotNull Biome bio) {
x -= (chunkX << 4);
z -= (chunkZ << 4);
x >>= 2;
y >>= 2;
z >>= 2;
biomes[(x << 8) + (y << 2) + z] = ((MinestomBiome) bio).getHandle();
}
}
@@ -0,0 +1,82 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockFace;
import com.dfsek.terra.api.platform.block.state.BlockState;
import com.dfsek.terra.api.util.generic.either.Either;
import net.minestom.server.utils.BlockPosition;
public class MinestomBlock implements Block {
private final net.minestom.server.instance.block.Block delegate;
private final BlockPosition position;
private final Either<MinestomChunkAccess, MinestomWorld> world;
public MinestomBlock(net.minestom.server.instance.block.Block delegate, BlockPosition position, Either<MinestomChunkAccess, MinestomWorld> world) {
this.delegate = delegate;
this.position = position;
this.world = world;
}
@Override
public net.minestom.server.instance.block.Block getHandle() {
return delegate;
}
@Override
public void setBlockData(BlockData data, boolean physics) {
world.ifLeft(chunk -> chunk.getHandle().setBlock(position.getX() - (chunk.getX() << 4), position.getY(), position.getZ() - (chunk.getZ() << 4), ((MinestomBlockData) data).getHandle()));
world.ifRight(world -> {
//world.getHandle().setBlock(position.getX(), position.getY(), position.getZ(), delegate);
});
}
@Override
public BlockData getBlockData() {
return new MinestomBlockData(delegate);
}
@Override
public BlockState getState() {
return null;
}
@Override
public Block getRelative(BlockFace face, int len) {
BlockPosition newLoc = position.clone().add(face.getModX(), face.getModY(), face.getModZ());
if(world.hasLeft()) return world.getLeft().get().getBlock(newLoc.getX(), newLoc.getY(), newLoc.getZ());
else return world.getRight().get().getBlockAt(newLoc.getX(), newLoc.getY(), newLoc.getZ());
}
@Override
public boolean isEmpty() {
return delegate.isAir();
}
@Override
public Location getLocation() {
if(world.hasLeft()) return new Location(world.getLeft().get().getWorld(), position.getX(), position.getY(), position.getZ());
return new Location(world.getRight().get(), position.getX(), position.getY(), position.getZ());
}
@Override
public int getX() {
return position.getX();
}
@Override
public int getZ() {
return position.getZ();
}
@Override
public int getY() {
return position.getY();
}
@Override
public boolean isPassable() {
return !delegate.isSolid();
}
}
@@ -0,0 +1,81 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.BlockType;
import net.minestom.server.instance.block.Block;
public class MinestomBlockData implements BlockData, BlockType {
private final Block delegate;
public MinestomBlockData(Block delegate) {
if(delegate == null) throw new NullPointerException("Delegate must not be null");
this.delegate = delegate;
}
@Override
public Block getHandle() {
return delegate;
}
@Override
public BlockType getBlockType() {
return this;
}
@Override
public boolean matches(BlockData other) {
return delegate == ((MinestomBlockData) other).delegate;
}
@Override
public BlockData clone() {
BlockData clone;
try {
clone = (BlockData) super.clone();
} catch(CloneNotSupportedException e) {
throw new Error(e);
}
return clone;
}
@Override
public String getAsString() {
return delegate.getName();
}
@Override
public boolean isAir() {
return delegate.isAir();
}
@Override
public boolean isStructureVoid() {
return delegate == Block.STRUCTURE_VOID;
}
@Override
public BlockData getDefaultData() {
return this;
}
@Override
public boolean isSolid() {
return delegate.isSolid();
}
@Override
public boolean isWater() {
return delegate == Block.WATER;
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof MinestomBlockData)) return false;
return ((MinestomBlockData) obj).delegate == delegate;
}
}
@@ -0,0 +1,24 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.ChunkPopulator;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.batch.ChunkBatch;
public class MinestomBlockPopulatorWrapper implements ChunkPopulator {
private final TerraBlockPopulator populator;
private final Instance world;
public MinestomBlockPopulatorWrapper(TerraBlockPopulator populator, Instance world) {
this.populator = populator;
this.world = world;
}
@Override
public void populateChunk(ChunkBatch batch, Chunk chunk) {
World minestom = new MinestomChunkWorld(batch, chunk, world);
populator.populate(minestom, new MinestomChunk(chunk, batch, new MinestomWorld(world)));
}
}
@@ -0,0 +1,57 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.generic.either.Either;
import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.utils.BlockPosition;
import org.jetbrains.annotations.NotNull;
public class MinestomChunk implements Chunk, MinestomChunkAccess {
private final net.minestom.server.instance.Chunk chunk;
private final ChunkBatch batch;
private final MinestomWorld world;
public MinestomChunk(net.minestom.server.instance.Chunk chunk, ChunkBatch batch, MinestomWorld world) {
this.chunk = chunk;
this.batch = batch;
this.world = world;
}
@Override
public ChunkBatch getHandle() {
return batch;
}
@Override
public int getX() {
return chunk.getChunkX();
}
@Override
public int getZ() {
return chunk.getChunkZ();
}
@Override
public World getWorld() {
return new MinestomChunkWorld(batch, chunk, world.getHandle());
}
@Override
public Block getBlock(int x, int y, int z) {
return new MinestomBlock(net.minestom.server.instance.block.Block.fromStateId(chunk.getBlockStateId(x, y, z)), new BlockPosition((getX() << 4) + x, y, (getZ() << 4) + z), Either.left(this));
}
@Override
public void setBlock(int x, int y, int z, @NotNull BlockData blockData) {
batch.setBlock(x, y, z, ((MinestomBlockData) blockData).getHandle());
}
@Override
public @NotNull BlockData getBlockData(int x, int y, int z) {
return getBlock(x, y, z).getBlockData();
}
}
@@ -0,0 +1,17 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.world.World;
import net.minestom.server.instance.batch.ChunkBatch;
public interface MinestomChunkAccess {
ChunkBatch getHandle();
int getX();
int getZ();
Block getBlock(int x, int y, int z);
World getWorld();
}
@@ -0,0 +1,43 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.world.generator.ChunkData;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.instance.block.Block;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class MinestomChunkData implements ChunkData {
private static final BlockData AIR = new MinestomBlockData(Block.AIR);
private final ChunkBatch batch;
private final Map<Long, MinestomBlockData> dataMap = new Long2ObjectOpenHashMap<>();
public MinestomChunkData(ChunkBatch batch) {
this.batch = batch;
}
@Override
public Object getHandle() {
return batch;
}
@Override
public void setBlock(int x, int y, int z, @NotNull BlockData blockData) {
MinestomBlockData d = ((MinestomBlockData) blockData);
dataMap.put(((long) y << 12) + ((long) x << 4) + y, d);
batch.setBlock(x, y, z, d.getHandle());
}
@Override
public @NotNull BlockData getBlockData(int x, int y, int z) {
BlockData data = dataMap.get(((long) y << 12) + ((long) x << 4) + y);
return data == null ? AIR : data;
}
@Override
public int getMaxHeight() {
return 255;
}
}
@@ -0,0 +1,109 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.api.util.generic.either.Either;
import com.dfsek.terra.minestom.generator.MinestomChunkGenerator;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.utils.BlockPosition;
import java.io.File;
import java.util.UUID;
public class MinestomChunkWorld implements World, MinestomChunkAccess {
private final ChunkBatch batch;
private final net.minestom.server.instance.Chunk chunk;
private final Instance world;
public MinestomChunkWorld(ChunkBatch batch, net.minestom.server.instance.Chunk chunk, Instance world) {
this.batch = batch;
this.chunk = chunk;
this.world = world;
}
@Override
public ChunkBatch getHandle() {
return batch;
}
@Override
public int getX() {
return chunk.getChunkX();
}
@Override
public int getZ() {
return chunk.getChunkZ();
}
@Override
public Block getBlock(int x, int y, int z) {
return new MinestomBlock(net.minestom.server.instance.block.Block.fromStateId(chunk.getBlockStateId(x, y, z)), new BlockPosition((chunk.getChunkX() << 4) + x, y, (chunk.getChunkZ() << 4) + z), Either.left(this));
}
@Override
public World getWorld() {
return new MinestomWorld(world);
}
@Override
public long getSeed() {
return 0;
}
@Override
public int getMaxHeight() {
return 255;
}
@Override
public ChunkGenerator getGenerator() {
return new MinestomChunkGenerator(world.getChunkGenerator());
}
@Override
public String getName() {
return null;
}
@Override
public UUID getUID() {
return world.getUniqueId();
}
@Override
public boolean isChunkGenerated(int x, int z) {
return false;
}
@Override
public Chunk getChunkAt(int x, int z) {
return null;
}
@Override
public File getWorldFolder() {
return null;
}
@Override
public Block getBlockAt(int x, int y, int z) {
return new MinestomBlock(net.minestom.server.instance.block.Block.fromStateId(chunk.getBlockStateId(x - (getX() << 4), y, z - (getZ() << 4))), new BlockPosition(x, y, z), Either.left(this));
}
@Override
public Entity spawnEntity(Location location, EntityType entityType) {
return null;
}
@Override
public int getMinHeight() {
return 0;
}
}
@@ -0,0 +1,19 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.world.Tree;
import com.dfsek.terra.api.util.collections.MaterialSet;
import java.util.Random;
public class MinestomTree implements Tree {
@Override
public boolean plant(Location l, Random r) {
return true;
}
@Override
public MaterialSet getSpawnable() {
return MaterialSet.empty();
}
}
@@ -0,0 +1,84 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.platform.block.Block;
import com.dfsek.terra.api.platform.entity.Entity;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.platform.world.generator.ChunkGenerator;
import com.dfsek.terra.api.util.generic.either.Either;
import com.dfsek.terra.minestom.generator.MinestomChunkGenerator;
import net.minestom.server.instance.Instance;
import net.minestom.server.utils.BlockPosition;
import java.io.File;
import java.util.UUID;
public class MinestomWorld implements World {
private final Instance instance;
public MinestomWorld(Instance instance) {
this.instance = instance;
}
@Override
public Instance getHandle() {
return instance;
}
@Override
public long getSeed() {
return 2403;
}
@Override
public int getMaxHeight() {
return 255;
}
@Override
public ChunkGenerator getGenerator() {
return new MinestomChunkGenerator(instance.getChunkGenerator());
}
@Override
public String getName() {
return null;
}
@Override
public UUID getUID() {
return instance.getUniqueId();
}
@Override
public boolean isChunkGenerated(int x, int z) {
return false;
}
@Override
public Chunk getChunkAt(int x, int z) {
return null; //instance.getChunk(x, z);
}
@Override
public File getWorldFolder() {
return null;
}
@Override
public Block getBlockAt(int x, int y, int z) {
return new MinestomBlock(instance.getBlock(x, y, z), new BlockPosition(x, y, z), Either.right(this));
}
@Override
public Entity spawnEntity(Location location, EntityType entityType) {
return null;
}
@Override
public int getMinHeight() {
return 0;
}
}
@@ -0,0 +1,38 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.entity.EntityType;
import com.dfsek.terra.api.platform.handle.WorldHandle;
import net.minestom.server.instance.block.Block;
import java.util.HashMap;
import java.util.Map;
public class MinestomWorldHandle implements WorldHandle {
private static final Map<String, Block> BLOCKS = new HashMap<>();
static {
for(Block value : Block.values()) {
BLOCKS.put(value.getName(), value);
}
}
@Override
public BlockData createBlockData(String data) {
String baseData = data.contains("[") ? data.substring(0, data.indexOf('[')) : data;
Block minestomBlock = BLOCKS.get(baseData);
if(data.contains("[")) {
String properties = data.substring(data.indexOf('['), data.indexOf(']'));
String[] propArray = properties.split(",");
minestomBlock = Block.fromStateId(minestomBlock.withProperties(propArray));
}
return new MinestomBlockData(minestomBlock);
}
@Override
public EntityType getEntity(String id) {
return null;
}
}
+5
View File
@@ -14,6 +14,11 @@ repositories {
maven { url = uri("https://jitpack.io/") }
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
dependencies {
"shadedApi"(project(":common"))
"shadedImplementation"("com.github.Querz:NBT:5.2") // Standalone NBT API
+5
View File
@@ -14,6 +14,11 @@ repositories {
jcenter()
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_1_8
}
dependencies {
"compileOnly"("org.spongepowered:spongeapi:7.2.0")
"shadedApi"(project(":common"))
+1
View File
@@ -13,6 +13,7 @@ include("platforms:bukkit")
include("platforms:fabric")
include("platforms:region")
include("platforms:sponge")
include("platforms:minestom")
pluginManagement {
repositories {