Merge branch 'master' into feat/allay-update

# Conflicts:
#	platforms/allay/src/main/java/com/dfsek/terra/allay/Mapping.java
#	platforms/allay/src/main/java/com/dfsek/terra/allay/handle/AllayItemHandle.java
This commit is contained in:
daoge_cmd
2025-10-04 17:19:01 +08:00
499 changed files with 4017 additions and 10011 deletions

View File

@@ -21,6 +21,7 @@ import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.world.biome.PlatformBiome;
/**
* @author daoge_cmd
*/
@@ -38,8 +39,7 @@ public class AllayPlatform extends AbstractPlatform {
@Override
public boolean reload() {
getTerraConfig().load(this);
getRawConfigRegistry().clear();
boolean succeed = getRawConfigRegistry().loadAll(this);
boolean succeed = loadConfigPacks();
GENERATOR_WRAPPERS.forEach(wrapper -> {
getConfigRegistry().get(wrapper.getConfigPack().getRegistryKey()).ifPresent(pack -> {
@@ -51,6 +51,7 @@ public class AllayPlatform extends AbstractPlatform {
);
});
});
return succeed;
}

View File

@@ -14,20 +14,12 @@ public class JeBlockState {
protected final TreeMap<String, String> properties;
protected int hash = Integer.MAX_VALUE;
public static JeBlockState fromString(String data) {
return new JeBlockState(data);
}
public static JeBlockState create(String identifier, TreeMap<String, String> properties) {
return new JeBlockState(identifier, properties);
}
private JeBlockState(String data) {
String[] strings = data.replace("[", ",").replace("]", ",").replace(" ", "").split(",");
this.identifier = strings[0];
this.properties = new TreeMap<>();
if (strings.length > 1) {
for (int i = 1; i < strings.length; i++) {
if(strings.length > 1) {
for(int i = 1; i < strings.length; i++) {
final String tmp = strings[i];
final int index = tmp.indexOf("=");
properties.put(tmp.substring(0, index), tmp.substring(index + 1));
@@ -36,6 +28,19 @@ public class JeBlockState {
completeMissingProperties();
}
private JeBlockState(String identifier, TreeMap<String, String> properties) {
this.identifier = identifier;
this.properties = properties;
}
public static JeBlockState fromString(String data) {
return new JeBlockState(data);
}
public static JeBlockState create(String identifier, TreeMap<String, String> properties) {
return new JeBlockState(identifier, properties);
}
public String getPropertyValue(String key) {
return properties.get(key);
}
@@ -49,24 +54,19 @@ public class JeBlockState {
entry -> properties.put(entry.getKey(), entry.getValue()));
}
private JeBlockState(String identifier, TreeMap<String, String> properties) {
this.identifier = identifier;
this.properties = properties;
}
public String toString(boolean includeProperties) {
if(!includeProperties) return identifier;
StringBuilder builder = new StringBuilder(identifier).append(";");
properties.forEach((k, v) -> builder.append(k).append("=").append(v).append(";"));
String str = builder.toString();
if (hash == Integer.MAX_VALUE) {
if(hash == Integer.MAX_VALUE) {
hash = HashUtils.fnv1a_32(str.getBytes());
}
return str;
}
public int getHash() {
if (hash == Integer.MAX_VALUE) {
if(hash == Integer.MAX_VALUE) {
hash = HashUtils.fnv1a_32(toString(true).getBytes());
}
return hash;

View File

@@ -70,6 +70,7 @@ public class TerraAllayPlugin extends Plugin {
@EventHandler
private void onWorldUnload(WorldUnloadEvent event) {
AllayPlatform.GENERATOR_WRAPPERS.removeIf(wrapper -> wrapper.getAllayWorldGenerator().getDimension().getWorld() == event.getWorld());
AllayPlatform.GENERATOR_WRAPPERS.removeIf(
wrapper -> wrapper.getAllayWorldGenerator().getDimension().getWorld() == event.getWorld());
}
}

View File

@@ -4,6 +4,7 @@ import org.allaymc.api.world.biome.BiomeType;
import com.dfsek.terra.api.world.biome.PlatformBiome;
/**
* @author daoge_cmd
*/

View File

@@ -7,6 +7,7 @@ import com.dfsek.terra.allay.JeBlockState;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.block.state.properties.Property;
/**
* @author daoge_cmd
*/
@@ -68,7 +69,7 @@ public final class AllayBlockState implements com.dfsek.terra.api.block.state.Bl
public BlockState allayBlockState() { return allayBlockState; }
public boolean containsWater() { return containsWater; }
public boolean containsWater() { return containsWater; }
public JeBlockState jeBlockState() { return jeBlockState; }
}

View File

@@ -6,6 +6,7 @@ import org.allaymc.api.block.type.BlockType;
import com.dfsek.terra.allay.Mapping;
import com.dfsek.terra.api.block.state.BlockState;
/**
* @author daoge_cmd
*/

View File

@@ -10,18 +10,20 @@ import com.dfsek.terra.allay.Mapping;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.world.ServerWorld;
/**
* @author daoge_cmd
*/
public record AllayChunk(ServerWorld world, Chunk allayChunk) implements com.dfsek.terra.api.world.chunk.Chunk {
private static final org.allaymc.api.block.type.BlockState WATER = BlockTypes.WATER.ofState(BlockPropertyTypes.LIQUID_DEPTH.createValue(0));
private static final org.allaymc.api.block.type.BlockState WATER = BlockTypes.WATER.ofState(
BlockPropertyTypes.LIQUID_DEPTH.createValue(0));
@Override
public void setBlock(int x, int y, int z, BlockState data, boolean physics) {
AllayBlockState allayBlockState = (AllayBlockState) data;
allayChunk.setBlockState(x, y, z, allayBlockState.allayBlockState());
if (allayBlockState.containsWater() || allayChunk.getBlockState(x, y, z).getBlockType().hasBlockTag(BlockTags.WATER)) {
if(allayBlockState.containsWater() || allayChunk.getBlockState(x, y, z).getBlockType().hasBlockTag(BlockTags.WATER)) {
allayChunk.setBlockState(x, y, z, WATER, 1);
}
}

View File

@@ -6,18 +6,19 @@ import com.dfsek.terra.allay.Mapping;
import com.dfsek.terra.api.inventory.ItemStack;
import com.dfsek.terra.api.inventory.item.Enchantment;
/**
* @author daoge_cmd
*/
public record AllayEnchantment(EnchantmentType allayEnchantment) implements Enchantment {
@Override
public boolean canEnchantItem(ItemStack itemStack) {
return ((AllayItemStack)itemStack).allayItemStack().checkEnchantmentCompatibility(allayEnchantment);
return ((AllayItemStack) itemStack).allayItemStack().checkEnchantmentCompatibility(allayEnchantment);
}
@Override
public boolean conflictsWith(Enchantment other) {
return ((AllayEnchantment)other).allayEnchantment.isIncompatibleWith(allayEnchantment);
return ((AllayEnchantment) other).allayEnchantment.isIncompatibleWith(allayEnchantment);
}
@Override

View File

@@ -1,9 +1,11 @@
package com.dfsek.terra.allay.delegate;
import com.dfsek.seismic.type.vector.Vector3;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
/**
* NOTICE: Entity is not supported currently, and this is a fake implementation.
*

View File

@@ -10,6 +10,7 @@ import java.util.Map;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.dfsek.terra.api.inventory.item.ItemMeta;
/**
* @author daoge_cmd
*/
@@ -23,7 +24,7 @@ public record AllayItemMeta(ItemStack allayItemStack) implements ItemMeta {
@Override
public Map<Enchantment, Integer> getEnchantments() {
Map<Enchantment, Integer> results = new HashMap<>();
for (EnchantmentInstance allayEnchantmentInstance : allayItemStack.getEnchantments()) {
for(EnchantmentInstance allayEnchantmentInstance : allayItemStack.getEnchantments()) {
results.put(new AllayEnchantment(allayEnchantmentInstance.getType()), allayEnchantmentInstance.getLevel());
}
return results;

View File

@@ -6,10 +6,11 @@ import org.allaymc.api.item.enchantment.EnchantmentInstance;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.item.ItemMeta;
/**
* @author daoge_cmd
*/
public record AllayItemStack(ItemStack allayItemStack) implements com.dfsek.terra.api.inventory.ItemStack{
public record AllayItemStack(ItemStack allayItemStack) implements com.dfsek.terra.api.inventory.ItemStack {
@Override
public int getAmount() {
return allayItemStack.getCount();
@@ -34,7 +35,7 @@ public record AllayItemStack(ItemStack allayItemStack) implements com.dfsek.terr
public void setItemMeta(ItemMeta meta) {
ItemStack targetItem = ((AllayItemMeta) meta).allayItemStack();
allayItemStack.removeAllEnchantments();
for (EnchantmentInstance enchantment : targetItem.getEnchantments()) {
for(EnchantmentInstance enchantment : targetItem.getEnchantments()) {
allayItemStack.addEnchantment(enchantment.getType(), enchantment.getLevel());
}
allayItemStack.setLore(targetItem.getLore());

View File

@@ -10,12 +10,14 @@ import com.dfsek.terra.allay.Mapping;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
/**
* @author daoge_cmd
*/
public record AllayProtoChunk(UnsafeChunk allayChunk) implements ProtoChunk {
private static final org.allaymc.api.block.type.BlockState WATER = BlockTypes.WATER.ofState(BlockPropertyTypes.LIQUID_DEPTH.createValue(0));
private static final org.allaymc.api.block.type.BlockState WATER = BlockTypes.WATER.ofState(
BlockPropertyTypes.LIQUID_DEPTH.createValue(0));
@Override
public int getMaxHeight() {

View File

@@ -1,5 +1,6 @@
package com.dfsek.terra.allay.delegate;
import com.dfsek.seismic.type.vector.Vector3;
import org.allaymc.api.block.property.type.BlockPropertyTypes;
import org.allaymc.api.block.data.BlockTags;
import org.allaymc.api.block.type.BlockTypes;
@@ -11,18 +12,19 @@ import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
/**
* @author daoge_cmd
*/
public record AllayProtoWorld(AllayServerWorld allayServerWorld, OtherChunkAccessibleContext context) implements ProtoWorld {
private static final org.allaymc.api.block.type.BlockState WATER = BlockTypes.WATER.ofState(BlockPropertyTypes.LIQUID_DEPTH.createValue(0));
private static final org.allaymc.api.block.type.BlockState WATER = BlockTypes.WATER.ofState(
BlockPropertyTypes.LIQUID_DEPTH.createValue(0));
@Override
public int centerChunkX() {

View File

@@ -1,5 +1,6 @@
package com.dfsek.terra.allay.delegate;
import com.dfsek.seismic.type.vector.Vector3;
import org.allaymc.api.world.Dimension;
import com.dfsek.terra.allay.Mapping;
@@ -9,12 +10,12 @@ import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.Chunk;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
/**
* @author daoge_cmd
*/

View File

@@ -24,6 +24,7 @@ import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
import com.dfsek.terra.api.world.info.WorldProperties;
/**
* @author daoge_cmd
*/
@@ -86,6 +87,18 @@ public class AllayGeneratorWrapper implements GeneratorWrapper {
.build();
}
protected static ConfigPack getConfigPack(String packName) {
Optional<ConfigPack> byId = TerraAllayPlugin.PLATFORM.getConfigRegistry().getByID(packName);
return byId.orElseGet(
() -> TerraAllayPlugin.PLATFORM.getConfigRegistry().getByID(packName.toUpperCase(Locale.ENGLISH))
.orElseThrow(() -> new IllegalArgumentException("Cant find terra config pack named " + packName))
);
}
protected static ChunkGenerator createGenerator(ConfigPack configPack) {
return configPack.getGeneratorProvider().newInstance(configPack);
}
@Override
public ChunkGenerator getHandle() {
return chunkGenerator;
@@ -112,6 +125,7 @@ public class AllayGeneratorWrapper implements GeneratorWrapper {
return this.allayWorldGenerator;
}
protected class AllayNoiser implements Noiser {
@Override
@@ -140,6 +154,7 @@ public class AllayGeneratorWrapper implements GeneratorWrapper {
}
}
protected class AllayPopulator implements Populator {
@Override
@@ -155,16 +170,4 @@ public class AllayGeneratorWrapper implements GeneratorWrapper {
return true;
}
}
protected static ConfigPack getConfigPack(String packName) {
Optional<ConfigPack> byId = TerraAllayPlugin.PLATFORM.getConfigRegistry().getByID(packName);
return byId.orElseGet(
() -> TerraAllayPlugin.PLATFORM.getConfigRegistry().getByID(packName.toUpperCase(Locale.ENGLISH))
.orElseThrow(() -> new IllegalArgumentException("Cant find terra config pack named " + packName))
);
}
protected static ChunkGenerator createGenerator(ConfigPack configPack) {
return configPack.getGeneratorProvider().newInstance(configPack);
}
}

View File

@@ -9,6 +9,7 @@ import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.handle.WorldHandle;
/**
* @author daoge_cmd
*/
@@ -29,6 +30,7 @@ public class AllayWorldHandle implements WorldHandle {
public @NotNull EntityType getEntity(@NotNull String id) {
return new EntityType() {
private final Object fakeEntityType = new Object();
@Override
public Object getHandle() {
return fakeEntityType;

View File

@@ -8,7 +8,7 @@ dependencies {
paperweight.paperDevBundle(Versions.Bukkit.paperDevBundle)
shaded(project(":platforms:bukkit:common"))
shaded(project(":platforms:bukkit:nms:v1_21_8"))
shaded(project(":platforms:bukkit:nms:v1_21_9"))
shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper)
}
@@ -27,7 +27,7 @@ tasks {
}
runServer {
minecraftVersion(Versions.Bukkit.minecraft)
minecraftVersion(Versions.Bukkit.runPaperMinecraft)
dependsOn(shadowJar)
pluginJars(shadowJar.get().archiveFile)

View File

@@ -1,62 +0,0 @@
/*
* 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;
import org.bukkit.ChatColor;
import java.util.Optional;
import com.dfsek.terra.api.command.CommandSender;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.Player;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
public class BukkitCommandSender implements CommandSender {
private final org.bukkit.command.CommandSender delegate;
public BukkitCommandSender(org.bukkit.command.CommandSender delegate) {
this.delegate = delegate;
}
@Override
public void sendMessage(String message) {
delegate.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
}
@Override
public Optional<Entity> getEntity() {
if(delegate instanceof org.bukkit.entity.Entity entity) {
return Optional.of(BukkitAdapter.adapt(entity));
}
return Optional.empty();
}
@Override
public Optional<Player> getPlayer() {
if(delegate instanceof org.bukkit.entity.Player player) {
return Optional.of(BukkitAdapter.adapt(player));
}
return Optional.empty();
}
@Override
public org.bukkit.command.CommandSender getHandle() {
return delegate;
}
}

View File

@@ -17,11 +17,11 @@
package com.dfsek.terra.bukkit;
import com.dfsek.seismic.type.vector.Vector3;
import io.papermc.lib.PaperLib;
import org.bukkit.Location;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.bukkit.world.BukkitAdapter;

View File

@@ -17,11 +17,11 @@
package com.dfsek.terra.bukkit;
import com.dfsek.seismic.type.vector.Vector3;
import io.papermc.lib.PaperLib;
import org.bukkit.Location;
import com.dfsek.terra.api.entity.Player;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.bukkit.world.BukkitAdapter;

View File

@@ -0,0 +1,46 @@
package com.dfsek.terra.bukkit;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import org.bukkit.ChatColor;
import java.util.Optional;
import com.dfsek.terra.api.command.CommandSender;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.Player;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
public class CloudCommandSender implements CommandSender {
private final CommandSourceStack delegate;
public CloudCommandSender(CommandSourceStack delegate) {
this.delegate = delegate;
}
@Override
public void sendMessage(String message) {
delegate.getSender().sendMessage(ChatColor.translateAlternateColorCodes('&', message));
}
@Override
public Optional<Entity> getEntity() {
if(delegate instanceof org.bukkit.entity.Entity entity) {
return Optional.of(BukkitAdapter.adapt(entity));
}
return Optional.empty();
}
@Override
public Optional<Player> getPlayer() {
if(delegate instanceof org.bukkit.entity.Player player) {
return Optional.of(BukkitAdapter.adapt(player));
}
return Optional.empty();
}
@Override
public CommandSourceStack getHandle() {
return delegate;
}
}

View File

@@ -20,7 +20,6 @@ package com.dfsek.terra.bukkit;
import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import org.bukkit.Bukkit;
@@ -56,7 +55,7 @@ public class PlatformImpl extends AbstractPlatform {
public PlatformImpl(TerraBukkitPlugin plugin) {
generationThreads = getMoonriseGenerationThreadsWithReflection();
if (generationThreads == 0) {
if(generationThreads == 0) {
generationThreads = 1;
}
this.plugin = plugin;
@@ -70,8 +69,7 @@ public class PlatformImpl extends AbstractPlatform {
@Override
public boolean reload() {
getTerraConfig().load(this);
getRawConfigRegistry().clear();
boolean succeed = getRawConfigRegistry().loadAll(this);
boolean succeed = loadConfigPacks();
Bukkit.getWorlds().forEach(world -> {
if(world.getGenerator() instanceof BukkitChunkGeneratorWrapper wrapper) {

View File

@@ -23,10 +23,8 @@ import org.bukkit.Bukkit;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.java.JavaPlugin;
import org.incendo.cloud.SenderMapper;
import org.incendo.cloud.brigadier.CloudBrigadierManager;
import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.paper.LegacyPaperCommandManager;
import org.incendo.cloud.paper.PaperCommandManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -50,10 +48,8 @@ import com.dfsek.terra.bukkit.world.BukkitAdapter;
public class TerraBukkitPlugin extends JavaPlugin {
private static final Logger logger = LoggerFactory.getLogger(TerraBukkitPlugin.class);
private PlatformImpl platform;
private final Map<String, com.dfsek.terra.api.world.chunk.generation.ChunkGenerator> generatorMap = new HashMap<>();
private PlatformImpl platform;
private AsyncScheduler asyncScheduler = this.getServer().getAsyncScheduler();
private GlobalRegionScheduler globalRegionScheduler = this.getServer().getGlobalRegionScheduler();
@@ -73,7 +69,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
platform.getEventManager().callEvent(new PlatformInitializationEvent());
try {
LegacyPaperCommandManager<CommandSender> commandManager = getCommandSenderPaperCommandManager();
PaperCommandManager<CommandSender> commandManager = getCommandSenderPaperCommandManager();
platform.getEventManager().callEvent(new CommandRegistrationEvent(commandManager));
@@ -93,25 +89,15 @@ public class TerraBukkitPlugin extends JavaPlugin {
}
@NotNull
private LegacyPaperCommandManager<CommandSender> getCommandSenderPaperCommandManager() throws Exception {
// TODO: Update to PaperCommandManager
LegacyPaperCommandManager<CommandSender> commandManager = new LegacyPaperCommandManager<>(
this,
ExecutionCoordinator.simpleCoordinator(),
SenderMapper.create(
private PaperCommandManager<CommandSender> getCommandSenderPaperCommandManager() throws Exception {
PaperCommandManager<CommandSender> commandManager = PaperCommandManager.builder(SenderMapper.create(
BukkitAdapter::adapt,
BukkitAdapter::adapt
));
))
.executionCoordinator(ExecutionCoordinator.simpleCoordinator())
.buildOnEnable(this);
if(commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
commandManager.registerBrigadier();
final CloudBrigadierManager<?, ?> brigManager = commandManager.brigadierManager();
if(brigManager != null) {
brigManager.setNativeNumberSuggestions(false);
}
} else if(commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
commandManager.registerAsynchronousCompletions();
}
commandManager.brigadierManager().setNativeNumberSuggestions(false);
return commandManager;
}

View File

@@ -40,13 +40,6 @@ public class BukkitWorldHandle implements WorldHandle {
@Override
public synchronized @NotNull BlockState createBlockState(@NotNull String data) {
if(data.equals("minecraft:grass")) { //TODO: remove in 7.0
data = "minecraft:short_grass";
logger.warn(
"Translating minecraft:grass to minecraft:short_grass. In 1.20.3 minecraft:grass was renamed to minecraft:short_grass" +
". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
"version of Terra.");
}
org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData(
data); // somehow bukkit managed to make this not thread safe! :)
return BukkitBlockState.newInstance(bukkitData);

View File

@@ -1,8 +1,5 @@
package com.dfsek.terra.bukkit.hooks;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.registry.key.Keyed;
import org.mvplugins.multiverse.core.MultiverseCoreApi;
import org.mvplugins.multiverse.core.world.generators.GeneratorPlugin;
import org.mvplugins.multiverse.external.jetbrains.annotations.NotNull;
@@ -10,6 +7,10 @@ import org.mvplugins.multiverse.external.jetbrains.annotations.Nullable;
import java.util.Collection;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.registry.key.Keyed;
public final class MultiverseGeneratorPluginHook implements GeneratorPlugin {
private final Platform platform;
@@ -18,6 +19,11 @@ public final class MultiverseGeneratorPluginHook implements GeneratorPlugin {
this.platform = platform;
}
public static void register(Platform platform) {
MultiverseCoreApi.get().getGeneratorProvider()
.registerGeneratorPlugin(new MultiverseGeneratorPluginHook(platform));
}
@Override
public @NotNull Collection<String> suggestIds(@Nullable String s) {
return platform.getConfigRegistry().entries().stream()
@@ -45,9 +51,4 @@ public final class MultiverseGeneratorPluginHook implements GeneratorPlugin {
public @NotNull String getPluginName() {
return "Terra";
}
public static void register(Platform platform) {
MultiverseCoreApi.get().getGeneratorProvider()
.registerGeneratorPlugin(new MultiverseGeneratorPluginHook(platform));
}
}

View File

@@ -17,14 +17,6 @@
package com.dfsek.terra.bukkit.listeners;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
import com.dfsek.terra.bukkit.hooks.MultiverseGeneratorPluginHook;
import com.dfsek.terra.bukkit.world.BukkitBiomeInfo;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.entity.Entity;
@@ -41,6 +33,13 @@ import org.slf4j.LoggerFactory;
import java.util.List;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
import com.dfsek.terra.bukkit.hooks.MultiverseGeneratorPluginHook;
import com.dfsek.terra.bukkit.world.BukkitBiomeInfo;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
/**
* Listener for events on all implementations.
@@ -72,17 +71,17 @@ public class CommonListener implements Listener {
private void applyWolfVariant(Wolf wolf) {
// Doesn't apply if variant has already been applied
if (wolf.getVariant() != Variant.PALE) {
if(wolf.getVariant() != Variant.PALE) {
return;
}
World world = wolf.getWorld();
if (!(world.getGenerator() instanceof BukkitChunkGeneratorWrapper wrapper)) {
if(!(world.getGenerator() instanceof BukkitChunkGeneratorWrapper wrapper)) {
return;
}
ConfigPack pack = platform.getConfigRegistry().get(wrapper.getPack().getRegistryKey()).orElse(null);
if (pack == null) {
if(pack == null) {
return;
}
@@ -109,11 +108,11 @@ public class CommonListener implements Listener {
@EventHandler
public void onWolfSpawn(CreatureSpawnEvent event) {
if (!(event.getEntity() instanceof Wolf wolf)) {
if(!(event.getEntity() instanceof Wolf wolf)) {
return;
}
if (!WOLF_VARIANT_SPAWN_REASONS.contains(event.getSpawnReason())) {
if(!WOLF_VARIANT_SPAWN_REASONS.contains(event.getSpawnReason())) {
logger.debug("Ignoring wolf spawned with reason: " + event.getSpawnReason());
return;
}
@@ -123,12 +122,12 @@ public class CommonListener implements Listener {
@EventHandler
public void onChunkGenerate(ChunkLoadEvent event) {
if (!event.isNewChunk()) {
if(!event.isNewChunk()) {
return;
}
for (Entity entity : event.getChunk().getEntities()) {
if (entity instanceof Wolf wolf) {
for(Entity entity : event.getChunk().getEntities()) {
if(entity instanceof Wolf wolf) {
applyWolfVariant(wolf);
}
}

View File

@@ -1,11 +1,10 @@
package com.dfsek.terra.bukkit.nms;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import com.dfsek.terra.bukkit.util.VersionUtil;
@@ -17,7 +16,7 @@ public interface Initializer {
Logger logger = LoggerFactory.getLogger(Initializer.class);
PlatformImpl platform = constructPlatform(plugin);
if (platform == null) {
if(platform == null) {
logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS);
logger.error("This is usually due to running Terra on an unsupported Minecraft version.");
String bypassKey = "IKnowThereAreNoNMSBindingsFor" + NMS + "ButIWillProceedAnyway";
@@ -46,12 +45,7 @@ public interface Initializer {
private static PlatformImpl constructPlatform(TerraBukkitPlugin plugin) {
try {
String packageVersion = NMS;
if (NMS.equals("v1_21_5") || NMS.equals("v1_21_6") || NMS.equals("v1_21_7")) {
packageVersion = "v1_21_8";
}
Class<?> platformClass = Class.forName(TERRA_PACKAGE + "." + packageVersion + ".NMSPlatform");
Class<?> platformClass = Class.forName(TERRA_PACKAGE + "." + NMS + ".NMSPlatform");
try {
return (PlatformImpl) platformClass
.getConstructor(TerraBukkitPlugin.class)

View File

@@ -20,14 +20,6 @@ public class BukkitUtils {
}
public static EntityType getEntityType(String id) {
if(!id.contains(":")) { //TODO: remove in 7.0
String newid = "minecraft:" + id.toLowerCase();
;
logger.warn(
"Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" +
". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
"version of Terra.");
}
if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
String entityID = id.toUpperCase(Locale.ROOT).substring(10);

View File

@@ -18,6 +18,8 @@
package com.dfsek.terra.bukkit.world;
import com.dfsek.seismic.type.vector.Vector3;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -34,13 +36,12 @@ import com.dfsek.terra.api.command.CommandSender;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.inventory.ItemStack;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.chunk.Chunk;
import com.dfsek.terra.api.world.info.WorldProperties;
import com.dfsek.terra.bukkit.BukkitCommandSender;
import com.dfsek.terra.bukkit.BukkitEntity;
import com.dfsek.terra.bukkit.BukkitPlayer;
import com.dfsek.terra.bukkit.CloudCommandSender;
import com.dfsek.terra.bukkit.world.block.BukkitBlockTypeAndItem;
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack;
@@ -157,16 +158,16 @@ public final class BukkitAdapter {
return Vector3.of(vector.getX(), vector.getY(), vector.getZ());
}
public static CommandSender adapt(org.bukkit.command.CommandSender sender) {
return new BukkitCommandSender(sender);
public static CommandSender adapt(CommandSourceStack sender) {
return new CloudCommandSender(sender);
}
public static Entity adapt(org.bukkit.entity.Entity entity) {
return new BukkitEntity(entity);
}
public static org.bukkit.command.CommandSender adapt(CommandSender sender) {
return ((BukkitCommandSender) sender).getHandle();
public static CommandSourceStack adapt(CommandSender sender) {
return ((CloudCommandSender) sender).getHandle();
}
public static ServerWorld adapt(org.bukkit.World world) {

View File

@@ -1,8 +1,9 @@
package com.dfsek.terra.bukkit.world;
import com.dfsek.terra.api.properties.Properties;
import org.bukkit.NamespacedKey;
import com.dfsek.terra.api.properties.Properties;
public record BukkitBiomeInfo(NamespacedKey biomeKey) implements Properties {}
public record BukkitBiomeInfo(NamespacedKey biomeKey) implements Properties {
}

View File

@@ -1,9 +1,9 @@
package com.dfsek.terra.bukkit.world;
import com.dfsek.terra.api.world.info.WorldProperties;
import org.bukkit.generator.WorldInfo;
import com.dfsek.terra.api.world.info.WorldProperties;
public class BukkitWorldProperties implements WorldProperties {
private final WorldInfo delegate;

View File

@@ -17,13 +17,13 @@
package com.dfsek.terra.bukkit.world.block.state;
import com.dfsek.seismic.type.vector.Vector3;
import org.bukkit.block.Container;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.Sign;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;

View File

@@ -1,8 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.VanillaBiomeProperties;
import com.dfsek.terra.bukkit.world.BukkitBiomeInfo;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import net.minecraft.core.Holder;
import net.minecraft.core.Holder.Reference;
@@ -29,6 +25,8 @@ import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.VanillaBiomeProperties;
import com.dfsek.terra.bukkit.world.BukkitBiomeInfo;
import com.dfsek.terra.bukkit.world.BukkitPlatformBiome;
import com.dfsek.terra.registry.master.ConfigRegistry;
@@ -57,9 +55,11 @@ public class AwfulBukkitHacks {
VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class);
Biome platform = NMSBiomeInjector.createBiome(biomeRegistry.get(vanillaMinecraftKey).orElseThrow().value(), vanillaBiomeProperties);
Biome platform = NMSBiomeInjector.createBiome(biomeRegistry.get(vanillaMinecraftKey).orElseThrow().value(),
vanillaBiomeProperties);
ResourceLocation delegateMinecraftKey = ResourceLocation.fromNamespaceAndPath("terra", NMSBiomeInjector.createBiomeID(pack, key));
ResourceLocation delegateMinecraftKey = ResourceLocation.fromNamespaceAndPath("terra",
NMSBiomeInjector.createBiomeID(pack, key));
NamespacedKey delegateBukkitKey = NamespacedKey.fromString(delegateMinecraftKey.toString());
ResourceKey<Biome> delegateKey = ResourceKey.create(Registries.BIOME, delegateMinecraftKey);
@@ -123,39 +123,42 @@ public class AwfulBukkitHacks {
Map<Holder.Reference<T>, List<TagKey<T>>> map = new IdentityHashMap<>();
Reflection.MAPPED_REGISTRY.getByKey(registry).values().forEach(entry -> map.put(entry, new ArrayList<>()));
tagEntries.forEach((tag, entries) -> {
for (Holder<T> holder : entries) {
// if (!holder.canSerializeIn(registry.asLookup())) {
// throw new IllegalStateException("Can't create named set " + tag + " containing value " + holder + " from outside registry " + this);
// }
for(Holder<T> holder : entries) {
// if (!holder.canSerializeIn(registry.asLookup())) {
// throw new IllegalStateException("Can't create named set " + tag + " containing value " + holder + "
// from outside registry " + this);
// }
if (!(holder instanceof Holder.Reference<T> reference)) {
if(!(holder instanceof Holder.Reference<T> reference)) {
throw new IllegalStateException("Found direct holder " + holder + " value in tag " + tag);
}
map.get(reference).add(tag);
}
});
// Set<TagKey<T>> set = Sets.difference(registry.tags.keySet(), tagEntries.keySet());
// if (!set.isEmpty()) {
// LOGGER.warn(
// "Not all defined tags for registry {} are present in data pack: {}",
// registry.key(),
// set.stream().map(tag -> tag.location().toString()).sorted().collect(Collectors.joining(", "))
// );
// }
// Set<TagKey<T>> set = Sets.difference(registry.tags.keySet(), tagEntries.keySet());
// if (!set.isEmpty()) {
// LOGGER.warn(
// "Not all defined tags for registry {} are present in data pack: {}",
// registry.key(),
// set.stream().map(tag -> tag.location().toString()).sorted().collect(Collectors.joining(", "))
// );
// }
Map<TagKey<T>, HolderSet.Named<T>> map2 = new IdentityHashMap<>(registry.getTags().collect(Collectors.toMap(
Named::key,
(named) -> named
)));
tagEntries.forEach((tag, entries) -> Reflection.HOLDER_SET.invokeBind(map2.computeIfAbsent(tag, key -> Reflection.MAPPED_REGISTRY.invokeCreateTag(registry, key)), entries));
tagEntries.forEach((tag, entries) -> Reflection.HOLDER_SET.invokeBind(
map2.computeIfAbsent(tag, key -> Reflection.MAPPED_REGISTRY.invokeCreateTag(registry, key)), entries));
map.forEach(Reflection.HOLDER_REFERENCE::invokeBindTags);
Reflection.MAPPED_REGISTRY.setAllTags(registry, Reflection.MAPPED_REGISTRY_TAG_SET.invokeFromMap(map2));
}
private static void resetTags(MappedRegistry<?> registry) {
registry.getTags().forEach(entryList -> Reflection.HOLDER_SET.invokeBind(entryList, List.of()));
Reflection.MAPPED_REGISTRY.getByKey(registry).values().forEach(entry -> Reflection.HOLDER_REFERENCE.invokeBindTags(entry, Set.of()));
Reflection.MAPPED_REGISTRY.getByKey(registry).values().forEach(
entry -> Reflection.HOLDER_REFERENCE.invokeBindTags(entry, Set.of()));
}
}

View File

@@ -1,11 +1,11 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.bukkit.BukkitAddon;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.VanillaBiomeProperties;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.VanillaBiomeProperties;
public class NMSAddon extends BukkitAddon {

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
@@ -12,7 +12,7 @@ import java.util.Objects;
import java.util.Optional;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.VanillaBiomeProperties;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.VanillaBiomeProperties;
public class NMSBiomeInjector {
@@ -33,7 +33,8 @@ public class NMSBiomeInjector {
.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor()))
.waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor()))
.skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor()))
.grassColorModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(), vanilla.getSpecialEffects().getGrassColorModifier()))
.grassColorModifier(Objects.requireNonNullElse(vanillaBiomeProperties.getGrassColorModifier(),
vanilla.getSpecialEffects().getGrassColorModifier()))
.backgroundMusicVolume(Objects.requireNonNullElse(vanillaBiomeProperties.getMusicVolume(), vanilla.getBackgroundMusicVolume()));
if(vanillaBiomeProperties.getGrassColor() == null) {
@@ -84,7 +85,8 @@ public class NMSBiomeInjector {
builder.downfall(Objects.requireNonNullElse(vanillaBiomeProperties.getDownfall(), vanilla.climateSettings.downfall()));
builder.temperatureAdjustment(Objects.requireNonNullElse(vanillaBiomeProperties.getTemperatureModifier(), vanilla.climateSettings.temperatureModifier()));
builder.temperatureAdjustment(
Objects.requireNonNullElse(vanillaBiomeProperties.getTemperatureModifier(), vanilla.climateSettings.temperatureModifier()));
builder.mobSpawnSettings(Objects.requireNonNullElse(vanillaBiomeProperties.getSpawnSettings(), vanilla.getMobSettings()));

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.Holder;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;

View File

@@ -1,34 +1,7 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.terra.addon.InternalAddon;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.BiomeAdditionsSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.BiomeMoodSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.BiomeParticleConfigTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.EntityTypeTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.MusicSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.SoundEventTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.SpawnCostConfig;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.SpawnEntryConfig;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.SpawnSettingsTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.SpawnTypeConfig;
import com.dfsek.terra.bukkit.nms.v1_21_8.config.VillagerTypeTemplate;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.Music;
import net.minecraft.sounds.SoundEvent;
@@ -47,6 +20,25 @@ import org.bukkit.Bukkit;
import java.util.List;
import java.util.Locale;
import com.dfsek.terra.addon.InternalAddon;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.BiomeAdditionsSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.BiomeMoodSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.BiomeParticleConfigTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.EntityTypeTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.MusicSoundTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.SoundEventTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.SpawnCostConfig;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.SpawnEntryConfig;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.SpawnSettingsTemplate;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.SpawnTypeConfig;
import com.dfsek.terra.bukkit.nms.v1_21_9.config.VillagerTypeTemplate;
public class NMSPlatform extends PlatformImpl {
@@ -74,7 +66,7 @@ public class NMSPlatform extends PlatformImpl {
.registerLoader(GrassColorModifier.class,
(type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase(
Locale.ROOT)))
.registerLoader(MobCategory.class, (type, o, loader, depthTracker) -> MobCategory.valueOf((String) o))
.registerLoader(MobCategory.class, (type, o, loader, depthTracker) -> MobCategory.valueOf((String) o))
.registerLoader(AmbientParticleSettings.class, BiomeParticleConfigTemplate::new)
.registerLoader(SoundEvent.class, SoundEventTemplate::new)
.registerLoader(AmbientMoodSettings.class, BiomeMoodSoundTemplate::new)

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import net.minecraft.world.level.LevelHeightAccessor;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import net.minecraft.core.Holder;
import net.minecraft.core.Holder.Reference;
@@ -71,6 +71,7 @@ public class Reflection {
<T> HolderSet.Named<T> invokeCreateTag(MappedRegistry<T> instance, TagKey<T> tag);
}
@Proxies(className = "net.minecraft.core.MappedRegistry$TagSet")
public interface MappedRegistryTagSetProxy {
@MethodName("fromMap")
@@ -95,6 +96,7 @@ public class Reflection {
<T> void invokeBindTags(Reference<T> instance, Collection<TagKey<T>> tags);
}
@Proxies(ChunkMap.class)
public interface ChunkMapProxy {
@FieldGetter("worldGenContext")
@@ -104,12 +106,14 @@ public class Reflection {
void setWorldGenContext(ChunkMap instance, WorldGenContext worldGenContext);
}
@Proxies(Holder.Reference.class)
public interface HolderReferenceProxy {
@MethodName("bindTags")
<T> void invokeBindTags(Holder.Reference<T> instance, Collection<TagKey<T>> tags);
}
@Proxies(HolderSet.Named.class)
public interface HolderSetNamedProxy {
@MethodName("bind")
@@ -119,12 +123,14 @@ public class Reflection {
<T> List<Holder<T>> invokeContents(HolderSet.Named<T> instance);
}
@Proxies(Biome.class)
public interface BiomeProxy {
@MethodName("getGrassColorFromTexture")
int invokeGrassColorFromTexture(Biome instance);
}
@Proxies(VillagerType.class)
public interface VillagerTypeProxy {
@Static

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8;
package com.dfsek.terra.bukkit.nms.v1_21_9;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
@@ -12,11 +12,11 @@ public class BiomeAdditionsSoundTemplate implements ObjectTemplate<AmbientAdditi
@Value("sound")
@Default
private SoundEvent sound = null;
@Value("sound-chance")
@Default
private Double soundChance = null;
@Override
public AmbientAdditionsSettings get() {
if(sound == null || soundChance == null) {

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
@@ -12,25 +12,26 @@ public class BiomeMoodSoundTemplate implements ObjectTemplate<AmbientMoodSetting
@Value("sound")
@Default
private SoundEvent sound = null;
@Value("cultivation-ticks")
@Default
private Integer soundCultivationTicks = null;
@Value("spawn-range")
@Default
private Integer soundSpawnRange = null;
@Value("extra-distance")
@Default
private Double soundExtraDistance = null;
@Override
public AmbientMoodSettings get() {
if(sound == null || soundCultivationTicks == null || soundSpawnRange == null || soundExtraDistance == null) {
return null;
} else {
return new AmbientMoodSettings(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), soundCultivationTicks, soundSpawnRange, soundExtraDistance);
return new AmbientMoodSettings(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), soundCultivationTicks, soundSpawnRange,
soundExtraDistance);
}
}
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
@@ -17,18 +17,17 @@ public class BiomeParticleConfigTemplate implements ObjectTemplate<AmbientPartic
@Value("particle")
@Default
private String particle = null;
@Value("probability")
@Default
private Float probability = 0.1f;
@Override
public AmbientParticleSettings get() {
if(particle == null) {
return null;
}
try {
return new AmbientParticleSettings(ParticleArgument.readParticle(new StringReader(particle),
HolderLookup.Provider.create(Stream.of(BuiltInRegistries.PARTICLE_TYPE))), probability);

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
@@ -12,7 +12,7 @@ public class EntityTypeTemplate implements ObjectTemplate<EntityType<?>> {
@Value("id")
@Default
private ResourceLocation id = null;
@Override
public EntityType<?> get() {
return BuiltInRegistries.ENTITY_TYPE.get(id).orElseThrow().value();

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
@@ -12,19 +12,19 @@ public class MusicSoundTemplate implements ObjectTemplate<Music> {
@Value("sound")
@Default
private SoundEvent sound = null;
@Value("min-delay")
@Default
private Integer minDelay = null;
@Value("max-delay")
@Default
private Integer maxDelay = null;
@Value("replace-current-music")
@Default
private Boolean replaceCurrentMusic = null;
@Override
public Music get() {
if(sound == null || minDelay == null || maxDelay == null || replaceCurrentMusic == null) {

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
@@ -11,11 +11,11 @@ public class SoundEventTemplate implements ObjectTemplate<SoundEvent> {
@Value("id")
@Default
private ResourceLocation id = null;
@Value("distance-to-travel")
@Default
private Float distanceToTravel = null;
@Override
public SoundEvent get() {
if(id == null) {

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
@@ -10,27 +10,27 @@ public class SpawnCostConfig implements ObjectTemplate<SpawnCostConfig> {
@Value("type")
@Default
private EntityType<?> type = null;
@Value("mass")
@Default
private Double mass = null;
@Value("gravity")
@Default
private Double gravity = null;
public EntityType<?> getType() {
return type;
}
public Double getMass() {
return mass;
}
public Double getGravity() {
return gravity;
}
@Override
public SpawnCostConfig get() {
return this;

View File

@@ -1,8 +1,11 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import com.dfsek.terra.api.util.range.Range;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
@@ -11,27 +14,23 @@ public class SpawnEntryConfig implements ObjectTemplate<SpawnEntryConfig> {
@Value("type")
@Default
private EntityType<?> type = null;
@Value("weight")
@Default
private Integer weight = null;
@Value("min-group-size")
@Value("group-size")
@Default
private Integer minGroupSize = null;
@Value("max-group-size")
@Default
private Integer maxGroupSize = null;
private Range groupSize = null;
public Integer getWeight() {
return weight;
}
public SpawnerData getSpawnEntry() {
return new SpawnerData(type, minGroupSize, maxGroupSize);
return new SpawnerData(type, groupSize.getMin(), groupSize.getMax());
}
@Override
public SpawnEntryConfig get() {
return this;

View File

@@ -1,14 +1,15 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import java.util.List;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.level.biome.MobSpawnSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
public class SpawnSettingsTemplate implements ObjectTemplate<MobSpawnSettings> {
@@ -18,15 +19,15 @@ public class SpawnSettingsTemplate implements ObjectTemplate<MobSpawnSettings> {
@Value("spawns")
@Default
private List<SpawnTypeConfig> spawns = null;
@Value("costs")
@Default
private List<SpawnCostConfig> costs = null;
@Value("probability")
@Default
private Float probability = null;
@Override
public MobSpawnSettings get() {
MobSpawnSettings.Builder builder = new MobSpawnSettings.Builder();
@@ -42,7 +43,7 @@ public class SpawnSettingsTemplate implements ObjectTemplate<MobSpawnSettings> {
if(probability != null) {
builder.creatureGenerationProbability(probability);
}
return builder.build();
}
}

View File

@@ -1,11 +1,12 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import java.util.List;
import net.minecraft.world.entity.MobCategory;
import java.util.List;
public class SpawnTypeConfig implements ObjectTemplate<SpawnTypeConfig> {
@Value("group")

View File

@@ -1,11 +1,8 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.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;
import net.minecraft.resources.ResourceKey;
import net.minecraft.sounds.Music;
import net.minecraft.sounds.SoundEvent;
@@ -17,6 +14,8 @@ import net.minecraft.world.level.biome.Biome.TemperatureModifier;
import net.minecraft.world.level.biome.BiomeSpecialEffects.GrassColorModifier;
import net.minecraft.world.level.biome.MobSpawnSettings;
import com.dfsek.terra.api.properties.Properties;
public class VanillaBiomeProperties implements ConfigTemplate, Properties {
@Value("colors.grass")

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21_8.config;
package com.dfsek.terra.bukkit.nms.v1_21_9.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
@@ -13,7 +13,7 @@ public class VillagerTypeTemplate implements ObjectTemplate<ResourceKey<Villager
@Value("id")
@Default
private ResourceLocation id = null;
@Override
public ResourceKey<VillagerType> get() {
return ResourceKey.create(BuiltInRegistries.VILLAGER_TYPE.key(), id);

View File

@@ -1,44 +1,48 @@
package com.dfsek.terra.cli;
import com.dfsek.seismic.type.vector.Vector2Int;
import net.querz.mca.MCAUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import java.io.IOException;
import java.util.concurrent.Callable;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.api.util.vector.Vector2Int;
import com.dfsek.terra.cli.world.CLIWorld;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
//TODO auto pull in version
@Command(name = "TerraCLI", mixinStandardHelpOptions = true, version = "6.6.0",
description = "Generates a Terra World and saves it in minecraft region format.")
public final class TerraCLI implements Callable<Integer> {
@Option(names = { "-s", "--size"}, description = "Number of regions to generate.")
@Option(names = { "-s", "--size" }, description = "Number of regions to generate.")
private int size = 2;
@Option(names = { "-p", "--pack"}, description = "Config pack to use.")
@Option(names = { "-p", "--pack" }, description = "Config pack to use.")
private String pack = "OVERWORLD";
@Option(names = { "--seed"}, description = "Seed for world generation.")
@Option(names = { "--seed" }, description = "Seed for world generation.")
private long seed = 0;
@Option(names = { "--max-height"}, description = "Maximum height of the world.")
@Option(names = { "--max-height" }, description = "Maximum height of the world.")
private int maxHeight = 320;
@Option(names = { "--min-height"}, description = "Minimum height of the world.")
@Option(names = { "--min-height" }, description = "Minimum height of the world.")
private int minHeight = -64;
@Option(names = { "--no-save"}, description = "Don't save the world to disk.")
@Option(names = { "--no-save" }, description = "Don't save the world to disk.")
private boolean noSave = false;
public static void main(String... args) {
int exitCode = new CommandLine(new TerraCLI()).execute(args);
System.exit(exitCode);
}
@Override
public Integer call() {
Logger LOGGER = LoggerFactory.getLogger(TerraCLI.class);
@@ -70,9 +74,4 @@ public final class TerraCLI implements Callable<Integer> {
LOGGER.info("Done.");
return 0;
}
public static void main(String... args) {
int exitCode = new CommandLine(new TerraCLI()).execute(args);
System.exit(exitCode);
}
}

View File

@@ -1,5 +1,7 @@
package com.dfsek.terra.cli.world;
import com.dfsek.seismic.type.vector.Vector2Int;
import com.dfsek.seismic.type.vector.Vector3;
import com.google.common.collect.Streams;
import net.querz.mca.MCAFile;
import org.slf4j.Logger;
@@ -22,8 +24,6 @@ import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.util.vector.Vector2Int;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
@@ -87,7 +87,7 @@ public class CLIWorld implements ServerWorld, NBTSerializable<Stream<Pair<Vector
try {
int num = amount.getAndIncrement();
CLIChunk chunk;
if (!noSave) {
if(!noSave) {
chunk = getChunkAt(finalX, finalZ);
} else {
chunk = new CLIChunk(Math.floorMod(finalX, 32), Math.floorMod(finalZ, 32), this);

View File

@@ -35,7 +35,7 @@
"depends": {
"fabricloader": ">=0.16.10",
"java": ">=21",
"minecraft": "1.21.7",
"minecraft": "1.21.9",
"fabric": "*"
}
}

View File

@@ -20,6 +20,9 @@ package com.dfsek.terra.forge;
import ca.solostudios.strata.Versions;
import ca.solostudios.strata.parser.tokenizer.ParseException;
import ca.solostudios.strata.version.Version;
import com.dfsek.terra.registry.master.ConfigRegistry.PackLoadFailuresException;
import net.minecraft.MinecraftVersion;
import net.minecraft.registry.Registry;
import net.minecraft.server.MinecraftServer;
@@ -34,6 +37,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -62,8 +66,7 @@ public class ForgePlatform extends ModPlatform {
@Override
public boolean reload() {
getTerraConfig().load(this);
getRawConfigRegistry().clear();
boolean succeed = getRawConfigRegistry().loadAll(this);
boolean succeed = loadConfigPacks();
MinecraftServer server = getServer();

View File

@@ -1,8 +1,8 @@
package com.dfsek.terra.forge.mixin.lifecycle;
import net.minecraft.registry.RegistryEntryLookup;
import net.minecraft.util.math.noise.DoublePerlinNoiseSampler.NoiseParameters;
import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler;
import net.minecraft.util.math.noise.DoublePerlinSampler.NoiseParameters;
import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiSampler;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
import net.minecraft.world.gen.noise.NoiseConfig;
import org.spongepowered.asm.mixin.Final;
@@ -22,13 +22,13 @@ import com.dfsek.terra.mod.util.SeedHack;
public class NoiseConfigMixin {
@Shadow
@Final
private MultiNoiseSampler multiNoiseSampler;
private MultiSampler multiSampler;
@Inject(method = "<init>(Lnet/minecraft/world/gen/chunk/ChunkGeneratorSettings;Lnet/minecraft/registry/RegistryEntryLookup;J)V",
at = @At("TAIL"))
private void mapMultiNoise(ChunkGeneratorSettings chunkGeneratorSettings, RegistryEntryLookup<NoiseParameters> noiseParametersLookup,
long seed,
CallbackInfo ci) {
SeedHack.register(multiNoiseSampler, seed);
SeedHack.register(multiSampler, seed);
}
}

View File

@@ -83,7 +83,8 @@ public final class BiomeUtil {
Objects.requireNonNullElse(vanillaBiomeProperties.getVillagerType(),
villagerMap.getOrDefault(vanilla.getKey().orElseThrow(), VillagerType.PLAINS)));
com.dfsek.terra.mod.util.BiomeUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getKey().orElseThrow().getValue(), i -> new ArrayList<>()).add(
com.dfsek.terra.mod.util.BiomeUtil.TERRA_BIOME_MAP.computeIfAbsent(vanilla.getKey().orElseThrow().getValue(),
i -> new ArrayList<>()).add(
identifier);
}
}

View File

@@ -16,22 +16,33 @@ import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
import com.dfsek.terra.minestom.world.TerraMinestomWorldBuilder;
public class TerraMinestomExample {
private static final Logger logger = LoggerFactory.getLogger(TerraMinestomExample.class);
private final MinecraftServer server = MinecraftServer.init();
private final TerraMinestomPlatform platform = new TerraMinestomPlatform();
private Instance instance;
private TerraMinestomWorld world;
public static void main(String[] args) {
TerraMinestomExample example = new TerraMinestomExample();
example.createNewInstance();
example.attachTerra();
example.preloadWorldAndMeasure();
example.addScheduler();
example.addListeners();
example.addCommands();
example.bind();
}
public void createNewInstance() {
instance = MinecraftServer.getInstanceManager().createInstanceContainer();
instance.setChunkSupplier(LightingChunk::new);
}
public void attachTerra() {
world = TerraMinestomWorldBuilder.from(instance)
world = platform.worldBuilder(instance)
.defaultPack()
.attach();
}
@@ -102,16 +113,6 @@ public class TerraMinestomExample {
server.start("localhost", 25565);
}
public static void main(String[] args) {
TerraMinestomExample example = new TerraMinestomExample();
example.createNewInstance();
example.attachTerra();
example.preloadWorldAndMeasure();
example.addScheduler();
example.addListeners();
example.addCommands();
example.bind();
}
public class RegenerateCommand extends Command {
public RegenerateCommand() {
@@ -121,12 +122,16 @@ public class TerraMinestomExample {
private void regenerate() {
instance.sendMessage(Component.text("Regenerating world"));
Instance oldInstance = instance;
platform.reload();
createNewInstance();
attachTerra();
preloadWorldAndMeasure();
MinecraftServer.getConnectionManager().getOnlinePlayers().forEach(player ->
player.setInstance(instance, new Pos(0, 100, 0))
);
MinecraftServer.getInstanceManager().unregisterInstance(oldInstance);
}
}
}

View File

@@ -1,7 +1,6 @@
package com.dfsek.terra.minestom;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.seismic.type.vector.Vector3;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;

View File

@@ -1,94 +0,0 @@
package com.dfsek.terra.minestom;
import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.loader.type.TypeLoader;
import com.dfsek.terra.AbstractPlatform;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import com.dfsek.terra.minestom.biome.MinestomBiomeLoader;
import com.dfsek.terra.minestom.entity.MinestomEntityType;
import com.dfsek.terra.minestom.item.MinestomItemHandle;
import com.dfsek.terra.minestom.world.MinestomChunkGeneratorWrapper;
import com.dfsek.terra.minestom.world.MinestomWorldHandle;
import net.minestom.server.MinecraftServer;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
public final class MinestomPlatform extends AbstractPlatform {
private static final Logger LOGGER = LoggerFactory.getLogger(MinestomPlatform.class);
private static MinestomPlatform INSTANCE = null;
private final MinestomWorldHandle worldHandle = new MinestomWorldHandle();
private final MinestomItemHandle itemHandle = new MinestomItemHandle();
private MinestomPlatform() {
load();
getEventManager().callEvent(new PlatformInitializationEvent());
}
@Override
public void register(TypeRegistry registry) {
super.register(registry);
registry
.registerLoader(PlatformBiome.class, new MinestomBiomeLoader())
.registerLoader(EntityType.class, (TypeLoader<EntityType>) (annotatedType, o, configLoader, depthTracker) -> new MinestomEntityType((String) o))
.registerLoader(BlockState.class, (TypeLoader<BlockState>) (annotatedType, o, configLoader, depthTracker) -> worldHandle.createBlockState((String) o));
}
@Override
public boolean reload() {
getTerraConfig().load(this);
getRawConfigRegistry().clear();
boolean succeed = getRawConfigRegistry().loadAll(this);
MinecraftServer.getInstanceManager().getInstances().forEach(world -> {
if(world.generator() instanceof MinestomChunkGeneratorWrapper wrapper) {
getConfigRegistry().get(wrapper.getPack().getRegistryKey()).ifPresent(pack -> {
wrapper.setPack(pack);
LOGGER.info("Replaced pack in chunk generator for instance {}", world.getUuid());
});
}
});
return succeed;
}
@Override
public @NotNull WorldHandle getWorldHandle() {
return worldHandle;
}
@Override
public @NotNull ItemHandle getItemHandle() {
return itemHandle;
}
@Override
public @NotNull String platformName() {
return "Minestom";
}
@Override
public @NotNull File getDataFolder() {
String pathName = System.getProperty("terra.datafolder");
if (pathName == null) pathName = "./terra/";
File file = new File(pathName);
if(!file.exists()) file.mkdirs();
return file;
}
public static MinestomPlatform getInstance() {
if(INSTANCE == null) {
INSTANCE = new MinestomPlatform();
}
return INSTANCE;
}
}

View File

@@ -0,0 +1,134 @@
package com.dfsek.terra.minestom;
import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.loader.type.TypeLoader;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.util.RGBLike;
import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.Instance;
import net.minestom.server.sound.SoundEvent;
import net.minestom.server.world.biome.BiomeEffects;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.dfsek.terra.AbstractPlatform;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import com.dfsek.terra.minestom.addon.MinestomAddon;
import com.dfsek.terra.minestom.api.TerraMinestomWorldBuilder;
import com.dfsek.terra.minestom.biome.MinestomBiomeLoader;
import com.dfsek.terra.minestom.config.BiomeAdditionsSoundTemplate;
import com.dfsek.terra.minestom.config.BiomeMoodSoundTemplate;
import com.dfsek.terra.minestom.config.BiomeParticleConfigTemplate;
import com.dfsek.terra.minestom.config.KeyLoader;
import com.dfsek.terra.minestom.config.RGBLikeLoader;
import com.dfsek.terra.minestom.config.SoundEventTemplate;
import com.dfsek.terra.minestom.entity.MinestomEntityType;
import com.dfsek.terra.minestom.item.MinestomItemHandle;
import com.dfsek.terra.minestom.world.MinestomChunkGeneratorWrapper;
import com.dfsek.terra.minestom.world.MinestomWorldHandle;
public final class TerraMinestomPlatform extends AbstractPlatform {
private static final Logger LOGGER = LoggerFactory.getLogger(TerraMinestomPlatform.class);
private final WorldHandle worldHandle;
private final ItemHandle itemHandle;
private final TypeLoader<PlatformBiome> biomeTypeLoader;
private final ArrayList<BaseAddon> platformAddons = new ArrayList<>(List.of(new MinestomAddon(this)));
public TerraMinestomPlatform(WorldHandle worldHandle, ItemHandle itemHandle, TypeLoader<PlatformBiome> biomeTypeLoader,
BaseAddon... extraAddons) {
this.worldHandle = worldHandle;
this.itemHandle = itemHandle;
this.biomeTypeLoader = biomeTypeLoader;
this.platformAddons.addAll(List.of(extraAddons));
load();
getEventManager().callEvent(new PlatformInitializationEvent());
}
public TerraMinestomPlatform() {
this(new MinestomWorldHandle(), new MinestomItemHandle(), new MinestomBiomeLoader());
}
@Override
public void register(TypeRegistry registry) {
super.register(registry);
registry
.registerLoader(PlatformBiome.class, biomeTypeLoader)
.registerLoader(RGBLike.class, new RGBLikeLoader())
.registerLoader(Key.class, new KeyLoader())
.registerLoader(EntityType.class,
(TypeLoader<EntityType>) (annotatedType, o, configLoader, depthTracker) -> new MinestomEntityType((String) o))
.registerLoader(BlockState.class,
(TypeLoader<BlockState>) (annotatedType, o, configLoader, depthTracker) -> worldHandle.createBlockState((String) o))
.registerLoader(BiomeEffects.Particle.class, BiomeParticleConfigTemplate::new)
.registerLoader(BiomeEffects.MoodSound.class, BiomeMoodSoundTemplate::new)
.registerLoader(BiomeEffects.AdditionsSound.class, BiomeAdditionsSoundTemplate::new)
.registerLoader(SoundEvent.class, SoundEventTemplate::new);
}
@Override
public boolean reload() {
getTerraConfig().load(this);
boolean succeed = loadConfigPacks();
MinecraftServer.getInstanceManager().getInstances().forEach(world -> {
if(world.generator() instanceof MinestomChunkGeneratorWrapper wrapper) {
getConfigRegistry().get(wrapper.getPack().getRegistryKey()).ifPresent(pack -> {
wrapper.setPack(pack);
LOGGER.info("Replaced pack in chunk generator for instance {}", world.getUuid());
});
}
});
return succeed;
}
@Override
public @NotNull WorldHandle getWorldHandle() {
return worldHandle;
}
@Override
public @NotNull ItemHandle getItemHandle() {
return itemHandle;
}
@Override
public @NotNull String platformName() {
return "Minestom";
}
@Override
public @NotNull File getDataFolder() {
String pathName = System.getProperty("terra.datafolder");
if(pathName == null) pathName = "./terra/";
File file = new File(pathName);
if(!file.exists()) file.mkdirs();
return file;
}
@Override
protected Iterable<BaseAddon> platformAddon() {
return platformAddons;
}
public TerraMinestomWorldBuilder worldBuilder(Instance instance) {
return new TerraMinestomWorldBuilder(this, instance);
}
public TerraMinestomWorldBuilder worldBuilder() {
return new TerraMinestomWorldBuilder(this, MinecraftServer.getInstanceManager().createInstanceContainer());
}
}

View File

@@ -0,0 +1,44 @@
package com.dfsek.terra.minestom.addon;
import ca.solostudios.strata.Versions;
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.functional.FunctionalEventHandler;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.minestom.TerraMinestomPlatform;
import com.dfsek.terra.minestom.config.VanillaBiomeProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MinestomAddon implements BaseAddon {
private static final Version VERSION = Versions.getVersion(1, 0, 0);
private static final Logger logger = LoggerFactory.getLogger(MinestomAddon.class);
private final TerraMinestomPlatform minestomPlatform;
public MinestomAddon(TerraMinestomPlatform minestomPlatform) {
this.minestomPlatform = minestomPlatform;
}
@Override
public void initialize() {
minestomPlatform.getEventManager()
.getHandler(FunctionalEventHandler.class)
.register(this, ConfigurationLoadEvent.class)
.then(event -> {
if(event.is(Biome.class)) {
event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties()));
}
})
.global();
}
@Override
public Version getVersion() { return VERSION; }
@Override
public String getID() { return "terra-minestom"; }
}

View File

@@ -0,0 +1,15 @@
package com.dfsek.terra.minestom.api;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.minestom.biome.UserDefinedBiome;
/**
* BiomeFactory serves as a contract for creating custom user-defined biomes in Terra.
* Implementations of this interface are responsible for defining the logic to convert
* configured biomes and source biome data into instances of UserDefinedBiome.
*/
public interface BiomeFactory {
UserDefinedBiome create(ConfigPack pack, Biome source);
}

View File

@@ -1,15 +1,15 @@
package com.dfsek.terra.minestom.api;
import com.dfsek.terra.api.block.entity.BlockEntity;
import net.minestom.server.coordinate.BlockVec;
import org.jetbrains.annotations.Nullable;
import com.dfsek.terra.api.block.entity.BlockEntity;
/**
* Represents a factory interface for creating instances of BlockEntity
* at a specified BlockVec position. This is not implemented directly because
* Minestom does not define a way to build block entities out of the box.
* at a specified BlockVec position. For more fine-grained control, users
* may supply their own version of this interface.
*/
public interface BlockEntityFactory {
@Nullable BlockEntity createBlockEntity(BlockVec position);

View File

@@ -1,55 +1,47 @@
package com.dfsek.terra.minestom.world;
package com.dfsek.terra.minestom.api;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.minestom.MinestomPlatform;
import com.dfsek.terra.minestom.api.BlockEntityFactory;
import com.dfsek.terra.minestom.api.EntityFactory;
import com.dfsek.terra.minestom.block.DefaultBlockEntityFactory;
import com.dfsek.terra.minestom.entity.DefaultEntityFactory;
import net.minestom.server.MinecraftServer;
import net.minestom.server.instance.Instance;
import java.util.Random;
import java.util.function.Function;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.minestom.TerraMinestomPlatform;
import com.dfsek.terra.minestom.biome.MinestomUserDefinedBiomeFactory;
import com.dfsek.terra.minestom.block.DefaultBlockEntityFactory;
import com.dfsek.terra.minestom.entity.DefaultEntityFactory;
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
public class TerraMinestomWorldBuilder {
private final TerraMinestomPlatform platform;
private final Instance instance;
private ConfigPack pack;
private long seed = new Random().nextLong();
private EntityFactory entityFactory = new DefaultEntityFactory();
private BlockEntityFactory blockEntityFactory;
private BiomeFactory biomeFactory = new MinestomUserDefinedBiomeFactory();
private TerraMinestomWorldBuilder(Instance instance) {
public TerraMinestomWorldBuilder(TerraMinestomPlatform platform, Instance instance) {
this.platform = platform;
this.instance = instance;
this.blockEntityFactory = new DefaultBlockEntityFactory(instance);
}
public static TerraMinestomWorldBuilder from(Instance instance) {
return new TerraMinestomWorldBuilder(instance);
}
public static TerraMinestomWorldBuilder builder() {
return new TerraMinestomWorldBuilder(MinecraftServer.getInstanceManager().createInstanceContainer());
}
public TerraMinestomWorldBuilder pack(ConfigPack pack) {
this.pack = pack;
return this;
}
public TerraMinestomWorldBuilder packById(String id) {
this.pack = MinestomPlatform.getInstance().getConfigRegistry().getByID(id).orElseThrow();
this.pack = platform.getConfigRegistry().getByID(id).orElseThrow();
return this;
}
public TerraMinestomWorldBuilder findPack(Function<CheckedRegistry<ConfigPack>, ConfigPack> fn) {
this.pack = fn.apply(MinestomPlatform.getInstance().getConfigRegistry());
this.pack = fn.apply(platform.getConfigRegistry());
return this;
}
@@ -72,7 +64,12 @@ public class TerraMinestomWorldBuilder {
return this;
}
public TerraMinestomWorldBuilder biomeFactory(BiomeFactory factory) {
this.biomeFactory = factory;
return this;
}
public TerraMinestomWorld attach() {
return new TerraMinestomWorld(instance, pack, seed, entityFactory, blockEntityFactory);
return new TerraMinestomWorld(platform, instance, pack, seed, entityFactory, blockEntityFactory, biomeFactory);
}
}

View File

@@ -1,17 +1,18 @@
package com.dfsek.terra.minestom.biome;
import net.minestom.server.registry.RegistryKey;
import net.minestom.server.world.biome.Biome;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import net.minestom.server.world.biome.Biome;
public class MinestomBiome implements PlatformBiome {
private final Biome biome;
private final RegistryKey<Biome> biome;
public MinestomBiome(Biome biome) { this.biome = biome; }
public MinestomBiome(RegistryKey<Biome> biome) { this.biome = biome; }
@Override
public Biome getHandle() {
public RegistryKey<Biome> getHandle() {
return biome;
}
}

View File

@@ -4,28 +4,23 @@ import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.loader.type.TypeLoader;
import com.dfsek.terra.api.world.biome.PlatformBiome;
import net.kyori.adventure.key.Key;
import net.minestom.server.MinecraftServer;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.world.biome.Biome;
import net.minestom.server.registry.RegistryKey;
import org.intellij.lang.annotations.Subst;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType;
import com.dfsek.terra.api.world.biome.PlatformBiome;
public class MinestomBiomeLoader implements TypeLoader<PlatformBiome> {
private final DynamicRegistry<Biome> biomeRegistry = MinecraftServer.getBiomeRegistry();
@Override
public PlatformBiome load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader,
DepthTracker depthTracker) throws LoadException {
@Subst("name:value")
String id = (String) o;
Key biomeID = Key.key(id);
Biome biome = biomeRegistry.get(biomeID);
if(biome == null) throw new LoadException("Biome %s does not exist in registry".formatted(id), depthTracker);
return new MinestomBiome(biome);
Key key = Key.key(id);
return new MinestomBiome(RegistryKey.unsafeOf(key));
}
}
}

View File

@@ -0,0 +1,74 @@
package com.dfsek.terra.minestom.biome;
import net.kyori.adventure.key.Key;
import net.minestom.server.MinecraftServer;
import net.minestom.server.color.Color;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.RegistryKey;
import net.minestom.server.world.biome.Biome;
import net.minestom.server.world.biome.BiomeEffects;
import org.intellij.lang.annotations.Subst;
import org.jetbrains.annotations.NotNull;
import java.util.Locale;
import java.util.Objects;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.minestom.api.BiomeFactory;
import com.dfsek.terra.minestom.config.VanillaBiomeProperties;
public class MinestomUserDefinedBiomeFactory implements BiomeFactory {
private final DynamicRegistry<Biome> biomeRegistry = MinecraftServer.getBiomeRegistry();
private final @NotNull Biome plainsBiome = Objects.requireNonNull(biomeRegistry.get(Key.key("minecraft:plains")));
private static <T> T mergeNullable(T first, T second) {
if(first == null) return second;
return first;
}
@Subst("value")
protected static String createBiomeID(ConfigPack pack, String biomeId) {
return pack.getID().toLowerCase() + "/" + biomeId.toLowerCase(Locale.ROOT);
}
@Override
public UserDefinedBiome create(ConfigPack pack, com.dfsek.terra.api.world.biome.Biome source) {
VanillaBiomeProperties properties = source.getContext().get(VanillaBiomeProperties.class);
RegistryKey<Biome> parentKey = ((MinestomBiome) source.getPlatformBiome()).getHandle();
Biome parent = mergeNullable(biomeRegistry.get(parentKey), plainsBiome);
BiomeEffects parentEffects = parent.effects();
Key key = Key.key("terra", createBiomeID(pack, source.getID()));
BiomeEffects.Builder effectsBuilder = BiomeEffects.builder()
.fogColor(mergeNullable(properties.getFogColor(), parentEffects.fogColor()))
.skyColor(mergeNullable(properties.getSkyColor(), parentEffects.skyColor()))
.waterColor(mergeNullable(properties.getWaterColor(), parentEffects.waterColor()))
.waterFogColor(mergeNullable(properties.getWaterFogColor(), parentEffects.waterFogColor()))
.foliageColor(mergeNullable(properties.getFoliageColor(), parentEffects.foliageColor()))
.grassColor(mergeNullable(properties.getGrassColor(), parentEffects.grassColor()))
.grassColorModifier(mergeNullable(properties.getGrassColorModifier(), parentEffects.grassColorModifier()))
.biomeParticle(mergeNullable(properties.getParticleConfig(), parentEffects.biomeParticle()))
.ambientSound(mergeNullable(properties.getLoopSound(), parentEffects.ambientSound()))
.moodSound(mergeNullable(properties.getMoodSound(), parentEffects.moodSound()))
.additionsSound(mergeNullable(properties.getAdditionsSound(), parentEffects.additionsSound()))
// TODO music
.music(parentEffects.music())
.musicVolume(parentEffects.musicVolume());
if(effectsBuilder.build().equals(BiomeEffects.PLAINS_EFFECTS)) {
effectsBuilder.fogColor(new Color(0xC0D8FE)); // circumvent a minestom bug
}
Biome target = Biome.builder()
.downfall(mergeNullable(properties.getDownfall(), parent.downfall()))
.hasPrecipitation(mergeNullable(properties.getPrecipitation(), parent.hasPrecipitation()))
.temperature(mergeNullable(properties.getTemperature(), parent.temperature()))
.temperatureModifier(mergeNullable(properties.getTemperatureModifier(), parent.temperatureModifier()))
.effects(effectsBuilder.build())
.build();
RegistryKey<Biome> registryKey = MinecraftServer.getBiomeRegistry().register(key, target);
return new UserDefinedBiome(key, registryKey, source.getID(), target);
}
}

View File

@@ -0,0 +1,45 @@
package com.dfsek.terra.minestom.biome;
import java.util.HashSet;
import java.util.IdentityHashMap;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.minestom.api.BiomeFactory;
public class MinestomUserDefinedBiomePool {
private final IdentityHashMap<Biome, UserDefinedBiome> biomes = new IdentityHashMap<>();
private final HashSet<String> createdBiomes = new HashSet<>();
private final BiomeFactory factory;
private final ConfigPack configPack;
public MinestomUserDefinedBiomePool(ConfigPack configPack, BiomeFactory factory) {
this.configPack = configPack;
this.factory = factory;
}
public UserDefinedBiome getBiome(Biome source) {
UserDefinedBiome userDefinedBiome = biomes.get(source);
if(userDefinedBiome != null) return userDefinedBiome;
userDefinedBiome = factory.create(configPack, source);
biomes.put(source, userDefinedBiome);
createdBiomes.add(source.getID());
return userDefinedBiome;
}
public void preloadBiomes(Iterable<Biome> biomesToLoad) {
biomesToLoad
.forEach(biome -> {
if(!this.createdBiomes.contains(biome.getID())) {
UserDefinedBiome udf = factory.create(configPack, biome);
this.biomes.put(biome, udf);
this.createdBiomes.add(biome.getID());
}
});
}
public void invalidate() {
biomes.clear();
}
}

View File

@@ -0,0 +1,49 @@
package com.dfsek.terra.minestom.biome;
import net.kyori.adventure.key.Key;
import net.minestom.server.MinecraftServer;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.RegistryKey;
import net.minestom.server.world.biome.Biome;
public class UserDefinedBiome {
private static final DynamicRegistry<Biome> BIOME_REGISTRY = MinecraftServer.getBiomeRegistry();
private final Key key;
private final RegistryKey<Biome> registry;
private final String id;
private final Biome biome;
private int registryId = -1;
public UserDefinedBiome(Key key, RegistryKey<Biome> registry, String id, Biome biome) {
this.key = key;
this.registry = registry;
this.id = id;
this.biome = biome;
}
public Key key() {
return key;
}
public RegistryKey<Biome> registryKey() {
return registry;
}
public String id() {
return id;
}
public Biome biome() {
return biome;
}
public int registryId() {
if(registryId == -1) {
registryId = BIOME_REGISTRY.getId(registry);
}
return registryId;
}
}

View File

@@ -1,14 +1,15 @@
package com.dfsek.terra.minestom.block;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.minestom.api.BlockEntityFactory;
import net.minestom.server.coordinate.BlockVec;
import net.minestom.server.instance.Instance;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.minestom.api.BlockEntityFactory;
public class DefaultBlockEntityFactory implements BlockEntityFactory {
private final Instance instance;
public DefaultBlockEntityFactory(Instance instance) {
this.instance = instance;
}

View File

@@ -1,7 +1,6 @@
package com.dfsek.terra.minestom.block;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.seismic.type.vector.Vector3;
import net.minestom.server.coordinate.BlockVec;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.block.Block;
@@ -9,6 +8,7 @@ import net.minestom.server.instance.block.Block;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState;
public class MinestomBlockEntity implements BlockEntity {
private final Instance instance;
private final BlockVec position;

View File

@@ -2,6 +2,7 @@ package com.dfsek.terra.minestom.block;
import net.minestom.server.instance.block.Block;
import java.util.HashMap;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -22,10 +23,24 @@ public class MinestomBlockState implements BlockState {
}
public MinestomBlockState(String data) {
block = Block.fromState(data);
if (block == null) {
throw new IllegalArgumentException("Invalid block state: " + data);
if(!data.contains("[")) {
block = Block.fromKey(data);
return;
}
String[] split = data.split("\\[");
String namespaceId = split[0];
String properties = split[1].substring(0, split[1].length() - 1);
Block block = Block.fromKey(namespaceId);
HashMap<String, String> propertiesMap = new HashMap<>();
for(String property : properties.split(",")) {
String[] kv = property.split("=");
propertiesMap.put(kv[0].strip(), kv[1].strip());
}
assert block != null;
this.block = block.withProperties(propertiesMap);
}
@Override
@@ -80,4 +95,4 @@ public class MinestomBlockState implements BlockState {
public int hashCode() {
return Objects.hashCode(block.id());
}
}
}

View File

@@ -1,10 +1,10 @@
package com.dfsek.terra.minestom.block;
import net.minestom.server.instance.block.Block;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.block.state.BlockState;
import net.minestom.server.instance.block.Block;
public class MinestomBlockType implements BlockType {
private final Block block;
@@ -41,7 +41,7 @@ public class MinestomBlockType implements BlockType {
@Override
public boolean equals(Object obj) {
if(obj instanceof MinestomBlockType other) {
return block.id() == other.block.id();
return block.stateId() == other.block.stateId();
}
return false;
}

View File

@@ -1,49 +1,48 @@
package com.dfsek.terra.minestom.chunk;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
import com.dfsek.terra.minestom.block.MinestomBlockState;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.generator.UnitModifier;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
import com.dfsek.terra.minestom.block.MinestomBlockState;
public class CachedChunk implements ProtoChunk {
private final int minHeight;
private final int maxHeight;
private final Block[][][] blocks;
private final Block[] blocks;
public CachedChunk(int minHeight, int maxHeight) {
this.minHeight = minHeight;
this.maxHeight = maxHeight;
this.blocks = new Block[16][maxHeight - minHeight + 1][16];
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
for(int y = 0; y < maxHeight - minHeight + 1; y++) {
blocks[x][y][z] = Block.AIR;
}
}
}
this.blocks = new Block[16 * (maxHeight - minHeight + 1) * 16];
Arrays.fill(blocks, Block.AIR);
}
public void writeRelative(UnitModifier modifier) {
modifier.setAllRelative((x, y, z) -> blocks[x][y][z]);
modifier.setAllRelative((x, y, z) -> blocks[getIndex(x, y + minHeight, z)]);
}
@Override
public void setBlock(int x, int y, int z, @NotNull BlockState blockState) {
Block block = (Block) blockState.getHandle();
if(block == null) return;
blocks[x][y - minHeight][z] = block;
blocks[getIndex(x, y, z)] = block;
}
private int getIndex(int x, int y, int z) {
int y_normalized = y - minHeight;
return x + (z * 16) + (y_normalized * 256);
}
@Override
public @NotNull BlockState getBlock(int x, int y, int z) {
return new MinestomBlockState(blocks[x][y - minHeight][z]);
return new MinestomBlockState(blocks[getIndex(x, y, z)]);
}
@Override

View File

@@ -1,11 +1,5 @@
package com.dfsek.terra.minestom.chunk;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.github.benmanes.caffeine.cache.stats.CacheStats;
@@ -13,6 +7,11 @@ import net.minestom.server.world.DimensionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
public class GeneratedChunkCache {
private static final Logger log = LoggerFactory.getLogger(GeneratedChunkCache.class);
@@ -22,13 +21,15 @@ public class GeneratedChunkCache {
private final ServerWorld world;
private final BiomeProvider biomeProvider;
public GeneratedChunkCache(DimensionType dimensionType, ChunkGenerator generator, ServerWorld world) {
public GeneratedChunkCache(DimensionType dimensionType, ChunkGenerator generator, ServerWorld world, BiomeProvider biomeProvider) {
this.dimensionType = dimensionType;
this.generator = generator;
this.world = world;
this.biomeProvider = world.getBiomeProvider();
this.cache = Caffeine.newBuilder().maximumSize(128).recordStats().build(
(Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight()));
this.biomeProvider = biomeProvider;
this.cache = Caffeine.newBuilder()
.maximumSize(128)
.recordStats()
.build((Pair<Integer, Integer> key) -> generateChunk(key.getLeft(), key.getRight()));
}
private CachedChunk generateChunk(int x, int z) {
@@ -39,8 +40,13 @@ public class GeneratedChunkCache {
public void displayStats() {
CacheStats stats = cache.stats();
log.info("Avg load time: {}ms | Hit rate: {}% | Load Count: {}", stats.averageLoadPenalty(), stats.hitRate() * 100,
stats.loadCount());
log.info("Avg load time: %.4fms | Hit rate: %3.4f%% | Load Count: %d"
.formatted(
stats.averageLoadPenalty() / 1000000f,
stats.hitRate() * 100,
stats.loadCount()
)
);
}
public CachedChunk at(int x, int z) {

View File

@@ -1,18 +1,17 @@
package com.dfsek.terra.minestom.chunk;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.chunk.Chunk;
import com.dfsek.terra.minestom.block.MinestomBlockState;
import net.minestom.server.instance.block.Block;
import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.chunk.Chunk;
import com.dfsek.terra.minestom.block.MinestomBlockState;
public class TerraMinestomChunk implements Chunk {
private net.minestom.server.instance.Chunk delegate;
private final ServerWorld world;
private net.minestom.server.instance.Chunk delegate;
public TerraMinestomChunk(net.minestom.server.instance.Chunk delegate, ServerWorld world) {
this.delegate = delegate;

View File

@@ -0,0 +1,24 @@
package com.dfsek.terra.minestom.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.minestom.server.sound.SoundEvent;
import net.minestom.server.world.biome.BiomeEffects;
public class BiomeAdditionsSoundTemplate implements ObjectTemplate<BiomeEffects.AdditionsSound> {
@Value("sound")
@Default
private SoundEvent sound = null;
@Value("sound-chance")
@Default
private Double soundChance = null;
@Override
public BiomeEffects.AdditionsSound get() {
if(sound == null) return null;
return new BiomeEffects.AdditionsSound(sound, soundChance);
}
}

View File

@@ -0,0 +1,37 @@
package com.dfsek.terra.minestom.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.minestom.server.sound.SoundEvent;
import net.minestom.server.world.biome.BiomeEffects;
public class BiomeMoodSoundTemplate implements ObjectTemplate<BiomeEffects.MoodSound> {
@Value("sound")
@Default
private SoundEvent sound = null;
@Value("cultivation-ticks")
@Default
private Integer soundCultivationTicks = null;
@Value("spawn-range")
@Default
private Integer soundSpawnRange = null;
@Value("extra-distance")
@Default
private Double soundExtraDistance = null;
@Override
public BiomeEffects.MoodSound get() {
if(sound == null) return null;
return new BiomeEffects.MoodSound(
sound,
soundCultivationTicks,
soundSpawnRange,
soundExtraDistance
);
}
}

View File

@@ -0,0 +1,30 @@
package com.dfsek.terra.minestom.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.minestom.server.particle.Particle;
import net.minestom.server.world.biome.BiomeEffects;
public class BiomeParticleConfigTemplate implements ObjectTemplate<BiomeEffects.Particle> {
@Value("particle")
@Default
private String particle = null;
@Value("probability")
@Default
private Float probability = null;
@Override
public BiomeEffects.Particle get() {
if(particle == null || probability == null) {
return null;
}
return new BiomeEffects.Particle(
probability,
Particle.fromKey(particle)
);
}
}

View File

@@ -0,0 +1,32 @@
package com.dfsek.terra.minestom.config;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.loader.type.TypeLoader;
import net.kyori.adventure.key.InvalidKeyException;
import net.kyori.adventure.key.Key;
import org.intellij.lang.annotations.Subst;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType;
public class KeyLoader implements TypeLoader<Key> {
@Override
public Key load(
@NotNull AnnotatedType annotatedType,
@NotNull Object o,
@NotNull ConfigLoader configLoader,
DepthTracker depthTracker
) throws LoadException {
if(!(o instanceof @Subst("a:o")String stringKey)) {
throw new LoadException("Value is not a String", depthTracker);
}
try {
return Key.key(stringKey);
} catch(InvalidKeyException e) {
throw new LoadException("Can't load key: Invalid Format", e, depthTracker);
}
}
}

View File

@@ -0,0 +1,28 @@
package com.dfsek.terra.minestom.config;
import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.loader.type.TypeLoader;
import net.kyori.adventure.util.RGBLike;
import net.minestom.server.color.Color;
import org.intellij.lang.annotations.Subst;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType;
public class RGBLikeLoader implements TypeLoader<RGBLike> {
@Override
public RGBLike load(
@NotNull AnnotatedType annotatedType,
@NotNull Object o,
@NotNull ConfigLoader configLoader,
DepthTracker depthTracker
) throws LoadException {
if(!(o instanceof @Subst("a:o")Integer value)) {
throw new LoadException("Value is not an integer", depthTracker);
}
return new Color(value);
}
}

View File

@@ -0,0 +1,28 @@
package com.dfsek.terra.minestom.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.kyori.adventure.key.Key;
import net.minestom.server.sound.SoundEvent;
public class SoundEventTemplate implements ObjectTemplate<SoundEvent> {
@Value("id")
@Default
private Key id = null;
@Value("distance-to-travel")
@Default
private Float distanceToTravel = null;
@Override
public SoundEvent get() {
if(id == null) {
return null;
} else {
// distanceToTravel is specifically allowed to be null.
return SoundEvent.of(id, distanceToTravel);
}
}
}

View File

@@ -0,0 +1,139 @@
package com.dfsek.terra.minestom.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 net.kyori.adventure.util.RGBLike;
import net.minestom.server.sound.SoundEvent;
import net.minestom.server.world.biome.Biome.TemperatureModifier;
import net.minestom.server.world.biome.BiomeEffects;
import net.minestom.server.world.biome.BiomeEffects.GrassColorModifier;
import com.dfsek.terra.api.properties.Properties;
public class VanillaBiomeProperties implements ConfigTemplate, Properties {
@Value("colors.grass")
@Default
private RGBLike grassColor = null;
@Value("colors.fog")
@Default
private RGBLike fogColor = null;
@Value("colors.water")
@Default
private RGBLike waterColor = null;
@Value("colors.water-fog")
@Default
private RGBLike waterFogColor = null;
@Value("colors.foliage")
@Default
private RGBLike foliageColor = null;
@Value("colors.sky")
@Default
private RGBLike skyColor = null;
@Value("colors.modifier")
@Default
private GrassColorModifier grassColorModifier = null;
@Value("particles")
@Default
private BiomeEffects.Particle particleConfig = null;
@Value("climate.precipitation")
@Default
private Boolean precipitation = null;
@Value("climate.temperature")
@Default
private Float temperature = null;
@Value("climate.temperature-modifier")
@Default
private TemperatureModifier temperatureModifier = null;
@Value("climate.downfall")
@Default
private Float downfall = null;
@Value("sound.loop-sound.sound")
@Default
private SoundEvent loopSound = null;
@Value("sound.mood-sound")
@Default
private BiomeEffects.MoodSound moodSound = null;
@Value("sound.additions-sound")
@Default
private BiomeEffects.AdditionsSound additionsSound = null;
// @Value("sound.music")
// @Default
// private MusicSound music = null;
public RGBLike getGrassColor() {
return grassColor;
}
public RGBLike getFogColor() {
return fogColor;
}
public RGBLike getWaterColor() {
return waterColor;
}
public RGBLike getWaterFogColor() {
return waterFogColor;
}
public RGBLike getFoliageColor() {
return foliageColor;
}
public RGBLike getSkyColor() {
return skyColor;
}
public GrassColorModifier getGrassColorModifier() {
return grassColorModifier;
}
public BiomeEffects.Particle getParticleConfig() {
return particleConfig;
}
public Boolean getPrecipitation() {
return precipitation;
}
public Float getTemperature() {
return temperature;
}
public TemperatureModifier getTemperatureModifier() {
return temperatureModifier;
}
public Float getDownfall() {
return downfall;
}
public SoundEvent getLoopSound() {
return loopSound;
}
public BiomeEffects.MoodSound getMoodSound() {
return moodSound;
}
public BiomeEffects.AdditionsSound getAdditionsSound() {
return additionsSound;
}
}

View File

@@ -1,10 +1,10 @@
package com.dfsek.terra.minestom.entity;
import com.dfsek.terra.minestom.api.EntityFactory;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityType;
import com.dfsek.terra.minestom.api.EntityFactory;
public class DefaultEntityFactory implements EntityFactory {
@Override

View File

@@ -1,13 +1,13 @@
package com.dfsek.terra.minestom.entity;
import com.dfsek.seismic.type.vector.Vector3;
import net.minestom.server.coordinate.Pos;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
import net.minestom.server.coordinate.Pos;
public class DeferredMinestomEntity implements Entity {
private final EntityType type;

View File

@@ -1,16 +1,15 @@
package com.dfsek.terra.minestom.entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.minestom.MinestomAdapter;
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
import com.dfsek.seismic.type.vector.Vector3;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Entity;
import net.minestom.server.instance.Instance;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.minestom.MinestomAdapter;
import com.dfsek.terra.minestom.world.TerraMinestomWorld;
public class MinestomEntity implements com.dfsek.terra.api.entity.Entity {
private final Entity delegate;
@@ -21,6 +20,13 @@ public class MinestomEntity implements com.dfsek.terra.api.entity.Entity {
this.world = world;
}
public static MinestomEntity spawn(double x, double y, double z, EntityType type, TerraMinestomWorld world) {
Instance instance = world.getHandle();
Entity entity = world.getEntityFactory().createEntity(((MinestomEntityType) type).getHandle());
entity.setInstance(instance, new Pos(x, y, z));
return new MinestomEntity(entity, world);
}
@Override
public Vector3 position() {
return MinestomAdapter.adapt(delegate.getPosition());
@@ -45,11 +51,4 @@ public class MinestomEntity implements com.dfsek.terra.api.entity.Entity {
public Object getHandle() {
return delegate;
}
public static MinestomEntity spawn(double x, double y, double z, EntityType type, TerraMinestomWorld world) {
Instance instance = world.getHandle();
Entity entity = world.getEntityFactory().createEntity(((MinestomEntityType) type).getHandle());
entity.setInstance(instance, new Pos(x, y, z));
return new MinestomEntity(entity, world);
}
}

View File

@@ -1,6 +1,5 @@
package com.dfsek.terra.minestom.entity;
import net.minestom.server.entity.EntityType;
@@ -15,4 +14,4 @@ public class MinestomEntityType implements com.dfsek.terra.api.entity.EntityType
public EntityType getHandle() {
return delegate;
}
}
}

View File

@@ -1,51 +1,67 @@
package com.dfsek.terra.minestom.item;
import com.dfsek.terra.api.inventory.ItemStack;
import com.dfsek.terra.api.inventory.item.Enchantment;
import net.kyori.adventure.key.Key;
import net.minestom.server.MinecraftServer;
import net.minestom.server.item.Material;
import net.minestom.server.registry.DynamicRegistry;
import net.minestom.server.registry.RegistryKey;
import java.util.Objects;
import com.dfsek.terra.api.inventory.ItemStack;
import com.dfsek.terra.api.inventory.item.Enchantment;
public class MinestomEnchantment implements Enchantment {
private final net.minestom.server.item.enchant.Enchantment registryItem;
private final RegistryKey<net.minestom.server.item.enchant.Enchantment> id;
private static final DynamicRegistry<net.minestom.server.item.enchant.Enchantment> enchantmentRegistry =
MinecraftServer.getEnchantmentRegistry();
private final net.minestom.server.item.enchant.Enchantment delegate;
private final String id;
public MinestomEnchantment(RegistryKey<net.minestom.server.item.enchant.Enchantment> id) {
this.id = id;
this.registryItem = enchantmentRegistry.get(id);
public MinestomEnchantment(net.minestom.server.item.enchant.Enchantment delegate) {
this.delegate = delegate;
DynamicRegistry<net.minestom.server.item.enchant.Enchantment> registry = MinecraftServer.getEnchantmentRegistry();
this.id = Objects.requireNonNull(registry.getKey(delegate)).toString();
}
public MinestomEnchantment(String id) {
this(RegistryKey.unsafeOf(id));
Key key = Key.key(id);
this.delegate = MinecraftServer.getEnchantmentRegistry().get(key);
this.id = id;
}
@Override
public boolean canEnchantItem(ItemStack itemStack) {
return registryItem.supportedItems().contains((Material) itemStack.getType().getHandle());
return delegate.supportedItems().contains((Material) itemStack.getType().getHandle());
}
@Override
public boolean conflictsWith(Enchantment other) {
return registryItem.exclusiveSet().contains(((MinestomEnchantment) other).id);
var otherDelegate = ((MinestomEnchantment) other).delegate;
delegate.exclusiveSet();
// Get the registry key for the other enchantment to use in contains
try {
DynamicRegistry<net.minestom.server.item.enchant.Enchantment> registry = MinecraftServer.getEnchantmentRegistry();
RegistryKey<net.minestom.server.item.enchant.Enchantment> otherKey = registry.getKey(otherDelegate);
return delegate.exclusiveSet().contains(otherKey);
} catch(Exception e) {
// If the key approach fails, fall back to a more basic implementation
String otherId = ((MinestomEnchantment) other).id;
return otherId.equals(this.id);
}
}
@Override
public String getID() {
return id.name();
return id;
}
@Override
public int getMaxLevel() {
return registryItem.maxLevel();
return delegate.maxLevel();
}
@Override
public net.minestom.server.item.enchant.Enchantment getHandle() {
return registryItem;
return delegate;
}
}
}

View File

@@ -1,14 +1,14 @@
package com.dfsek.terra.minestom.item;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.item.Enchantment;
import net.minestom.server.MinecraftServer;
import java.util.Set;
import java.util.stream.Collectors;
import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.item.Enchantment;
public class MinestomItemHandle implements ItemHandle {
@Override
@@ -23,6 +23,6 @@ public class MinestomItemHandle implements ItemHandle {
@Override
public Set<Enchantment> getEnchantments() {
return MinecraftServer.getEnchantmentRegistry().keys().stream().map(MinestomEnchantment::new).collect(Collectors.toSet());
return MinecraftServer.getEnchantmentRegistry().values().stream().map(MinestomEnchantment::new).collect(Collectors.toSet());
}
}

View File

@@ -1,11 +1,11 @@
package com.dfsek.terra.minestom.item;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.dfsek.terra.api.inventory.item.ItemMeta;
import java.util.HashMap;
import java.util.Map;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.dfsek.terra.api.inventory.item.ItemMeta;
public class MinestomItemMeta implements ItemMeta {
private final HashMap<Enchantment, Integer> enchantments;

View File

@@ -1,10 +1,5 @@
package com.dfsek.terra.minestom.item;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.dfsek.terra.api.inventory.item.ItemMeta;
import net.minestom.server.MinecraftServer;
import net.minestom.server.component.DataComponents;
import net.minestom.server.item.ItemStack;
@@ -16,6 +11,10 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Objects;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.item.Enchantment;
import com.dfsek.terra.api.inventory.item.ItemMeta;
public class MinestomItemStack implements com.dfsek.terra.api.inventory.ItemStack {
private ItemStack base;
@@ -50,7 +49,8 @@ public class MinestomItemStack implements com.dfsek.terra.api.inventory.ItemStac
EnchantmentList enchantmentList = base.get(DataComponents.ENCHANTMENTS);
if(enchantmentList != null) {
enchantmentList.enchantments().forEach((enchantmentKey, integer) -> {
enchantments.put(new MinestomEnchantment(enchantmentKey), integer);
enchantments.put(
new MinestomEnchantment(Objects.requireNonNull(MinecraftServer.getEnchantmentRegistry().get(enchantmentKey))), integer);
});
}
return new MinestomItemMeta(enchantments);

View File

@@ -1,10 +1,10 @@
package com.dfsek.terra.minestom.item;
import net.minestom.server.item.Material;
import com.dfsek.terra.api.inventory.Item;
import com.dfsek.terra.api.inventory.ItemStack;
import net.minestom.server.item.Material;
public class MinestomMaterial implements Item {
private final Material delegate;
@@ -14,7 +14,7 @@ public class MinestomMaterial implements Item {
}
public MinestomMaterial(String id) {
this.delegate = Material.fromKey(id);
this.delegate = Material.fromId(Integer.parseInt(id));
}
@Override
@@ -31,4 +31,4 @@ public class MinestomMaterial implements Item {
public Material getHandle() {
return delegate;
}
}
}

View File

@@ -1,43 +1,88 @@
package com.dfsek.terra.minestom.world;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
import com.dfsek.terra.minestom.chunk.CachedChunk;
import com.dfsek.terra.minestom.chunk.GeneratedChunkCache;
import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.generator.GenerationUnit;
import net.minestom.server.instance.generator.Generator;
import net.minestom.server.instance.generator.GeneratorImpl.AreaModifierImpl;
import net.minestom.server.instance.generator.GeneratorImpl.SectionModifierImpl;
import net.minestom.server.instance.generator.UnitModifier;
import net.minestom.server.instance.palette.Palette;
import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
import com.dfsek.terra.minestom.biome.MinestomUserDefinedBiomePool;
import com.dfsek.terra.minestom.biome.UserDefinedBiome;
import com.dfsek.terra.minestom.chunk.CachedChunk;
import com.dfsek.terra.minestom.chunk.GeneratedChunkCache;
public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrapper {
private final GeneratedChunkCache cache;
private ChunkGenerator generator;
private final TerraMinestomWorld world;
private final BiomeProvider biomeProvider;
private final MinestomUserDefinedBiomePool biomePool;
private ChunkGenerator generator;
private ConfigPack pack;
public MinestomChunkGeneratorWrapper(ChunkGenerator generator, TerraMinestomWorld world, ConfigPack pack) {
public MinestomChunkGeneratorWrapper(
ChunkGenerator generator,
TerraMinestomWorld world,
ConfigPack pack,
MinestomUserDefinedBiomePool biomePool
) {
this.generator = generator;
this.world = world;
this.pack = pack;
this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world);
this.biomePool = biomePool;
this.biomeProvider = pack.getBiomeProvider();
this.cache = new GeneratedChunkCache(world.getDimensionType(), generator, world, biomeProvider);
preloadBiomes();
}
public ChunkGenerator getGenerator() {
return generator;
}
@SuppressWarnings("UnstableApiUsage")
@Override
public void generate(@NotNull GenerationUnit unit) {
Point start = unit.absoluteStart();
int x = start.chunkX();
int z = start.chunkZ();
int blockX = start.blockX();
int blockZ = start.blockZ();
CachedChunk chunk = cache.at(x, z);
chunk.writeRelative(unit.modifier());
UnitModifier modifier = unit.modifier();
chunk.writeRelative(modifier);
AreaModifierImpl areaModifiers = (AreaModifierImpl) modifier;
for(GenerationUnit section : areaModifiers.sections()) {
SectionModifierImpl sectionModifier = (SectionModifierImpl) section.modifier();
Palette biomes = sectionModifier.genSection().biomes();
int minY = section.absoluteStart().blockY();
for(int relativeX = 0; relativeX < 16; relativeX += 1) {
int absoluteX = blockX + relativeX;
for(int relativeZ = 0; relativeZ < 16; relativeZ += 1) {
int absoluteZ = blockZ + relativeZ;
for(int relativeY = 0; relativeY < 16; relativeY += 1) {
int absoluteY = minY + relativeY;
if(relativeX % 4 == 0 && relativeY % 4 == 0 && relativeZ % 4 == 0) {
UserDefinedBiome userDefinedBiome = biomePool.getBiome(
biomeProvider.getBiome(absoluteX, absoluteY, absoluteZ, world.getSeed())
);
int registryId = userDefinedBiome.registryId();
biomes.set(relativeX / 4, relativeY / 4, relativeZ / 4, registryId);
}
}
}
}
}
unit.fork(setter -> {
MinestomProtoWorld protoWorld = new MinestomProtoWorld(cache, x, z, world, setter);
@@ -55,6 +100,12 @@ public class MinestomChunkGeneratorWrapper implements Generator, GeneratorWrappe
public void setPack(ConfigPack pack) {
this.pack = pack;
this.generator = pack.getGeneratorProvider().newInstance(pack);
this.biomePool.invalidate();
preloadBiomes();
}
private void preloadBiomes() {
this.biomePool.preloadBiomes(world.getBiomeProvider().getBiomes());
}
public void displayStats() {

Some files were not shown because too many files have changed in this diff Show More