Refactored BCLib Package Structure
This commit is contained in:
parent
c658a24750
commit
f6d5f85ec1
206 changed files with 974 additions and 945 deletions
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api;
|
||||
package org.betterx.bclib.api.v2;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api;
|
||||
package org.betterx.bclib.api.v2;
|
||||
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api;
|
||||
package org.betterx.bclib.api.v2;
|
||||
|
||||
import net.minecraft.client.gui.screens.worldselection.WorldGenSettingsComponent;
|
||||
import net.minecraft.core.Registry;
|
||||
|
@ -16,10 +16,10 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
|
|||
import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraft.world.level.storage.ServerLevelData;
|
||||
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.datafixer.DataFixerAPI;
|
||||
import org.betterx.bclib.api.worldgen.WorldGenUtil;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.v2.datafixer.DataFixerAPI;
|
||||
import org.betterx.bclib.api.v2.levelgen.LevelGenUtil;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
|
||||
import org.betterx.bclib.mixin.common.RegistryOpsAccessor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -37,13 +37,13 @@ public class LifeCycleAPI {
|
|||
|
||||
|
||||
private static void worldCreationStarted(RegistryAccess access) {
|
||||
BiomeAPI.initRegistry(access);
|
||||
InternalBiomeAPI.initRegistry(access);
|
||||
}
|
||||
|
||||
public static void newWorldSetup(LevelStorageSource.LevelStorageAccess levelStorageAccess,
|
||||
WorldGenSettings settings) {
|
||||
DataExchangeAPI.prepareServerside();
|
||||
BiomeAPI.prepareNewLevel();
|
||||
InternalBiomeAPI.prepareNewLevel();
|
||||
|
||||
DataFixerAPI.createWorldData(levelStorageAccess, settings);
|
||||
_runBeforeLevelLoad();
|
||||
|
@ -53,14 +53,14 @@ public class LifeCycleAPI {
|
|||
WorldGenSettings worldGenSettings,
|
||||
LevelStorageSource levelSource) {
|
||||
DataExchangeAPI.prepareServerside();
|
||||
BiomeAPI.prepareNewLevel();
|
||||
InternalBiomeAPI.prepareNewLevel();
|
||||
|
||||
DataFixerAPI.createWorldData(levelSource, levelID, worldGenSettings);
|
||||
_runBeforeLevelLoad();
|
||||
}
|
||||
|
||||
public static void newWorldSetup(LevelStorageSource.LevelStorageAccess levelStorageAccess) {
|
||||
BiomeAPI.prepareNewLevel();
|
||||
InternalBiomeAPI.prepareNewLevel();
|
||||
DataFixerAPI.fixData(levelStorageAccess, false, (didFix) -> {/* not called when showUI==false */});
|
||||
|
||||
_runBeforeLevelLoad();
|
||||
|
@ -68,9 +68,9 @@ public class LifeCycleAPI {
|
|||
|
||||
public static WorldGenSettings worldLoadStarted(WorldGenSettings settings, Optional<RegistryOps<Tag>> registryOps) {
|
||||
if (registryOps.orElse(null) instanceof RegistryOpsAccessor acc) {
|
||||
BiomeAPI.initRegistry(acc.bcl_getRegistryAccess());
|
||||
InternalBiomeAPI.initRegistry(acc.bcl_getRegistryAccess());
|
||||
}
|
||||
settings = WorldGenUtil.fixSettingsInCurrentWorld(registryOps, settings);
|
||||
settings = LevelGenUtil.fixSettingsInCurrentWorld(registryOps, settings);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
@ -154,16 +154,16 @@ public class LifeCycleAPI {
|
|||
List<CustomSpawner> list,
|
||||
boolean bl2) {
|
||||
onLoadLevel.forEach(c -> c.onLoad(world,
|
||||
minecraftServer,
|
||||
executor,
|
||||
levelStorageAccess,
|
||||
serverLevelData,
|
||||
resourceKey,
|
||||
chunkProgressListener,
|
||||
bl,
|
||||
l,
|
||||
list,
|
||||
bl2));
|
||||
minecraftServer,
|
||||
executor,
|
||||
levelStorageAccess,
|
||||
serverLevelData,
|
||||
resourceKey,
|
||||
chunkProgressListener,
|
||||
bl,
|
||||
l,
|
||||
list,
|
||||
bl2));
|
||||
|
||||
final long seed = world.getSeed();
|
||||
final Registry<Biome> biomeRegistry = world.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api;
|
||||
package org.betterx.bclib.api.v2;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api;
|
||||
package org.betterx.bclib.api.v2;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.core.Registry;
|
||||
|
@ -12,9 +12,9 @@ import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.tag.NamedMineableTags;
|
||||
import org.betterx.bclib.api.tag.TagAPI;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
|
||||
import org.betterx.bclib.api.v2.tag.NamedMineableTags;
|
||||
import org.betterx.bclib.api.v2.tag.TagAPI;
|
||||
import org.betterx.bclib.blocks.BaseBarrelBlock;
|
||||
import org.betterx.bclib.blocks.BaseChestBlock;
|
||||
import org.betterx.bclib.blocks.BaseFurnaceBlock;
|
||||
|
@ -70,7 +70,7 @@ public class PostInitAPI {
|
|||
}
|
||||
blockTags = null;
|
||||
itemTags = null;
|
||||
BiomeAPI.loadFabricAPIBiomes();
|
||||
InternalBiomeAPI.loadFabricAPIBiomes();
|
||||
Configs.BIOMES_CONFIG.saveChanges();
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api;
|
||||
package org.betterx.bclib.api.v2;
|
||||
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api;
|
||||
package org.betterx.bclib.api.v2;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
|
@ -10,7 +10,7 @@ import net.fabricmc.loader.api.ModContainer;
|
|||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.datafixer.DataFixerAPI;
|
||||
import org.betterx.bclib.api.v2.datafixer.DataFixerAPI;
|
||||
import org.betterx.bclib.util.ModUtil;
|
||||
|
||||
import java.io.File;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
|
@ -1,6 +1,6 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import org.betterx.bclib.api.dataexchange.handler.DataExchange;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.DataExchange;
|
||||
|
||||
import java.util.Set;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
|
@ -10,7 +10,7 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
|||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.handler.DataExchange;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.DataExchange;
|
||||
|
||||
/**
|
||||
* This is an internal class that handles a Clienetside players Connection to a Server
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
@ -9,7 +9,7 @@ import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
|||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.handler.DataExchange;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.DataExchange;
|
||||
|
||||
/**
|
||||
* This is an internal class that handles a Serverside Connection to a Client-Player
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
|
@ -7,9 +7,9 @@ import net.fabricmc.api.Environment;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.handler.DataExchange;
|
||||
import org.betterx.bclib.api.dataexchange.handler.autosync.AutoSync;
|
||||
import org.betterx.bclib.api.dataexchange.handler.autosync.AutoSyncID;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.DataExchange;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.autosync.AutoSync;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.autosync.AutoSyncID;
|
||||
import org.betterx.bclib.config.Config;
|
||||
import org.betterx.bclib.util.ModUtil;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
|
@ -18,8 +18,7 @@ import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
|||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.handler.autosync.Chunker;
|
||||
import org.betterx.bclib.api.dataexchange.handler.autosync.Chunker.PacketChunkSender;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.autosync.Chunker;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
@ -113,7 +112,7 @@ public abstract class DataHandler extends BaseDataHandler {
|
|||
Collection<ServerPlayer> players,
|
||||
FriendlyByteBuf buf) {
|
||||
if (buf.readableBytes() > Chunker.MAX_PACKET_SIZE) {
|
||||
final PacketChunkSender sender = new PacketChunkSender(buf, identifier);
|
||||
final Chunker.PacketChunkSender sender = new Chunker.PacketChunkSender(buf, identifier);
|
||||
sender.sendChunks(players);
|
||||
} else {
|
||||
for (ServerPlayer player : players) {
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package org.betterx.bclib.api.dataexchange;
|
||||
package org.betterx.bclib.api.v2.dataexchange;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
import org.betterx.bclib.api.dataexchange.handler.autosync.AutoSync;
|
||||
import org.betterx.bclib.api.dataexchange.handler.autosync.AutoSyncID;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.autosync.AutoSync;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.autosync.AutoSyncID;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Objects;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
|
@ -7,7 +7,7 @@ import net.fabricmc.api.Environment;
|
|||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
|
||||
import org.betterx.bclib.api.dataexchange.*;
|
||||
import org.betterx.bclib.api.v2.dataexchange.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
|
@ -1,10 +1,10 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.dataexchange.SyncFileHash;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.SyncFileHash;
|
||||
import org.betterx.bclib.util.ModUtil;
|
||||
import org.betterx.bclib.util.ModUtil.ModInfo;
|
||||
import org.betterx.bclib.util.Pair;
|
|
@ -1,10 +1,10 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.dataexchange.SyncFileHash;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.v2.dataexchange.SyncFileHash;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.config.ServerConfig;
|
||||
import org.betterx.bclib.util.PathUtil;
|
|
@ -1,8 +1,8 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
import org.betterx.bclib.api.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.config.Config;
|
||||
import org.betterx.bclib.util.ModUtil;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
@ -11,10 +11,10 @@ import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
|||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.BaseDataHandler;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.api.dataexchange.handler.DataExchange;
|
||||
import org.betterx.bclib.api.v2.dataexchange.BaseDataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.DataExchange;
|
||||
|
||||
import java.util.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
|
@ -1,11 +1,11 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.util.ProgressListener;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import org.betterx.bclib.gui.screens.ProgressScreen;
|
||||
import org.betterx.bclib.client.gui.screens.ProgressScreen;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ChunkerProgress {
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
@ -12,15 +12,15 @@ import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
|||
import net.fabricmc.loader.api.metadata.ModEnvironment;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.client.gui.screens.ModListScreen;
|
||||
import org.betterx.bclib.client.gui.screens.ProgressScreen;
|
||||
import org.betterx.bclib.client.gui.screens.SyncFilesScreen;
|
||||
import org.betterx.bclib.client.gui.screens.WarnBCLibVersionMismatch;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.config.ServerConfig;
|
||||
import org.betterx.bclib.gui.screens.ModListScreen;
|
||||
import org.betterx.bclib.gui.screens.ProgressScreen;
|
||||
import org.betterx.bclib.gui.screens.SyncFilesScreen;
|
||||
import org.betterx.bclib.gui.screens.WarnBCLibVersionMismatch;
|
||||
import org.betterx.bclib.util.ModUtil;
|
||||
import org.betterx.bclib.util.ModUtil.ModInfo;
|
||||
import org.betterx.bclib.util.PathUtil;
|
||||
|
@ -48,10 +48,10 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
}
|
||||
|
||||
public static final DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID,
|
||||
"hello_client"),
|
||||
HelloClient::new,
|
||||
false,
|
||||
false);
|
||||
"hello_client"),
|
||||
HelloClient::new,
|
||||
false,
|
||||
false);
|
||||
|
||||
public HelloClient() {
|
||||
super(DESCRIPTOR.IDENTIFIER);
|
||||
|
@ -87,14 +87,14 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
mods = new ArrayList<>(inmods.size());
|
||||
mods.addAll(inmods);
|
||||
mods.addAll(ModUtil
|
||||
.getMods()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> entry.getValue().metadata.getEnvironment() != ModEnvironment.SERVER && !inmods.contains(
|
||||
entry.getKey()))
|
||||
.map(entry -> entry.getKey())
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
.getMods()
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> entry.getValue().metadata.getEnvironment() != ModEnvironment.SERVER && !inmods.contains(
|
||||
entry.getKey()))
|
||||
.map(entry -> entry.getKey())
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
mods = mods
|
||||
|
@ -265,7 +265,7 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
if (!localSubFile.hash.equals(subFile.hash)) {
|
||||
BCLib.LOGGER.info(" * " + subFile.relPath + " (changed)");
|
||||
filesToRequest.add(new AutoSyncID.ForDirectFileRequest(desc.folderID,
|
||||
new File(subFile.relPath)));
|
||||
new File(subFile.relPath)));
|
||||
} else {
|
||||
BCLib.LOGGER.info(" * " + subFile.relPath);
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
//the file is missing locally
|
||||
BCLib.LOGGER.info(" * " + subFile.relPath + " (missing on client)");
|
||||
filesToRequest.add(new AutoSyncID.ForDirectFileRequest(desc.folderID,
|
||||
new File(subFile.relPath)));
|
||||
new File(subFile.relPath)));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -310,9 +310,9 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
filesToRequest.add(new AutoSyncID(e.serverHash.modID, e.serverHash.uniqueID));
|
||||
} else {
|
||||
filesToRequest.add(new AutoSyncID.WithContentOverride(e.serverHash.modID,
|
||||
e.serverHash.uniqueID,
|
||||
contentWrapper,
|
||||
e.localMatch.fileName));
|
||||
e.serverHash.uniqueID,
|
||||
contentWrapper,
|
||||
e.localMatch.fileName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,11 +390,11 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
return;
|
||||
} else if (serverPublishedModInfo && mismatchingMods.size() > 0 && Configs.CLIENT_CONFIG.isShowingModInfo()) {
|
||||
client.setScreen(new ModListScreen(client.screen,
|
||||
Component.translatable("title.bclib.modmissmatch"),
|
||||
Component.translatable("message.bclib.modmissmatch"),
|
||||
CommonComponents.GUI_PROCEED,
|
||||
ModUtil.getMods(),
|
||||
modVersion));
|
||||
Component.translatable("title.bclib.modmissmatch"),
|
||||
Component.translatable("message.bclib.modmissmatch"),
|
||||
CommonComponents.GUI_PROCEED,
|
||||
ModUtil.getMods(),
|
||||
modVersion));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -436,39 +436,39 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
}
|
||||
|
||||
client.setScreen(new SyncFilesScreen(modFiles,
|
||||
configFiles,
|
||||
singleFiles,
|
||||
folderFiles,
|
||||
filesToRemove.size(),
|
||||
modVersion,
|
||||
(downloadMods, downloadConfigs, downloadFiles, removeFiles) -> {
|
||||
if (downloadMods || downloadConfigs || downloadFiles) {
|
||||
BCLib.LOGGER.info("Updating local Files:");
|
||||
List<AutoSyncID.WithContentOverride> localChanges = new ArrayList<>(
|
||||
files.toArray().length);
|
||||
List<AutoSyncID> requestFiles = new ArrayList<>(files.toArray().length);
|
||||
configFiles,
|
||||
singleFiles,
|
||||
folderFiles,
|
||||
filesToRemove.size(),
|
||||
modVersion,
|
||||
(downloadMods, downloadConfigs, downloadFiles, removeFiles) -> {
|
||||
if (downloadMods || downloadConfigs || downloadFiles) {
|
||||
BCLib.LOGGER.info("Updating local Files:");
|
||||
List<AutoSyncID.WithContentOverride> localChanges = new ArrayList<>(
|
||||
files.toArray().length);
|
||||
List<AutoSyncID> requestFiles = new ArrayList<>(files.toArray().length);
|
||||
|
||||
files.forEach(aid -> {
|
||||
if (aid.isConfigFile() && downloadConfigs) {
|
||||
processOfferedFile(requestFiles, aid);
|
||||
} else if (aid instanceof AutoSyncID.ForModFileRequest && downloadMods) {
|
||||
processOfferedFile(requestFiles, aid);
|
||||
} else if (downloadFiles) {
|
||||
processOfferedFile(requestFiles, aid);
|
||||
}
|
||||
});
|
||||
files.forEach(aid -> {
|
||||
if (aid.isConfigFile() && downloadConfigs) {
|
||||
processOfferedFile(requestFiles, aid);
|
||||
} else if (aid instanceof AutoSyncID.ForModFileRequest && downloadMods) {
|
||||
processOfferedFile(requestFiles, aid);
|
||||
} else if (downloadFiles) {
|
||||
processOfferedFile(requestFiles, aid);
|
||||
}
|
||||
});
|
||||
|
||||
requestFileDownloads(requestFiles);
|
||||
}
|
||||
if (removeFiles) {
|
||||
filesToRemove.forEach(aid -> {
|
||||
BCLib.LOGGER.info(" - " + aid.relFile + " (removing)");
|
||||
aid.relFile.delete();
|
||||
});
|
||||
}
|
||||
requestFileDownloads(requestFiles);
|
||||
}
|
||||
if (removeFiles) {
|
||||
filesToRemove.forEach(aid -> {
|
||||
BCLib.LOGGER.info(" - " + aid.relFile + " (removing)");
|
||||
aid.relFile.delete();
|
||||
});
|
||||
}
|
||||
|
||||
this.onCloseSyncFilesScreen();
|
||||
}));
|
||||
this.onCloseSyncFilesScreen();
|
||||
}));
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
|
@ -499,8 +499,8 @@ public class HelloClient extends DataHandler.FromServer {
|
|||
BCLib.LOGGER.info("Starting download of Files:" + files.size());
|
||||
|
||||
final ProgressScreen progress = new ProgressScreen(null,
|
||||
Component.translatable("title.bclib.filesync.progress"),
|
||||
Component.translatable("message.bclib.filesync.progress"));
|
||||
Component.translatable("title.bclib.filesync.progress"),
|
||||
Component.translatable("message.bclib.filesync.progress"));
|
||||
progress.progressStart(Component.translatable("message.bclib.filesync.progress.stage.empty"));
|
||||
ChunkerProgress.setProgressScreen(progress);
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -10,9 +10,9 @@ import net.fabricmc.api.Environment;
|
|||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataExchangeAPI;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.util.ModUtil;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -10,8 +10,8 @@ import net.fabricmc.api.Environment;
|
|||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
|
||||
import java.util.ArrayList;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
@ -9,10 +9,10 @@ import net.fabricmc.api.Environment;
|
|||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandlerDescriptor;
|
||||
import org.betterx.bclib.client.gui.screens.ConfirmRestartScreen;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.gui.screens.ConfirmRestartScreen;
|
||||
import org.betterx.bclib.util.Pair;
|
||||
import org.betterx.bclib.util.PathUtil;
|
||||
import org.betterx.bclib.util.Triple;
|
||||
|
@ -27,10 +27,10 @@ import java.util.stream.Collectors;
|
|||
|
||||
public class SendFiles extends DataHandler.FromServer {
|
||||
public static final DataHandlerDescriptor DESCRIPTOR = new DataHandlerDescriptor(new ResourceLocation(BCLib.MOD_ID,
|
||||
"send_files"),
|
||||
SendFiles::new,
|
||||
false,
|
||||
false);
|
||||
"send_files"),
|
||||
SendFiles::new,
|
||||
false,
|
||||
false);
|
||||
|
||||
protected List<AutoFileSyncEntry> files;
|
||||
private String token;
|
||||
|
@ -173,7 +173,7 @@ public class SendFiles extends DataHandler.FromServer {
|
|||
}
|
||||
count++;
|
||||
name = prefix + mase.modID + "_" + mase.version.replace(".", "_") + "__" + String.format("%03d",
|
||||
count) + ".jar";
|
||||
count) + ".jar";
|
||||
} while (path.toFile().exists());
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package org.betterx.bclib.api.dataexchange.handler.autosync;
|
||||
package org.betterx.bclib.api.v2.dataexchange.handler.autosync;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.dataexchange.FileHash;
|
||||
import org.betterx.bclib.api.dataexchange.handler.autosync.AutoSyncID.ForDirectFileRequest;
|
||||
import org.betterx.bclib.api.v2.dataexchange.DataHandler;
|
||||
import org.betterx.bclib.api.v2.dataexchange.FileHash;
|
||||
import org.betterx.bclib.api.v2.dataexchange.handler.autosync.AutoSyncID.ForDirectFileRequest;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.util.PathUtil;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.datafixer;
|
||||
package org.betterx.bclib.api.v2.datafixer;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -17,14 +17,14 @@ import net.fabricmc.api.EnvType;
|
|||
import net.fabricmc.api.Environment;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.WorldDataAPI;
|
||||
import org.betterx.bclib.api.v2.WorldDataAPI;
|
||||
import org.betterx.bclib.api.v2.levelgen.LevelGenUtil;
|
||||
import org.betterx.bclib.client.gui.screens.AtomicProgressListener;
|
||||
import org.betterx.bclib.client.gui.screens.ConfirmFixScreen;
|
||||
import org.betterx.bclib.client.gui.screens.LevelFixErrorScreen;
|
||||
import org.betterx.bclib.client.gui.screens.LevelFixErrorScreen.Listener;
|
||||
import org.betterx.bclib.client.gui.screens.ProgressScreen;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.gui.screens.AtomicProgressListener;
|
||||
import org.betterx.bclib.gui.screens.ConfirmFixScreen;
|
||||
import org.betterx.bclib.gui.screens.LevelFixErrorScreen;
|
||||
import org.betterx.bclib.gui.screens.LevelFixErrorScreen.Listener;
|
||||
import org.betterx.bclib.gui.screens.ProgressScreen;
|
||||
import org.betterx.bclib.api.worldgen.WorldGenUtil;
|
||||
import org.betterx.bclib.util.Logger;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -181,7 +181,7 @@ public class DataFixerAPI {
|
|||
|
||||
public static void createWorldData(LevelStorageAccess access, WorldGenSettings settings) {
|
||||
initializeWorldData(access, true);
|
||||
WorldGenUtil.initializeWorldData(settings);
|
||||
LevelGenUtil.initializeWorldData(settings);
|
||||
WorldDataAPI.saveFile(BCLib.MOD_ID);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.datafixer;
|
||||
package org.betterx.bclib.api.v2.datafixer;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.datafixer;
|
||||
package org.betterx.bclib.api.v2.datafixer;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
|
@ -6,7 +6,7 @@ import net.minecraft.nbt.NbtIo;
|
|||
import net.minecraft.nbt.Tag;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.WorldDataAPI;
|
||||
import org.betterx.bclib.api.v2.WorldDataAPI;
|
||||
import org.betterx.bclib.interfaces.PatchBiFunction;
|
||||
import org.betterx.bclib.interfaces.PatchFunction;
|
||||
import org.betterx.bclib.util.ModUtil;
|
|
@ -1,9 +1,9 @@
|
|||
package org.betterx.bclib.api.datafixer;
|
||||
package org.betterx.bclib.api.v2.datafixer;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
|
||||
import org.betterx.bclib.api.WorldDataAPI;
|
||||
import org.betterx.bclib.api.v2.WorldDataAPI;
|
||||
import org.betterx.bclib.interfaces.PatchBiFunction;
|
||||
import org.betterx.bclib.interfaces.PatchFunction;
|
||||
import org.betterx.bclib.util.ModUtil;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.datafixer;
|
||||
package org.betterx.bclib.api.v2.datafixer;
|
||||
|
||||
public class PatchDidiFailException extends Exception {
|
||||
public PatchDidiFailException() {
|
|
@ -0,0 +1,110 @@
|
|||
package org.betterx.bclib.api.v2.generator;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class BCLBiomeSource extends BiomeSource {
|
||||
public static int BIOME_SOURCE_VERSION_NONE = -1;
|
||||
public static int BIOME_SOURCE_VERSION_VANILLA = 0;
|
||||
public static int BIOME_SOURCE_VERSION_SQUARE = 17;
|
||||
public static int BIOME_SOURCE_VERSION_HEX = 18;
|
||||
public static int DEFAULT_BIOME_SOURCE_VERSION = BIOME_SOURCE_VERSION_HEX;
|
||||
protected final Registry<Biome> biomeRegistry;
|
||||
protected long currentSeed;
|
||||
|
||||
public final int biomeSourceVersion;
|
||||
|
||||
private static List<Holder<Biome>> preInit(Registry<Biome> biomeRegistry, List<Holder<Biome>> biomes) {
|
||||
biomes = biomes.stream().sorted(Comparator.comparing(holder -> holder.unwrapKey()
|
||||
.get()
|
||||
.location()
|
||||
.toString()))
|
||||
.toList();
|
||||
biomes.forEach(biome -> BiomeAPI.sortBiomeFeatures(biome));
|
||||
return biomes;
|
||||
}
|
||||
|
||||
protected BCLBiomeSource(Registry<Biome> biomeRegistry,
|
||||
List<Holder<Biome>> list,
|
||||
long seed,
|
||||
Optional<Integer> biomeSourceVersion) {
|
||||
super(preInit(biomeRegistry, list));
|
||||
|
||||
this.biomeRegistry = biomeRegistry;
|
||||
this.biomeSourceVersion = biomeSourceVersion.orElse(DEFAULT_BIOME_SOURCE_VERSION);
|
||||
this.currentSeed = seed;
|
||||
|
||||
System.out.println(this + " with Registry: " + biomeRegistry.getClass().getName() + "@" + Integer.toHexString(
|
||||
biomeRegistry.hashCode()));
|
||||
|
||||
//BiomeAPI.initRegistry(biomeRegistry);
|
||||
}
|
||||
|
||||
final public void setSeed(long seed) {
|
||||
if (seed != currentSeed) {
|
||||
System.out.println(this + " set Seed: " + seed);
|
||||
this.currentSeed = seed;
|
||||
initMap(seed);
|
||||
}
|
||||
}
|
||||
|
||||
protected final void initMap(long seed) {
|
||||
System.out.println(this + " updates Map");
|
||||
onInitMap(seed);
|
||||
}
|
||||
|
||||
protected abstract void onInitMap(long newSeed);
|
||||
|
||||
public static int getVersionBiomeSource(BiomeSource biomeSource) {
|
||||
if (biomeSource == null) return BCLBiomeSource.BIOME_SOURCE_VERSION_NONE;
|
||||
|
||||
if (biomeSource instanceof BCLBiomeSource bcl) {
|
||||
return bcl.biomeSourceVersion;
|
||||
} else {
|
||||
return BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA;
|
||||
}
|
||||
}
|
||||
|
||||
public BCLBiomeSource createCopyForDatapack(Set<Holder<Biome>> datapackBiomes) {
|
||||
Set<Holder<Biome>> mutableSet = Sets.newHashSet();
|
||||
mutableSet.addAll(datapackBiomes);
|
||||
return cloneForDatapack(mutableSet);
|
||||
}
|
||||
|
||||
protected abstract BCLBiomeSource cloneForDatapack(Set<Holder<Biome>> datapackBiomes);
|
||||
|
||||
public interface ValidBiomePredicate {
|
||||
boolean isValid(Holder<Biome> biome, ResourceLocation location);
|
||||
}
|
||||
|
||||
protected static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry,
|
||||
List<String> exclude,
|
||||
List<String> include,
|
||||
BCLibNetherBiomeSource.ValidBiomePredicate test) {
|
||||
return biomeRegistry.stream()
|
||||
.filter(biome -> biomeRegistry.getResourceKey(biome).isPresent())
|
||||
|
||||
.map(biome -> biomeRegistry.getOrCreateHolderOrThrow(biomeRegistry.getResourceKey(biome)
|
||||
.get()))
|
||||
.filter(biome -> {
|
||||
ResourceLocation location = biome.unwrapKey().orElseThrow().location();
|
||||
final String strLocation = location.toString();
|
||||
if (exclude.contains(strLocation)) return false;
|
||||
if (include.contains(strLocation)) return true;
|
||||
|
||||
return test.isValid(biome, location);
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.worldgen;
|
||||
package org.betterx.bclib.api.v2.generator;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
|
@ -18,8 +18,8 @@ import net.minecraft.world.level.levelgen.synth.NormalNoise;
|
|||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.surface.SurfaceRuleUtil;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
|
||||
import org.betterx.bclib.api.v2.levelgen.surface.SurfaceRuleUtil;
|
||||
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
|
||||
import org.betterx.bclib.interfaces.SurfaceRuleProvider;
|
||||
|
||||
|
@ -69,7 +69,7 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
|
|||
ChunkGenerator loadedChunkGenerator) {
|
||||
BCLib.LOGGER.debug("Checking Noise Settings for " + dimensionKey.location().toString());
|
||||
final BiomeSource loadedBiomeSource = loadedChunkGenerator.getBiomeSource();
|
||||
BiomeAPI.applyModifications(loadedBiomeSource, dimensionKey);
|
||||
InternalBiomeAPI.applyModifications(loadedBiomeSource, dimensionKey);
|
||||
|
||||
if (loadedChunkGenerator instanceof NoiseBasedChunkGenerator nbc) {
|
||||
if (((Object) nbc.generatorSettings().value()) instanceof SurfaceRuleProvider srp) {
|
|
@ -0,0 +1,306 @@
|
|||
package org.betterx.bclib.api.v2.generator;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BiomeTags;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.biome.Climate;
|
||||
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||
import net.minecraft.world.level.levelgen.synth.SimplexNoise;
|
||||
|
||||
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap;
|
||||
import org.betterx.bclib.api.v2.generator.map.square.SquareBiomeMap;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.interfaces.BiomeMap;
|
||||
import org.betterx.bclib.interfaces.TheEndBiomeDataAccessor;
|
||||
import org.betterx.bclib.noise.OpenSimplexNoise;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class BCLibEndBiomeSource extends BCLBiomeSource {
|
||||
private static final OpenSimplexNoise SMALL_NOISE = new OpenSimplexNoise(8324);
|
||||
public static Codec<BCLibEndBiomeSource> CODEC
|
||||
= RecordCodecBuilder.create((instance) -> instance.group(
|
||||
RegistryOps
|
||||
.retrieveRegistry(Registry.BIOME_REGISTRY)
|
||||
.forGetter((theEndBiomeSource) -> theEndBiomeSource.biomeRegistry),
|
||||
Codec
|
||||
.LONG
|
||||
.fieldOf("seed")
|
||||
.stable()
|
||||
.forGetter(source -> source.currentSeed),
|
||||
Codec
|
||||
.INT
|
||||
.optionalFieldOf("version")
|
||||
.stable()
|
||||
.forGetter(source -> Optional.of(source.biomeSourceVersion)))
|
||||
.apply(instance,
|
||||
instance.stable(BCLibEndBiomeSource::new)
|
||||
)
|
||||
);
|
||||
private final Holder<Biome> centerBiome;
|
||||
private final Holder<Biome> barrens;
|
||||
private final Point pos;
|
||||
private final Function<Point, Boolean> endLandFunction;
|
||||
private SimplexNoise noise;
|
||||
private BiomeMap mapLand;
|
||||
private BiomeMap mapVoid;
|
||||
|
||||
private final BiomePicker endLandBiomePicker;
|
||||
private final BiomePicker endVoidBiomePicker;
|
||||
|
||||
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version) {
|
||||
this(biomeRegistry, seed, version, true);
|
||||
}
|
||||
|
||||
public BCLibEndBiomeSource(Registry<Biome> biomeRegistry, Optional<Integer> version) {
|
||||
this(biomeRegistry, 0, version, false);
|
||||
}
|
||||
|
||||
private BCLibEndBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version, boolean initMaps) {
|
||||
this(biomeRegistry, getBiomes(biomeRegistry), seed, version, initMaps);
|
||||
}
|
||||
|
||||
private BCLibEndBiomeSource(Registry<Biome> biomeRegistry,
|
||||
List<Holder<Biome>> list,
|
||||
long seed,
|
||||
Optional<Integer> version,
|
||||
boolean initMaps) {
|
||||
super(biomeRegistry, list, seed, version);
|
||||
|
||||
endLandBiomePicker = new BiomePicker(biomeRegistry);
|
||||
endVoidBiomePicker = new BiomePicker(biomeRegistry);
|
||||
|
||||
List<String> includeVoid = Configs.BIOMES_CONFIG.getEntry("force_include",
|
||||
"end_void_biomes",
|
||||
StringArrayEntry.class).getValue();
|
||||
this.possibleBiomes().forEach(biome -> {
|
||||
ResourceLocation key = biome.unwrapKey().orElseThrow().location();
|
||||
String group = key.getNamespace() + "." + key.getPath();
|
||||
|
||||
if (!BiomeAPI.hasBiome(key)) {
|
||||
BCLBiome bclBiome = new BCLBiome(key, biome.value());
|
||||
|
||||
if (includeVoid.contains(key.toString())) {
|
||||
endVoidBiomePicker.addBiome(bclBiome);
|
||||
} else {
|
||||
endLandBiomePicker.addBiome(bclBiome);
|
||||
}
|
||||
} else {
|
||||
BCLBiome bclBiome = BiomeAPI.getBiome(key);
|
||||
if (bclBiome != BiomeAPI.EMPTY_BIOME) {
|
||||
if (bclBiome.getParentBiome() == null) {
|
||||
if (BiomeAPI.wasRegisteredAsEndVoidBiome(key) || includeVoid.contains(key.toString())) {
|
||||
endVoidBiomePicker.addBiome(bclBiome);
|
||||
} else {
|
||||
endLandBiomePicker.addBiome(bclBiome);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
endLandBiomePicker.rebuild();
|
||||
endVoidBiomePicker.rebuild();
|
||||
|
||||
|
||||
this.centerBiome = biomeRegistry.getOrCreateHolderOrThrow(Biomes.THE_END);
|
||||
this.barrens = biomeRegistry.getOrCreateHolderOrThrow(Biomes.END_BARRENS);
|
||||
|
||||
this.endLandFunction = GeneratorOptions.getEndLandFunction();
|
||||
this.pos = new Point();
|
||||
|
||||
if (initMaps) {
|
||||
initMap(seed);
|
||||
}
|
||||
}
|
||||
|
||||
protected BCLBiomeSource cloneForDatapack(Set<Holder<Biome>> datapackBiomes) {
|
||||
datapackBiomes.addAll(getBclBiomes(this.biomeRegistry));
|
||||
return new BCLibEndBiomeSource(this.biomeRegistry,
|
||||
datapackBiomes.stream().toList(),
|
||||
this.currentSeed,
|
||||
Optional.of(biomeSourceVersion),
|
||||
true);
|
||||
}
|
||||
|
||||
private static List<Holder<Biome>> getBclBiomes(Registry<Biome> biomeRegistry) {
|
||||
List<String> include = Configs.BIOMES_CONFIG.getEntry("force_include",
|
||||
"end_land_biomes",
|
||||
StringArrayEntry.class).getValue();
|
||||
include.addAll(Configs.BIOMES_CONFIG.getEntry("force_include",
|
||||
"end_void_biomes",
|
||||
StringArrayEntry.class).getValue());
|
||||
if (TheEndBiomeData.createOverrides(biomeRegistry) instanceof TheEndBiomeDataAccessor acc) {
|
||||
return getBiomes(biomeRegistry,
|
||||
new ArrayList<>(0),
|
||||
include,
|
||||
(biome, location) ->
|
||||
BCLibEndBiomeSource.isValidNonVanillaEndBiome(biome, location) ||
|
||||
acc.bcl_isNonVanillaAndCanGenerateInEnd(biome.unwrapKey().orElseThrow())
|
||||
|
||||
);
|
||||
} else {
|
||||
return getBiomes(biomeRegistry,
|
||||
new ArrayList<>(0),
|
||||
include,
|
||||
BCLibEndBiomeSource::isValidNonVanillaEndBiome);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry) {
|
||||
List<String> include = Configs.BIOMES_CONFIG.getEntry("force_include",
|
||||
"end_land_biomes",
|
||||
StringArrayEntry.class).getValue();
|
||||
include.addAll(Configs.BIOMES_CONFIG.getEntry("force_include",
|
||||
"end_void_biomes",
|
||||
StringArrayEntry.class).getValue());
|
||||
|
||||
if (TheEndBiomeData.createOverrides(biomeRegistry) instanceof TheEndBiomeDataAccessor acc) {
|
||||
return getBiomes(biomeRegistry,
|
||||
new ArrayList<>(0),
|
||||
include,
|
||||
(biome, location) ->
|
||||
BCLibEndBiomeSource.isValidEndBiome(biome, location) || acc.bcl_canGenerateInEnd(
|
||||
biome.unwrapKey().orElseThrow())
|
||||
|
||||
);
|
||||
} else {
|
||||
return getBiomes(biomeRegistry, new ArrayList<>(0), include, BCLibEndBiomeSource::isValidEndBiome);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static boolean isValidEndBiome(Holder<Biome> biome, ResourceLocation location) {
|
||||
return biome.is(BiomeTags.IS_END) ||
|
||||
BiomeAPI.wasRegisteredAsEndBiome(location);
|
||||
}
|
||||
|
||||
private static boolean isValidNonVanillaEndBiome(Holder<Biome> biome, ResourceLocation location) {
|
||||
return biome.is(BiomeTags.IS_END) ||
|
||||
BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_END_LAND) ||
|
||||
BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_END_VOID);
|
||||
}
|
||||
|
||||
public static float getLegacyHeightValue(SimplexNoise simplexNoise, int i, int j) {
|
||||
int k = i / 2;
|
||||
int l = j / 2;
|
||||
int m = i % 2;
|
||||
int n = j % 2;
|
||||
float f = 100.0f - Mth.sqrt(i * i + j * j) * 8.0f;
|
||||
f = Mth.clamp(f, -100.0f, 80.0f);
|
||||
for (int o = -12; o <= 12; ++o) {
|
||||
for (int p = -12; p <= 12; ++p) {
|
||||
long q = k + o;
|
||||
long r = l + p;
|
||||
if (q * q + r * r <= 4096L || !(simplexNoise.getValue(q, r) < (double) -0.9f)) continue;
|
||||
float g = (Mth.abs(q) * 3439.0f + Mth.abs(r) * 147.0f) % 13.0f + 9.0f;
|
||||
float h = m - o * 2;
|
||||
float s = n - p * 2;
|
||||
float t = 100.0f - Mth.sqrt(h * h + s * s) * g;
|
||||
t = Mth.clamp(t, -100.0f, 80.0f);
|
||||
f = Math.max(f, t);
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("end_biome_source"), CODEC);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitMap(long seed) {
|
||||
if ((biomeSourceVersion != BIOME_SOURCE_VERSION_HEX)) {
|
||||
this.mapLand = new SquareBiomeMap(seed,
|
||||
GeneratorOptions.getBiomeSizeEndLand(),
|
||||
endLandBiomePicker);
|
||||
this.mapVoid = new SquareBiomeMap(seed,
|
||||
GeneratorOptions.getBiomeSizeEndVoid(),
|
||||
endVoidBiomePicker);
|
||||
} else {
|
||||
this.mapLand = new HexBiomeMap(seed,
|
||||
GeneratorOptions.getBiomeSizeEndLand(),
|
||||
endLandBiomePicker);
|
||||
this.mapVoid = new HexBiomeMap(seed,
|
||||
GeneratorOptions.getBiomeSizeEndVoid(),
|
||||
endVoidBiomePicker);
|
||||
}
|
||||
|
||||
WorldgenRandom chunkRandom = new WorldgenRandom(new LegacyRandomSource(seed));
|
||||
chunkRandom.consumeCount(17292);
|
||||
this.noise = new SimplexNoise(chunkRandom);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) {
|
||||
if (mapLand == null || mapVoid == null)
|
||||
return this.possibleBiomes().stream().findFirst().get();
|
||||
long posX = biomeX << 2;
|
||||
long posZ = biomeZ << 2;
|
||||
long farEndBiomes = GeneratorOptions.getFarEndBiomes();
|
||||
long dist = posX * posX + posZ * posZ;
|
||||
|
||||
if ((biomeX & 63) == 0 && (biomeZ & 63) == 0) {
|
||||
mapLand.clearCache();
|
||||
mapVoid.clearCache();
|
||||
}
|
||||
|
||||
if (endLandFunction == null) {
|
||||
if (dist <= farEndBiomes) return centerBiome;
|
||||
float height = getLegacyHeightValue(
|
||||
noise,
|
||||
(biomeX >> 1) + 1,
|
||||
(biomeZ >> 1) + 1
|
||||
) + (float) SMALL_NOISE.eval(biomeX, biomeZ) * 5;
|
||||
|
||||
if (height > -20F && height < -5F) {
|
||||
return barrens;
|
||||
}
|
||||
|
||||
if (height < -10F) {
|
||||
return mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
|
||||
} else {
|
||||
return mapLand.getBiome(posX, biomeY << 2, posZ).biome;
|
||||
}
|
||||
} else {
|
||||
pos.setLocation(biomeX, biomeZ);
|
||||
if (endLandFunction.apply(pos)) {
|
||||
return dist <= farEndBiomes ? centerBiome : mapLand.getBiome(posX, biomeY << 2, posZ).biome;
|
||||
} else {
|
||||
return dist <= farEndBiomes ? barrens : mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Codec<? extends BiomeSource> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BCLib - The End BiomeSource (" + Integer.toHexString(hashCode()) + ", version=" + biomeSourceVersion + ", seed=" + currentSeed + ", biomes=" + possibleBiomes().size() + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
package org.betterx.bclib.api.v2.generator;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BiomeTags;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate;
|
||||
|
||||
import net.fabricmc.fabric.impl.biome.NetherBiomeData;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.apache.commons.lang3.function.TriFunction;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.v2.generator.map.MapStack;
|
||||
import org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap;
|
||||
import org.betterx.bclib.api.v2.generator.map.square.SquareBiomeMap;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.interfaces.BiomeMap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public class BCLibNetherBiomeSource extends BCLBiomeSource {
|
||||
private static int lastWorldHeight;
|
||||
private static int worldHeight;
|
||||
public static final Codec<BCLibNetherBiomeSource> CODEC = RecordCodecBuilder
|
||||
.create(instance -> instance
|
||||
.group(RegistryOps
|
||||
.retrieveRegistry(Registry.BIOME_REGISTRY)
|
||||
.forGetter(source -> source.biomeRegistry),
|
||||
Codec
|
||||
.LONG
|
||||
.fieldOf("seed")
|
||||
.stable()
|
||||
.forGetter(source -> {
|
||||
return source.currentSeed;
|
||||
}),
|
||||
Codec
|
||||
.INT
|
||||
.optionalFieldOf("version")
|
||||
.stable()
|
||||
.forGetter(source -> Optional.of(source.biomeSourceVersion))
|
||||
)
|
||||
.apply(instance, instance.stable(BCLibNetherBiomeSource::new))
|
||||
);
|
||||
private BiomeMap biomeMap;
|
||||
private final BiomePicker biomePicker;
|
||||
|
||||
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, Optional<Integer> version) {
|
||||
this(biomeRegistry, 0, version, false);
|
||||
}
|
||||
|
||||
public BCLibNetherBiomeSource(Registry<Biome> biomeRegistry, long seed, Optional<Integer> version) {
|
||||
this(biomeRegistry, seed, version, true);
|
||||
}
|
||||
|
||||
private BCLibNetherBiomeSource(Registry<Biome> biomeRegistry,
|
||||
long seed,
|
||||
Optional<Integer> version,
|
||||
boolean initMaps) {
|
||||
this(biomeRegistry, getBiomes(biomeRegistry), seed, version, initMaps);
|
||||
}
|
||||
|
||||
private BCLibNetherBiomeSource(Registry<Biome> biomeRegistry,
|
||||
List<Holder<Biome>> list,
|
||||
long seed,
|
||||
Optional<Integer> version,
|
||||
boolean initMaps) {
|
||||
super(biomeRegistry, list, seed, version);
|
||||
|
||||
biomePicker = new BiomePicker(biomeRegistry);
|
||||
|
||||
this.possibleBiomes().forEach(biome -> {
|
||||
ResourceLocation key = biome.unwrapKey().orElseThrow().location();
|
||||
|
||||
if (!BiomeAPI.hasBiome(key)) {
|
||||
BCLBiome bclBiome = new BCLBiome(key, biome.value());
|
||||
biomePicker.addBiome(bclBiome);
|
||||
} else {
|
||||
BCLBiome bclBiome = BiomeAPI.getBiome(key);
|
||||
|
||||
if (bclBiome != BiomeAPI.EMPTY_BIOME) {
|
||||
if (bclBiome.getParentBiome() == null) {
|
||||
biomePicker.addBiome(bclBiome);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
biomePicker.rebuild();
|
||||
if (initMaps) {
|
||||
initMap(seed);
|
||||
}
|
||||
}
|
||||
|
||||
protected BCLBiomeSource cloneForDatapack(Set<Holder<Biome>> datapackBiomes) {
|
||||
datapackBiomes.addAll(getBclBiomes(this.biomeRegistry));
|
||||
return new BCLibNetherBiomeSource(this.biomeRegistry,
|
||||
datapackBiomes.stream().toList(),
|
||||
this.currentSeed,
|
||||
Optional.of(biomeSourceVersion),
|
||||
true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set world height, used when Nether is larger than vanilla 128 blocks tall.
|
||||
*
|
||||
* @param worldHeight height of the Nether ceiling.
|
||||
*/
|
||||
public static void setWorldHeight(int worldHeight) {
|
||||
BCLibNetherBiomeSource.worldHeight = worldHeight;
|
||||
}
|
||||
|
||||
private static List<Holder<Biome>> getBclBiomes(Registry<Biome> biomeRegistry) {
|
||||
List<String> include = Configs.BIOMES_CONFIG.getEntry("force_include", "nether_biomes", StringArrayEntry.class)
|
||||
.getValue();
|
||||
List<String> exclude = Configs.BIOMES_CONFIG.getEntry("force_exclude", "nether_biomes", StringArrayEntry.class)
|
||||
.getValue();
|
||||
|
||||
return getBiomes(biomeRegistry, exclude, include, BCLibNetherBiomeSource::isValidNonVanillaNetherBiome);
|
||||
}
|
||||
|
||||
|
||||
private static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry) {
|
||||
List<String> include = Configs.BIOMES_CONFIG.getEntry("force_include", "nether_biomes", StringArrayEntry.class)
|
||||
.getValue();
|
||||
List<String> exclude = Configs.BIOMES_CONFIG.getEntry("force_exclude", "nether_biomes", StringArrayEntry.class)
|
||||
.getValue();
|
||||
|
||||
return getBiomes(biomeRegistry, exclude, include, BCLibNetherBiomeSource::isValidNetherBiome);
|
||||
}
|
||||
|
||||
|
||||
private static boolean isValidNetherBiome(Holder<Biome> biome, ResourceLocation location) {
|
||||
return NetherBiomeData.canGenerateInNether(biome.unwrapKey().get()) ||
|
||||
biome.is(BiomeTags.IS_NETHER) ||
|
||||
BiomeAPI.wasRegisteredAsNetherBiome(location);
|
||||
}
|
||||
|
||||
private static boolean isValidNonVanillaNetherBiome(Holder<Biome> biome, ResourceLocation location) {
|
||||
return (
|
||||
!"minecraft".equals(location.getNamespace()) &&
|
||||
NetherBiomeData.canGenerateInNether(biome.unwrapKey().get())) ||
|
||||
BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_NETHER);
|
||||
}
|
||||
|
||||
public static <T> void debug(Object el, Registry<T> reg) {
|
||||
System.out.println("Unknown " + el + " in " + reg);
|
||||
}
|
||||
|
||||
public static void register() {
|
||||
Registry.register(Registry.BIOME_SOURCE, BCLib.makeID("nether_biome_source"), CODEC);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler var4) {
|
||||
if (biomeMap == null)
|
||||
return this.possibleBiomes().stream().findFirst().get();
|
||||
if (lastWorldHeight != worldHeight) {
|
||||
lastWorldHeight = worldHeight;
|
||||
initMap(this.currentSeed);
|
||||
}
|
||||
if ((biomeX & 63) == 0 && (biomeZ & 63) == 0) {
|
||||
biomeMap.clearCache();
|
||||
}
|
||||
BiomePicker.ActualBiome bb = biomeMap.getBiome(biomeX << 2, biomeY << 2, biomeZ << 2);
|
||||
return bb.biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Codec<? extends BiomeSource> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitMap(long seed) {
|
||||
TriFunction<Long, Integer, BiomePicker, BiomeMap> mapConstructor = (biomeSourceVersion != BIOME_SOURCE_VERSION_HEX)
|
||||
? SquareBiomeMap::new
|
||||
: HexBiomeMap::new;
|
||||
if (worldHeight > 128 && GeneratorOptions.useVerticalBiomes()) {
|
||||
this.biomeMap = new MapStack(
|
||||
seed,
|
||||
GeneratorOptions.getBiomeSizeNether(),
|
||||
biomePicker,
|
||||
GeneratorOptions.getVerticalBiomeSizeNether(),
|
||||
worldHeight,
|
||||
mapConstructor
|
||||
);
|
||||
} else {
|
||||
this.biomeMap = mapConstructor.apply(seed,
|
||||
GeneratorOptions.getBiomeSizeNether(),
|
||||
biomePicker);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BCLib - Nether BiomeSource (" + Integer.toHexString(hashCode()) + ", version=" + biomeSourceVersion + ", seed=" + currentSeed + ", biomes=" + possibleBiomes().size() + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package org.betterx.bclib.api.v2.generator;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
|
||||
import org.betterx.bclib.util.WeighTree;
|
||||
import org.betterx.bclib.util.WeightedList;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BiomePicker {
|
||||
public final Map<BCLBiome, ActualBiome> all = new HashMap<>();
|
||||
public final Registry<Biome> biomeRegistry;
|
||||
private final List<ActualBiome> biomes = Lists.newArrayList();
|
||||
private final List<String> allowedBiomes;
|
||||
private WeighTree<ActualBiome> tree;
|
||||
|
||||
public BiomePicker(Registry<Biome> biomeRegistry) {
|
||||
this(biomeRegistry, null);
|
||||
}
|
||||
|
||||
public BiomePicker(Registry<Biome> biomeRegistry, List<Holder<Biome>> allowedBiomes) {
|
||||
this.biomeRegistry = biomeRegistry;
|
||||
this.allowedBiomes = allowedBiomes != null ? allowedBiomes
|
||||
.stream()
|
||||
.map(h -> h.unwrapKey())
|
||||
.filter(o -> o.isPresent())
|
||||
.map(o -> o.get().location().toString()).toList() : null;
|
||||
}
|
||||
|
||||
private boolean isAllowed(BCLBiome b) {
|
||||
if (allowedBiomes == null) return true;
|
||||
return allowedBiomes.contains(b.getID().toString());
|
||||
}
|
||||
|
||||
private ActualBiome create(BCLBiome bclBiome) {
|
||||
ActualBiome e = all.get(bclBiome);
|
||||
if (e != null) return e;
|
||||
return new ActualBiome(bclBiome);
|
||||
}
|
||||
|
||||
public void addBiome(BCLBiome biome) {
|
||||
biomes.add(create(biome));
|
||||
}
|
||||
|
||||
public ActualBiome getBiome(WorldgenRandom random) {
|
||||
return biomes.isEmpty() ? null : tree.get(random);
|
||||
}
|
||||
|
||||
public void rebuild() {
|
||||
if (biomes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
WeightedList<ActualBiome> list = new WeightedList<>();
|
||||
biomes.forEach(biome -> {
|
||||
list.add(biome, biome.bclBiome.getGenChance());
|
||||
});
|
||||
tree = new WeighTree<>(list);
|
||||
}
|
||||
|
||||
public class ActualBiome {
|
||||
public final BCLBiome bclBiome;
|
||||
public final Holder<Biome> biome;
|
||||
public final ResourceKey<Biome> key;
|
||||
|
||||
private final WeightedList<ActualBiome> subbiomes = new WeightedList<>();
|
||||
private final ActualBiome edge;
|
||||
private final ActualBiome parent;
|
||||
|
||||
private ActualBiome(BCLBiome bclBiome) {
|
||||
all.put(bclBiome, this);
|
||||
this.bclBiome = bclBiome;
|
||||
|
||||
this.key = biomeRegistry.getResourceKey(biomeRegistry.get(bclBiome.getID())).orElseThrow();
|
||||
this.biome = biomeRegistry.getOrCreateHolderOrThrow(key);
|
||||
|
||||
bclBiome.forEachSubBiome((b, w) -> {
|
||||
if (isAllowed(b))
|
||||
subbiomes.add(create(b), w);
|
||||
});
|
||||
|
||||
if (bclBiome.getEdge() != null && isAllowed(bclBiome.getEdge())) {
|
||||
edge = create(bclBiome.getEdge());
|
||||
} else {
|
||||
edge = null;
|
||||
}
|
||||
|
||||
parent = bclBiome.getParentBiome() != null ? create(bclBiome.getParentBiome()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ActualBiome entry = (ActualBiome) o;
|
||||
return bclBiome.equals(entry.bclBiome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(bclBiome);
|
||||
}
|
||||
|
||||
public ActualBiome getSubBiome(WorldgenRandom random) {
|
||||
return subbiomes.get(random);
|
||||
}
|
||||
|
||||
public ActualBiome getEdge() {
|
||||
return edge;
|
||||
}
|
||||
|
||||
public ActualBiome getParentBiome() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isSame(ActualBiome e) {
|
||||
return bclBiome.isSame(e.bclBiome);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.betterx.bclib.api.v2.generator;
|
||||
|
||||
public enum BiomeType {
|
||||
LAND, VOID
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package org.betterx.bclib.api.v2.generator;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
import org.betterx.bclib.config.Configs;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class GeneratorOptions {
|
||||
private static int biomeSizeNether;
|
||||
private static int biomeVSizeNether;
|
||||
private static int biomeSizeEndLand;
|
||||
private static int biomeSizeEndVoid;
|
||||
private static Function<Point, Boolean> endLandFunction;
|
||||
private static boolean customNetherBiomeSource = true;
|
||||
private static boolean customEndBiomeSource = true;
|
||||
private static boolean verticalBiomes = true;
|
||||
private static long farEndBiomesSqr = 1000000;
|
||||
private static boolean fixEndBiomeSource = true;
|
||||
private static boolean fixNetherBiomeSource = true;
|
||||
|
||||
public static void init() {
|
||||
biomeSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap", "biomeSize", 256);
|
||||
biomeVSizeNether = Configs.GENERATOR_CONFIG.getInt("nether.biomeMap",
|
||||
"biomeVerticalSize(onlyInTallNether)",
|
||||
86);
|
||||
biomeSizeEndLand = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeLand", 256);
|
||||
biomeSizeEndVoid = Configs.GENERATOR_CONFIG.getInt("end.biomeMap", "biomeSizeVoid", 256);
|
||||
customNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customNetherBiomeSource", true);
|
||||
customEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options", "customEndBiomeSource", true);
|
||||
verticalBiomes = Configs.GENERATOR_CONFIG.getBoolean("options", "verticalBiomesInTallNether", true);
|
||||
fixEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options.biomeSource", "fixEndBiomeSource", true);
|
||||
fixNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options.biomeSource", "fixNetherBiomeSource", true);
|
||||
}
|
||||
|
||||
public static int getBiomeSizeNether() {
|
||||
return Mth.clamp(biomeSizeNether, 1, 8192);
|
||||
}
|
||||
|
||||
public static int getVerticalBiomeSizeNether() {
|
||||
return Mth.clamp(biomeVSizeNether, 1, 8192);
|
||||
}
|
||||
|
||||
public static int getBiomeSizeEndLand() {
|
||||
return Mth.clamp(biomeSizeEndLand, 1, 8192);
|
||||
}
|
||||
|
||||
public static int getBiomeSizeEndVoid() {
|
||||
return Mth.clamp(biomeSizeEndVoid, 1, 8192);
|
||||
}
|
||||
|
||||
public static void setEndLandFunction(Function<Point, Boolean> endLandFunction) {
|
||||
GeneratorOptions.endLandFunction = endLandFunction;
|
||||
}
|
||||
|
||||
public static Function<Point, Boolean> getEndLandFunction() {
|
||||
return endLandFunction;
|
||||
}
|
||||
|
||||
public static long getFarEndBiomes() {
|
||||
return farEndBiomesSqr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set distance of far End biomes generation, in blocks
|
||||
*
|
||||
* @param distance
|
||||
*/
|
||||
public static void setFarEndBiomes(int distance) {
|
||||
GeneratorOptions.farEndBiomesSqr = (long) distance * (long) distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set distance of far End biomes generation, in blocks^2
|
||||
*
|
||||
* @param distanceSqr the distance squared
|
||||
*/
|
||||
public static void setFarEndBiomesSqr(long distanceSqr) {
|
||||
GeneratorOptions.farEndBiomesSqr = distanceSqr;
|
||||
}
|
||||
|
||||
public static boolean customNetherBiomeSource() {
|
||||
return customNetherBiomeSource;
|
||||
}
|
||||
|
||||
public static boolean customEndBiomeSource() {
|
||||
return customEndBiomeSource;
|
||||
}
|
||||
|
||||
|
||||
public static boolean useVerticalBiomes() {
|
||||
return verticalBiomes;
|
||||
}
|
||||
|
||||
public static boolean fixEndBiomeSource() {
|
||||
return fixEndBiomeSource;
|
||||
}
|
||||
|
||||
public static boolean fixNetherBiomeSource() {
|
||||
return fixNetherBiomeSource;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package org.betterx.bclib.api.v2.generator.map;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
import org.apache.commons.lang3.function.TriFunction;
|
||||
import org.betterx.bclib.api.v2.generator.BiomePicker;
|
||||
import org.betterx.bclib.interfaces.BiomeChunk;
|
||||
import org.betterx.bclib.interfaces.BiomeMap;
|
||||
import org.betterx.bclib.interfaces.TriConsumer;
|
||||
import org.betterx.bclib.noise.OpenSimplexNoise;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class MapStack implements BiomeMap {
|
||||
private final OpenSimplexNoise noise;
|
||||
private final BiomeMap[] maps;
|
||||
private final double layerDistortion;
|
||||
private final int worldHeight;
|
||||
private final int minValue;
|
||||
private final int maxValue;
|
||||
private final int maxIndex;
|
||||
|
||||
public MapStack(long seed,
|
||||
int size,
|
||||
BiomePicker picker,
|
||||
int mapHeight,
|
||||
int worldHeight,
|
||||
TriFunction<Long, Integer, BiomePicker, BiomeMap> mapConstructor) {
|
||||
final int mapCount = Mth.ceil((float) worldHeight / mapHeight);
|
||||
this.maxIndex = mapCount - 1;
|
||||
this.worldHeight = worldHeight;
|
||||
this.layerDistortion = mapHeight * 0.1;
|
||||
minValue = Mth.floor(mapHeight * 0.5F + 0.5F);
|
||||
maxValue = Mth.floor(worldHeight - mapHeight * 0.5F + 0.5F);
|
||||
maps = new BiomeMap[mapCount];
|
||||
Random random = new Random(seed);
|
||||
for (int i = 0; i < mapCount; i++) {
|
||||
maps[i] = mapConstructor.apply(random.nextLong(), size, picker);
|
||||
maps[i].setChunkProcessor(this::onChunkCreation);
|
||||
}
|
||||
noise = new OpenSimplexNoise(random.nextInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache() {
|
||||
for (BiomeMap map : maps) {
|
||||
map.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeChunk getChunk(int cx, int cz, boolean update) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomePicker.ActualBiome getBiome(double x, double y, double z) {
|
||||
int mapIndex;
|
||||
|
||||
if (y < minValue) {
|
||||
mapIndex = 0;
|
||||
} else if (y > maxValue) {
|
||||
mapIndex = maxIndex;
|
||||
} else {
|
||||
mapIndex = Mth.floor((y + noise.eval(x * 0.03,
|
||||
z * 0.03) * layerDistortion) / worldHeight * maxIndex + 0.5F);
|
||||
mapIndex = Mth.clamp(mapIndex, 0, maxIndex);
|
||||
}
|
||||
|
||||
return maps[mapIndex].getBiome(x, y, z);
|
||||
}
|
||||
|
||||
private void onChunkCreation(int cx, int cz, int side) {
|
||||
BiomePicker.ActualBiome[][] biomeMap = new BiomePicker.ActualBiome[side][side];
|
||||
BiomeChunk[] chunks = new BiomeChunk[maps.length];
|
||||
|
||||
boolean isNoEmpty = false;
|
||||
for (int i = 0; i < maps.length; i++) {
|
||||
chunks[i] = maps[i].getChunk(cx, cz, false);
|
||||
for (int x = 0; x < side; x++) {
|
||||
for (int z = 0; z < side; z++) {
|
||||
if (biomeMap[x][z] == null) {
|
||||
BiomePicker.ActualBiome biome = chunks[i].getBiome(x, z);
|
||||
if (biome.bclBiome.isVertical()) {
|
||||
biomeMap[x][z] = biome;
|
||||
isNoEmpty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isNoEmpty) {
|
||||
for (int i = 0; i < maps.length; i++) {
|
||||
for (int x = 0; x < side; x++) {
|
||||
for (int z = 0; z < side; z++) {
|
||||
if (biomeMap[x][z] != null) {
|
||||
chunks[i].setBiome(x, z, biomeMap[x][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
package org.betterx.bclib.api.v2.generator.map.hex;
|
||||
|
||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||
|
||||
import org.betterx.bclib.api.v2.generator.BiomePicker;
|
||||
import org.betterx.bclib.interfaces.BiomeChunk;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class HexBiomeChunk implements BiomeChunk {
|
||||
private static final short SIDE = 32;
|
||||
private static final byte SIDE_PRE = 4;
|
||||
private static final short SIZE = SIDE * SIDE;
|
||||
private static final short MAX_SIDE = SIZE - SIDE;
|
||||
private static final byte SCALE_PRE = SIDE / SIDE_PRE;
|
||||
private static final byte SIZE_PRE = SIDE_PRE * SIDE_PRE;
|
||||
private static final byte SIDE_MASK = SIDE - 1;
|
||||
private static final byte SIDE_PRE_MASK = SIDE_PRE - 1;
|
||||
private static final byte SIDE_OFFSET = (byte) Math.round(Math.log(SIDE) / Math.log(2));
|
||||
private static final byte SIDE_PRE_OFFSET = (byte) Math.round(Math.log(SIDE_PRE) / Math.log(2));
|
||||
private static final short[][] NEIGHBOURS;
|
||||
|
||||
private final BiomePicker.ActualBiome[] biomes = new BiomePicker.ActualBiome[SIZE];
|
||||
|
||||
public HexBiomeChunk(WorldgenRandom random, BiomePicker picker) {
|
||||
BiomePicker.ActualBiome[][] buffers = new BiomePicker.ActualBiome[2][SIZE];
|
||||
|
||||
for (BiomePicker.ActualBiome[] buffer : buffers) {
|
||||
Arrays.fill(buffer, null);
|
||||
}
|
||||
|
||||
for (byte index = 0; index < SIZE_PRE; index++) {
|
||||
byte px = (byte) (index >> SIDE_PRE_OFFSET);
|
||||
byte pz = (byte) (index & SIDE_PRE_MASK);
|
||||
px = (byte) (px * SCALE_PRE + random.nextInt(SCALE_PRE));
|
||||
pz = (byte) (pz * SCALE_PRE + random.nextInt(SCALE_PRE));
|
||||
circle(buffers[0], getIndex(px, pz), picker.getBiome(random), null);
|
||||
}
|
||||
|
||||
boolean hasEmptyCells = true;
|
||||
byte bufferIndex = 0;
|
||||
while (hasEmptyCells) {
|
||||
BiomePicker.ActualBiome[] inBuffer = buffers[bufferIndex];
|
||||
bufferIndex = (byte) ((bufferIndex + 1) & 1);
|
||||
BiomePicker.ActualBiome[] outBuffer = buffers[bufferIndex];
|
||||
hasEmptyCells = false;
|
||||
|
||||
for (short index = SIDE; index < MAX_SIDE; index++) {
|
||||
byte z = (byte) (index & SIDE_MASK);
|
||||
if (z == 0 || z == SIDE_MASK) {
|
||||
continue;
|
||||
}
|
||||
if (inBuffer[index] != null) {
|
||||
outBuffer[index] = inBuffer[index];
|
||||
short[] neighbours = getNeighbours(index & SIDE_MASK);
|
||||
short indexSide = (short) (index + neighbours[random.nextInt(6)]);
|
||||
if (indexSide >= 0 && indexSide < SIZE && outBuffer[indexSide] == null) {
|
||||
outBuffer[indexSide] = inBuffer[index];
|
||||
}
|
||||
} else {
|
||||
hasEmptyCells = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BiomePicker.ActualBiome[] outBuffer = buffers[bufferIndex];
|
||||
byte preN = (byte) (SIDE_MASK - 2);
|
||||
for (byte index = 0; index < SIDE; index++) {
|
||||
outBuffer[getIndex(index, (byte) 0)] = outBuffer[getIndex(index, (byte) 2)];
|
||||
outBuffer[getIndex((byte) 0, index)] = outBuffer[getIndex((byte) 2, index)];
|
||||
outBuffer[getIndex(index, SIDE_MASK)] = outBuffer[getIndex(index, preN)];
|
||||
outBuffer[getIndex(SIDE_MASK, index)] = outBuffer[getIndex(preN, index)];
|
||||
}
|
||||
|
||||
for (short index = 0; index < SIZE; index++) {
|
||||
if (outBuffer[index] == null) {
|
||||
outBuffer[index] = picker.getBiome(random);
|
||||
} else if (random.nextInt(4) == 0) {
|
||||
circle(outBuffer, index, outBuffer[index].getSubBiome(random), outBuffer[index]);
|
||||
}
|
||||
}
|
||||
|
||||
System.arraycopy(outBuffer, 0, this.biomes, 0, SIZE);
|
||||
}
|
||||
|
||||
private void circle(BiomePicker.ActualBiome[] buffer,
|
||||
short center,
|
||||
BiomePicker.ActualBiome biome,
|
||||
BiomePicker.ActualBiome mask) {
|
||||
if (buffer[center] == mask) {
|
||||
buffer[center] = biome;
|
||||
}
|
||||
short[] neighbours = getNeighbours(center & SIDE_MASK);
|
||||
for (short i : neighbours) {
|
||||
short index = (short) (center + i);
|
||||
if (index >= 0 && index < SIZE && buffer[index] == mask) {
|
||||
buffer[index] = biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static byte wrap(int value) {
|
||||
return (byte) (value & SIDE_MASK);
|
||||
}
|
||||
|
||||
private short getIndex(byte x, byte z) {
|
||||
return (short) ((short) x << SIDE_OFFSET | z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomePicker.ActualBiome getBiome(int x, int z) {
|
||||
return biomes[getIndex(wrap(x), wrap(z))];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, BiomePicker.ActualBiome biome) {
|
||||
biomes[getIndex(wrap(x), wrap(z))] = biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSide() {
|
||||
return SIDE;
|
||||
}
|
||||
|
||||
public static int scaleCoordinate(int value) {
|
||||
return value >> SIDE_OFFSET;
|
||||
}
|
||||
|
||||
public static boolean isBorder(int value) {
|
||||
return wrap(value) == SIDE_MASK;
|
||||
}
|
||||
|
||||
private short[] getNeighbours(int z) {
|
||||
return NEIGHBOURS[z & 1];
|
||||
}
|
||||
|
||||
public static float scaleMap(float size) {
|
||||
return size / (SIDE >> 2);
|
||||
}
|
||||
|
||||
static {
|
||||
NEIGHBOURS = new short[2][6];
|
||||
|
||||
NEIGHBOURS[0][0] = 1;
|
||||
NEIGHBOURS[0][1] = -1;
|
||||
NEIGHBOURS[0][2] = SIDE;
|
||||
NEIGHBOURS[0][3] = -SIDE;
|
||||
NEIGHBOURS[0][4] = SIDE + 1;
|
||||
NEIGHBOURS[0][5] = SIDE - 1;
|
||||
|
||||
NEIGHBOURS[1][0] = 1;
|
||||
NEIGHBOURS[1][1] = -1;
|
||||
NEIGHBOURS[1][2] = SIDE;
|
||||
NEIGHBOURS[1][3] = -SIDE;
|
||||
NEIGHBOURS[1][4] = -SIDE + 1;
|
||||
NEIGHBOURS[1][5] = -SIDE - 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
package org.betterx.bclib.api.v2.generator.map.hex;
|
||||
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.betterx.bclib.api.v2.generator.BiomePicker;
|
||||
import org.betterx.bclib.interfaces.BiomeChunk;
|
||||
import org.betterx.bclib.interfaces.BiomeMap;
|
||||
import org.betterx.bclib.interfaces.TriConsumer;
|
||||
import org.betterx.bclib.noise.OpenSimplexNoise;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class HexBiomeMap implements BiomeMap {
|
||||
private static final float RAD_INNER = (float) Math.sqrt(3.0) * 0.5F;
|
||||
private static final float COEF = 0.25F * (float) Math.sqrt(3.0);
|
||||
private static final float COEF_HALF = COEF * 0.5F;
|
||||
private static final float SIN = (float) Math.sin(0.4);
|
||||
private static final float COS = (float) Math.cos(0.4);
|
||||
private static final float[] EDGE_CIRCLE_X;
|
||||
private static final float[] EDGE_CIRCLE_Z;
|
||||
|
||||
private final Map<ChunkPos, HexBiomeChunk> chunks = Maps.newConcurrentMap();
|
||||
private final BiomePicker picker;
|
||||
|
||||
private final OpenSimplexNoise[] noises = new OpenSimplexNoise[2];
|
||||
private TriConsumer<Integer, Integer, Integer> processor;
|
||||
private final byte noiseIterations;
|
||||
private final float scale;
|
||||
private final int seed;
|
||||
|
||||
public HexBiomeMap(long seed, int size, BiomePicker picker) {
|
||||
this.picker = picker;
|
||||
this.scale = HexBiomeChunk.scaleMap(size);
|
||||
Random random = new Random(seed);
|
||||
|
||||
noises[0] = new OpenSimplexNoise(random.nextInt());
|
||||
noises[1] = new OpenSimplexNoise(random.nextInt());
|
||||
noiseIterations = (byte) Math.min(Math.ceil(Math.log(scale) / Math.log(2)), 5);
|
||||
this.seed = random.nextInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache() {
|
||||
if (chunks.size() > 127) {
|
||||
chunks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomePicker.ActualBiome getBiome(double x, double y, double z) {
|
||||
BiomePicker.ActualBiome biome = getRawBiome(x, z);
|
||||
BiomePicker.ActualBiome edge = biome.getEdge();
|
||||
int size = biome.bclBiome.getEdgeSize();
|
||||
|
||||
if (edge == null && biome.getParentBiome() != null) {
|
||||
edge = biome.getParentBiome().getEdge();
|
||||
size = biome.getParentBiome().bclBiome.getEdgeSize();
|
||||
}
|
||||
|
||||
if (edge == null) {
|
||||
return biome;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
if (!getRawBiome(x + size * EDGE_CIRCLE_X[i], z + size * EDGE_CIRCLE_Z[i]).isSame(biome)) {
|
||||
return edge;
|
||||
}
|
||||
}
|
||||
|
||||
return biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeChunk getChunk(final int cx, final int cz, final boolean update) {
|
||||
final ChunkPos pos = new ChunkPos(cx, cz);
|
||||
HexBiomeChunk chunk = chunks.get(pos);
|
||||
if (chunk == null) {
|
||||
WorldgenRandom random = new WorldgenRandom(RandomSource.create(MHelper.getSeed(seed, cx, cz)));
|
||||
chunk = new HexBiomeChunk(random, picker);
|
||||
if (update && processor != null) {
|
||||
processor.accept(cx, cz, chunk.getSide());
|
||||
}
|
||||
chunks.put(pos, chunk);
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
private BiomePicker.ActualBiome getRawBiome(double x, double z) {
|
||||
double px = x / scale * RAD_INNER;
|
||||
double pz = z / scale;
|
||||
double dx = rotateX(px, pz);
|
||||
double dz = rotateZ(px, pz);
|
||||
px = dx;
|
||||
pz = dz;
|
||||
|
||||
dx = getNoise(px, pz, (byte) 0) * 0.2F;
|
||||
dz = getNoise(pz, px, (byte) 1) * 0.2F;
|
||||
px += dx;
|
||||
pz += dz;
|
||||
|
||||
int cellZ = (int) Math.floor(pz);
|
||||
boolean offset = (cellZ & 1) == 1;
|
||||
|
||||
if (offset) {
|
||||
px += 0.5;
|
||||
}
|
||||
|
||||
int cellX = (int) Math.floor(px);
|
||||
|
||||
float pointX = (float) (px - cellX - 0.5);
|
||||
float pointZ = (float) (pz - cellZ - 0.5);
|
||||
|
||||
if (Math.abs(pointZ) < 0.3333F) {
|
||||
return getChunkBiome(cellX, cellZ);
|
||||
}
|
||||
|
||||
if (insideHexagon(0, 0, 1.1555F, pointZ * RAD_INNER, pointX)) {
|
||||
return getChunkBiome(cellX, cellZ);
|
||||
}
|
||||
|
||||
cellX = pointX < 0 ? (offset ? cellX - 1 : cellX) : (offset ? cellX : cellX + 1);
|
||||
cellZ = pointZ < 0 ? cellZ - 1 : cellZ + 1;
|
||||
|
||||
return getChunkBiome(cellX, cellZ);
|
||||
}
|
||||
|
||||
private BiomePicker.ActualBiome getChunkBiome(int x, int z) {
|
||||
int cx = HexBiomeChunk.scaleCoordinate(x);
|
||||
int cz = HexBiomeChunk.scaleCoordinate(z);
|
||||
|
||||
if (((z >> 2) & 1) == 0 && HexBiomeChunk.isBorder(x)) {
|
||||
x = 0;
|
||||
cx += 1;
|
||||
} else if (((x >> 2) & 1) == 0 && HexBiomeChunk.isBorder(z)) {
|
||||
z = 0;
|
||||
cz += 1;
|
||||
}
|
||||
|
||||
return getChunk(cx, cz, true).getBiome(x, z);
|
||||
}
|
||||
|
||||
private boolean insideHexagon(float centerX, float centerZ, float radius, float x, float z) {
|
||||
double dx = Math.abs(x - centerX) / radius;
|
||||
double dy = Math.abs(z - centerZ) / radius;
|
||||
return (dy <= COEF) && (COEF * dx + 0.25F * dy <= COEF_HALF);
|
||||
}
|
||||
|
||||
private double getNoise(double x, double z, byte state) {
|
||||
double result = 0;
|
||||
for (byte i = 1; i <= noiseIterations; i++) {
|
||||
OpenSimplexNoise noise = noises[state];
|
||||
state = (byte) ((state + 1) & 1);
|
||||
result += noise.eval(x * i, z * i) / i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private double rotateX(double x, double z) {
|
||||
return x * COS - z * SIN;
|
||||
}
|
||||
|
||||
private double rotateZ(double x, double z) {
|
||||
return x * SIN + z * COS;
|
||||
}
|
||||
|
||||
static {
|
||||
EDGE_CIRCLE_X = new float[8];
|
||||
EDGE_CIRCLE_Z = new float[8];
|
||||
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
float angle = i / 4F * (float) Math.PI;
|
||||
EDGE_CIRCLE_X[i] = (float) Math.sin(angle);
|
||||
EDGE_CIRCLE_Z[i] = (float) Math.cos(angle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package org.betterx.bclib.api.v2.generator.map.square;
|
||||
|
||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||
|
||||
import org.betterx.bclib.api.v2.generator.BiomePicker;
|
||||
import org.betterx.bclib.interfaces.BiomeChunk;
|
||||
|
||||
public class SquareBiomeChunk implements BiomeChunk {
|
||||
private static final int BIT_OFFSET = 4;
|
||||
protected static final int WIDTH = 1 << BIT_OFFSET;
|
||||
private static final int SM_WIDTH = WIDTH >> 1;
|
||||
private static final int SM_BIT_OFFSET = BIT_OFFSET >> 1;
|
||||
private static final int MASK_OFFSET = SM_WIDTH - 1;
|
||||
protected static final int MASK_WIDTH = WIDTH - 1;
|
||||
|
||||
private static final int SM_CAPACITY = SM_WIDTH * SM_WIDTH;
|
||||
private static final int CAPACITY = WIDTH * WIDTH;
|
||||
|
||||
private final BiomePicker.ActualBiome[] biomes;
|
||||
|
||||
public SquareBiomeChunk(WorldgenRandom random, BiomePicker picker) {
|
||||
BiomePicker.ActualBiome[] PreBio = new BiomePicker.ActualBiome[SM_CAPACITY];
|
||||
biomes = new BiomePicker.ActualBiome[CAPACITY];
|
||||
|
||||
for (int x = 0; x < SM_WIDTH; x++) {
|
||||
int offset = x << SM_BIT_OFFSET;
|
||||
for (int z = 0; z < SM_WIDTH; z++) {
|
||||
PreBio[offset | z] = picker.getBiome(random);
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < WIDTH; x++) {
|
||||
int offset = x << BIT_OFFSET;
|
||||
for (int z = 0; z < WIDTH; z++) {
|
||||
biomes[offset | z] = PreBio[getSmIndex(offsetXZ(x, random), offsetXZ(z, random))].getSubBiome(random);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomePicker.ActualBiome getBiome(int x, int z) {
|
||||
return biomes[getIndex(x & MASK_WIDTH, z & MASK_WIDTH)];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, BiomePicker.ActualBiome biome) {
|
||||
biomes[getIndex(x & MASK_WIDTH, z & MASK_WIDTH)] = biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSide() {
|
||||
return WIDTH;
|
||||
}
|
||||
|
||||
private int offsetXZ(int x, WorldgenRandom random) {
|
||||
return ((x + random.nextInt(2)) >> 1) & MASK_OFFSET;
|
||||
}
|
||||
|
||||
private int getIndex(int x, int z) {
|
||||
return x << BIT_OFFSET | z;
|
||||
}
|
||||
|
||||
private int getSmIndex(int x, int z) {
|
||||
return x << SM_BIT_OFFSET | z;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
package org.betterx.bclib.api.v2.generator.map.square;
|
||||
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
||||
import net.minecraft.world.level.levelgen.WorldgenRandom;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.betterx.bclib.api.v2.generator.BiomePicker;
|
||||
import org.betterx.bclib.interfaces.BiomeChunk;
|
||||
import org.betterx.bclib.interfaces.BiomeMap;
|
||||
import org.betterx.bclib.interfaces.TriConsumer;
|
||||
import org.betterx.bclib.noise.OpenSimplexNoise;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SquareBiomeMap implements BiomeMap {
|
||||
private final Map<ChunkPos, SquareBiomeChunk> maps = Maps.newHashMap();
|
||||
private final OpenSimplexNoise noiseX;
|
||||
private final OpenSimplexNoise noiseZ;
|
||||
private final WorldgenRandom random;
|
||||
private final BiomePicker picker;
|
||||
|
||||
private final int sizeXZ;
|
||||
private final int depth;
|
||||
private final int size;
|
||||
|
||||
private TriConsumer<Integer, Integer, Integer> processor;
|
||||
|
||||
public SquareBiomeMap(long seed, int size, BiomePicker picker) {
|
||||
random = new WorldgenRandom(new LegacyRandomSource(seed));
|
||||
noiseX = new OpenSimplexNoise(random.nextLong());
|
||||
noiseZ = new OpenSimplexNoise(random.nextLong());
|
||||
this.sizeXZ = size;
|
||||
depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2;
|
||||
this.size = 1 << depth;
|
||||
this.picker = picker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache() {
|
||||
if (maps.size() > 32) {
|
||||
maps.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomePicker.ActualBiome getBiome(double x, double y, double z) {
|
||||
BiomePicker.ActualBiome biome = getRawBiome(x, z);
|
||||
|
||||
if (biome.getEdge() != null || (biome.getParentBiome() != null && biome.getParentBiome().getEdge() != null)) {
|
||||
BiomePicker.ActualBiome search = biome;
|
||||
if (biome.getParentBiome() != null) {
|
||||
search = biome.getParentBiome();
|
||||
}
|
||||
|
||||
int size = search.bclBiome.getEdgeSize();
|
||||
boolean edge = !search.isSame(getRawBiome(x + size, z));
|
||||
edge = edge || !search.isSame(getRawBiome(x - size, z));
|
||||
edge = edge || !search.isSame(getRawBiome(x, z + size));
|
||||
edge = edge || !search.isSame(getRawBiome(x, z - size));
|
||||
edge = edge || !search.isSame(getRawBiome(x - 1, z - 1));
|
||||
edge = edge || !search.isSame(getRawBiome(x - 1, z + 1));
|
||||
edge = edge || !search.isSame(getRawBiome(x + 1, z - 1));
|
||||
edge = edge || !search.isSame(getRawBiome(x + 1, z + 1));
|
||||
|
||||
if (edge) {
|
||||
biome = search.getEdge();
|
||||
}
|
||||
}
|
||||
|
||||
return biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {
|
||||
this.processor = processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeChunk getChunk(int cx, int cz, boolean update) {
|
||||
ChunkPos cpos = new ChunkPos(cx, cz);
|
||||
SquareBiomeChunk chunk = maps.get(cpos);
|
||||
if (chunk == null) {
|
||||
synchronized (random) {
|
||||
random.setLargeFeatureWithSalt(0, cpos.x, cpos.z, 0);
|
||||
chunk = new SquareBiomeChunk(random, picker);
|
||||
}
|
||||
maps.put(cpos, chunk);
|
||||
|
||||
if (update && processor != null) {
|
||||
processor.accept(cx, cz, chunk.getSide());
|
||||
}
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
private BiomePicker.ActualBiome getRawBiome(double bx, double bz) {
|
||||
double x = bx * size / sizeXZ;
|
||||
double z = bz * size / sizeXZ;
|
||||
|
||||
double px = bx * 0.2;
|
||||
double pz = bz * 0.2;
|
||||
|
||||
for (int i = 0; i < depth; i++) {
|
||||
double nx = (x + noiseX.eval(px, pz)) / 2F;
|
||||
double nz = (z + noiseZ.eval(px, pz)) / 2F;
|
||||
|
||||
x = nx;
|
||||
z = nz;
|
||||
|
||||
px = px / 2 + i;
|
||||
pz = pz / 2 + i;
|
||||
}
|
||||
|
||||
int ix = MHelper.floor(x);
|
||||
int iz = MHelper.floor(z);
|
||||
|
||||
if ((ix & SquareBiomeChunk.MASK_WIDTH) == SquareBiomeChunk.MASK_WIDTH) {
|
||||
x += (iz / 2) & 1;
|
||||
}
|
||||
if ((iz & SquareBiomeChunk.MASK_WIDTH) == SquareBiomeChunk.MASK_WIDTH) {
|
||||
z += (ix / 2) & 1;
|
||||
}
|
||||
|
||||
ChunkPos cpos = new ChunkPos(MHelper.floor(x / SquareBiomeChunk.WIDTH),
|
||||
MHelper.floor(z / SquareBiomeChunk.WIDTH));
|
||||
SquareBiomeChunk chunk = maps.get(cpos);
|
||||
if (chunk == null) {
|
||||
synchronized (random) {
|
||||
random.setLargeFeatureWithSalt(0, cpos.x, cpos.z, 0);
|
||||
chunk = new SquareBiomeChunk(random, picker);
|
||||
}
|
||||
maps.put(cpos, chunk);
|
||||
}
|
||||
|
||||
return chunk.getBiome(MHelper.floor(x), MHelper.floor(z));
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.worldgen;
|
||||
package org.betterx.bclib.api.v2.levelgen;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.MappedRegistry;
|
||||
|
@ -25,21 +25,22 @@ import com.mojang.datafixers.util.Pair;
|
|||
import com.mojang.serialization.Dynamic;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.WorldDataAPI;
|
||||
import org.betterx.bclib.api.v2.WorldDataAPI;
|
||||
import org.betterx.bclib.api.v2.generator.BCLBiomeSource;
|
||||
import org.betterx.bclib.api.v2.generator.BCLChunkGenerator;
|
||||
import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
|
||||
import org.betterx.bclib.api.v2.generator.BCLibNetherBiomeSource;
|
||||
import org.betterx.bclib.mixin.common.RegistryOpsAccessor;
|
||||
import org.betterx.bclib.presets.worldgen.BCLWorldPresetSettings;
|
||||
import org.betterx.bclib.presets.worldgen.BCLWorldPresets;
|
||||
import org.betterx.bclib.presets.worldgen.WorldPresetSettings;
|
||||
import org.betterx.bclib.util.ModUtil;
|
||||
import org.betterx.bclib.world.generator.BCLBiomeSource;
|
||||
import org.betterx.bclib.world.generator.BCLibEndBiomeSource;
|
||||
import org.betterx.bclib.world.generator.BCLibNetherBiomeSource;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class WorldGenUtil {
|
||||
public class LevelGenUtil {
|
||||
private static final String TAG_VERSION = "version";
|
||||
private static final String TAG_BN_GEN_VERSION = "generator_version";
|
||||
private static String TAG_GENERATOR = "generator";
|
||||
|
@ -122,10 +123,10 @@ public class WorldGenUtil {
|
|||
boolean generateStructures,
|
||||
boolean generateBonusChest) {
|
||||
return createWorldFromPreset(BCLWorldPresets.DEFAULT.orElseThrow(),
|
||||
registryAccess,
|
||||
seed,
|
||||
generateStructures,
|
||||
generateBonusChest);
|
||||
registryAccess,
|
||||
seed,
|
||||
generateStructures,
|
||||
generateBonusChest);
|
||||
}
|
||||
|
||||
public static Pair<WorldGenSettings, RegistryAccess.Frozen> defaultWorldDataSupplier(RegistryAccess.Frozen frozen) {
|
||||
|
@ -147,7 +148,7 @@ public class WorldGenUtil {
|
|||
int biomeSourceVersion,
|
||||
RegistryAccess registryAccess,
|
||||
WorldGenSettings worldGenSettings
|
||||
) {
|
||||
) {
|
||||
Optional<Holder<LevelStem>> oLevelStem = referenceStemForVersion(
|
||||
dimensionKey,
|
||||
biomeSourceVersion,
|
||||
|
@ -155,12 +156,12 @@ public class WorldGenUtil {
|
|||
worldGenSettings.seed(),
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateStructures()
|
||||
);
|
||||
);
|
||||
return replaceGenerator(dimensionKey,
|
||||
dimensionTypeKey,
|
||||
registryAccess,
|
||||
worldGenSettings,
|
||||
oLevelStem.map(l -> l.value().generator()).orElseThrow());
|
||||
dimensionTypeKey,
|
||||
registryAccess,
|
||||
worldGenSettings,
|
||||
oLevelStem.map(l -> l.value().generator()).orElseThrow());
|
||||
}
|
||||
|
||||
public static WorldGenSettings replaceGenerator(
|
||||
|
@ -169,31 +170,31 @@ public class WorldGenUtil {
|
|||
RegistryAccess registryAccess,
|
||||
WorldGenSettings worldGenSettings,
|
||||
ChunkGenerator generator
|
||||
) {
|
||||
) {
|
||||
Registry<DimensionType> dimensionTypeRegistry = registryAccess.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
|
||||
Registry<LevelStem> newDimensions = withDimension(dimensionKey,
|
||||
dimensionTypeKey,
|
||||
dimensionTypeRegistry,
|
||||
worldGenSettings.dimensions(),
|
||||
generator);
|
||||
dimensionTypeKey,
|
||||
dimensionTypeRegistry,
|
||||
worldGenSettings.dimensions(),
|
||||
generator);
|
||||
return new WorldGenSettings(worldGenSettings.seed(),
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateBonusChest(),
|
||||
newDimensions);
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateBonusChest(),
|
||||
newDimensions);
|
||||
}
|
||||
|
||||
public static WorldGenSettings replaceStem(
|
||||
ResourceKey<LevelStem> dimensionKey,
|
||||
WorldGenSettings worldGenSettings,
|
||||
LevelStem levelStem
|
||||
) {
|
||||
) {
|
||||
Registry<LevelStem> newDimensions = withDimension(dimensionKey,
|
||||
worldGenSettings.dimensions(),
|
||||
levelStem);
|
||||
worldGenSettings.dimensions(),
|
||||
levelStem);
|
||||
return new WorldGenSettings(worldGenSettings.seed(),
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateBonusChest(),
|
||||
newDimensions);
|
||||
worldGenSettings.generateStructures(),
|
||||
worldGenSettings.generateBonusChest(),
|
||||
newDimensions);
|
||||
}
|
||||
|
||||
public static Registry<LevelStem> withDimension(ResourceKey<LevelStem> dimensionKey,
|
||||
|
@ -213,17 +214,17 @@ public class WorldGenUtil {
|
|||
Registry<LevelStem> inputDimensions,
|
||||
LevelStem levelStem) {
|
||||
MappedRegistry<LevelStem> writableRegistry = new MappedRegistry<>(Registry.LEVEL_STEM_REGISTRY,
|
||||
Lifecycle.experimental(),
|
||||
null);
|
||||
Lifecycle.experimental(),
|
||||
null);
|
||||
writableRegistry.register(dimensionKey,
|
||||
levelStem,
|
||||
Lifecycle.stable());
|
||||
levelStem,
|
||||
Lifecycle.stable());
|
||||
for (Map.Entry<ResourceKey<LevelStem>, LevelStem> entry : inputDimensions.entrySet()) {
|
||||
ResourceKey<LevelStem> resourceKey = entry.getKey();
|
||||
if (resourceKey == dimensionKey) continue;
|
||||
writableRegistry.register(resourceKey,
|
||||
entry.getValue(),
|
||||
inputDimensions.lifecycle(entry.getValue()));
|
||||
entry.getValue(),
|
||||
inputDimensions.lifecycle(entry.getValue()));
|
||||
}
|
||||
return writableRegistry;
|
||||
}
|
||||
|
@ -240,7 +241,7 @@ public class WorldGenUtil {
|
|||
long seed,
|
||||
boolean generateStructures,
|
||||
boolean generateBonusChest
|
||||
) {
|
||||
) {
|
||||
final WorldGenSettings referenceSettings;
|
||||
if (biomeSourceVersion == BCLBiomeSource.BIOME_SOURCE_VERSION_VANILLA) {
|
||||
referenceSettings = net.minecraft.world.level.levelgen.presets.WorldPresets.createNormalWorldFromPreset(
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.biomes;
|
||||
package org.betterx.bclib.api.v2.levelgen.biomes;
|
||||
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
|
@ -14,8 +14,8 @@ import com.google.common.collect.Lists;
|
|||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.surface.SurfaceRuleUtil;
|
||||
import org.betterx.bclib.api.tag.TagAPI;
|
||||
import org.betterx.bclib.api.v2.levelgen.surface.SurfaceRuleUtil;
|
||||
import org.betterx.bclib.api.v2.tag.TagAPI;
|
||||
import org.betterx.bclib.util.WeightedList;
|
||||
|
||||
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.biomes;
|
||||
package org.betterx.bclib.api.v2.levelgen.biomes;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
|
@ -29,9 +29,9 @@ import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.betterx.bclib.api.features.BCLFeature;
|
||||
import org.betterx.bclib.api.structures.BCLStructure;
|
||||
import org.betterx.bclib.api.surface.SurfaceRuleBuilder;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.BCLStructure;
|
||||
import org.betterx.bclib.api.v2.levelgen.surface.SurfaceRuleBuilder;
|
||||
import org.betterx.bclib.entity.BCLEntityWrapper;
|
||||
import org.betterx.bclib.mixin.common.BiomeGenerationSettingsAccessor;
|
||||
import org.betterx.bclib.util.CollectionsUtil;
|
|
@ -1,9 +1,9 @@
|
|||
package org.betterx.bclib.api.biomes;
|
||||
package org.betterx.bclib.api.v2.levelgen.biomes;
|
||||
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
||||
import org.betterx.bclib.api.v2.generator.BiomePicker;
|
||||
import org.betterx.bclib.config.Configs;
|
||||
import org.betterx.bclib.world.generator.BiomePicker;
|
||||
|
||||
public class BCLBiomeSettings {
|
||||
public static Builder createBCL() {
|
|
@ -1,11 +1,13 @@
|
|||
package org.betterx.bclib.api.biomes;
|
||||
package org.betterx.bclib.api.v2.levelgen.biomes;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.tags.BiomeTags;
|
||||
import net.minecraft.util.random.WeightedRandomList;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
|
@ -16,16 +18,13 @@ import net.minecraft.world.level.LevelAccessor;
|
|||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeGenerationSettings;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings.SpawnerData;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.PalettedContainerRO;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
|
||||
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
|
@ -40,28 +39,22 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.features.BCLFeature;
|
||||
import org.betterx.bclib.api.tag.CommonBiomeTags;
|
||||
import org.betterx.bclib.api.tag.TagAPI;
|
||||
import org.betterx.bclib.interfaces.BiomeSourceAccessor;
|
||||
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
|
||||
import org.betterx.bclib.api.v2.tag.CommonBiomeTags;
|
||||
import org.betterx.bclib.api.v2.tag.TagAPI;
|
||||
import org.betterx.bclib.interfaces.SurfaceMaterialProvider;
|
||||
import org.betterx.bclib.interfaces.SurfaceRuleProvider;
|
||||
import org.betterx.bclib.mixin.common.BiomeGenerationSettingsAccessor;
|
||||
import org.betterx.bclib.mixin.common.MobSpawnSettingsAccessor;
|
||||
import org.betterx.bclib.util.CollectionsUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BiomeAPI {
|
||||
|
@ -79,7 +72,7 @@ public class BiomeAPI {
|
|||
public static final BiomeType OTHER_END_LAND = new BiomeType("OTHER_END_LAND", END_LAND);
|
||||
public static final BiomeType OTHER_END_VOID = new BiomeType("OTHER_END_VOID", END_VOID);
|
||||
|
||||
private static final Map<ResourceLocation, BiomeType> BIOME_TYPE_MAP = Maps.newHashMap();
|
||||
static final Map<ResourceLocation, BiomeType> BIOME_TYPE_MAP = Maps.newHashMap();
|
||||
public final BiomeType parentOrNull;
|
||||
private final String debugName;
|
||||
|
||||
|
@ -113,15 +106,6 @@ public class BiomeAPI {
|
|||
public static final BCLBiome EMPTY_BIOME = new BCLBiome(Biomes.THE_VOID.location());
|
||||
|
||||
private static final Map<ResourceLocation, BCLBiome> ID_MAP = Maps.newHashMap();
|
||||
private static final Map<Biome, BCLBiome> CLIENT = Maps.newHashMap();
|
||||
private static Registry<Biome> biomeRegistry;
|
||||
private static RegistryAccess registryAccess;
|
||||
|
||||
private static final Map<Holder<PlacedFeature>, Integer> FEATURE_ORDER = Maps.newHashMap();
|
||||
private static final MutableInt FEATURE_ORDER_ID = new MutableInt(0);
|
||||
|
||||
private static final Map<ResourceKey<LevelStem>, List<BiConsumer<ResourceLocation, Holder<Biome>>>> MODIFICATIONS = Maps.newHashMap();
|
||||
private static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Holder<Biome>>>> TAG_ADDERS = Maps.newHashMap();
|
||||
|
||||
public static final BCLBiome NETHER_WASTES_BIOME = registerNetherBiome(getFromRegistry(Biomes.NETHER_WASTES).value());
|
||||
public static final BCLBiome CRIMSON_FOREST_BIOME = registerNetherBiome(getFromRegistry(Biomes.CRIMSON_FOREST).value());
|
||||
|
@ -141,53 +125,6 @@ public class BiomeAPI {
|
|||
public static final BCLBiome SMALL_END_ISLANDS = registerEndVoidBiome(getFromRegistry(new ResourceLocation(
|
||||
"small_end_islands")));
|
||||
|
||||
private static void initFeatureOrder() {
|
||||
if (!FEATURE_ORDER.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuiltinRegistries.BIOME
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> entry
|
||||
.getKey()
|
||||
.location()
|
||||
.getNamespace()
|
||||
.equals("minecraft"))
|
||||
.map(Entry::getValue)
|
||||
.map(biome -> (BiomeGenerationSettingsAccessor) biome.getGenerationSettings())
|
||||
.map(BiomeGenerationSettingsAccessor::bclib_getFeatures)
|
||||
.forEach(stepFeatureSuppliers -> stepFeatureSuppliers.forEach(step -> step.forEach(feature -> {
|
||||
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
|
||||
})));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize registry for current server.
|
||||
*
|
||||
* @param access - The new, active {@link RegistryAccess} for the current session.
|
||||
*/
|
||||
public static void initRegistry(RegistryAccess access) {
|
||||
if (access != registryAccess) {
|
||||
BiomeAPI.registryAccess = access;
|
||||
Registry<Biome> biomeRegistry = access.registry(Registry.BIOME_REGISTRY).orElse(null);
|
||||
|
||||
if (biomeRegistry != BiomeAPI.biomeRegistry) {
|
||||
BiomeAPI.biomeRegistry = biomeRegistry;
|
||||
CLIENT.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
* <p>
|
||||
* This method gets called before a world is loaded/created to flush cashes we build.
|
||||
*/
|
||||
public static void prepareNewLevel() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@link BCLBiome} instance and its {@link Biome} if necessary.
|
||||
*
|
||||
|
@ -251,7 +188,7 @@ public class BiomeAPI {
|
|||
public static BCLBiome registerNetherBiome(BCLBiome bclBiome) {
|
||||
registerBiome(bclBiome, BiomeType.BCL_NETHER);
|
||||
|
||||
ResourceKey<Biome> key = BiomeAPI.getBiomeKey(bclBiome.getBiome());
|
||||
ResourceKey<Biome> key = getBiomeKey(bclBiome.getBiome());
|
||||
if (bclBiome.allowFabricRegistration()) {
|
||||
bclBiome.forEachClimateParameter(p -> NetherBiomeData.addNetherBiome(key, p));
|
||||
}
|
||||
|
@ -282,7 +219,7 @@ public class BiomeAPI {
|
|||
registerBiome(biome, BiomeType.BCL_END_LAND);
|
||||
|
||||
float weight = biome.getGenChance();
|
||||
ResourceKey<Biome> key = BiomeAPI.getBiomeKey(biome.getBiome());
|
||||
ResourceKey<Biome> key = getBiomeKey(biome.getBiome());
|
||||
if (biome.allowFabricRegistration()) {
|
||||
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_HIGHLANDS, key, weight);
|
||||
TheEndBiomeData.addEndBiomeReplacement(Biomes.END_MIDLANDS, key, weight);
|
||||
|
@ -331,7 +268,7 @@ public class BiomeAPI {
|
|||
registerBiome(biome, BiomeType.END_VOID);
|
||||
|
||||
float weight = biome.getGenChance();
|
||||
ResourceKey<Biome> key = BiomeAPI.getBiomeKey(biome.getBiome());
|
||||
ResourceKey<Biome> key = getBiomeKey(biome.getBiome());
|
||||
if (biome.allowFabricRegistration()) {
|
||||
TheEndBiomeData.addEndBiomeReplacement(Biomes.SMALL_END_ISLANDS, key, weight);
|
||||
}
|
||||
|
@ -375,7 +312,7 @@ public class BiomeAPI {
|
|||
* @return {@link BCLBiome} or {@code BiomeAPI.EMPTY_BIOME}.
|
||||
*/
|
||||
public static BCLBiome getFromBiome(Holder<Biome> biome) {
|
||||
if (biomeRegistry == null) {
|
||||
if (InternalBiomeAPI.biomeRegistry == null) {
|
||||
return EMPTY_BIOME;
|
||||
}
|
||||
return ID_MAP.getOrDefault(biome.unwrapKey().orElseThrow().location(), EMPTY_BIOME);
|
||||
|
@ -389,14 +326,14 @@ public class BiomeAPI {
|
|||
*/
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static BCLBiome getRenderBiome(Biome biome) {
|
||||
BCLBiome endBiome = CLIENT.get(biome);
|
||||
BCLBiome endBiome = InternalBiomeAPI.CLIENT.get(biome);
|
||||
if (endBiome == null) {
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
ResourceLocation id = minecraft.level.registryAccess()
|
||||
.registryOrThrow(Registry.BIOME_REGISTRY)
|
||||
.getKey(biome);
|
||||
endBiome = id == null ? EMPTY_BIOME : ID_MAP.getOrDefault(id, EMPTY_BIOME);
|
||||
CLIENT.put(biome, endBiome);
|
||||
InternalBiomeAPI.CLIENT.put(biome, endBiome);
|
||||
}
|
||||
return endBiome;
|
||||
}
|
||||
|
@ -409,8 +346,8 @@ public class BiomeAPI {
|
|||
*/
|
||||
@Nullable
|
||||
public static ResourceKey getBiomeKey(Biome biome) {
|
||||
if (biomeRegistry != null) {
|
||||
Optional<ResourceKey<Biome>> key = biomeRegistry.getResourceKey(biome);
|
||||
if (InternalBiomeAPI.biomeRegistry != null) {
|
||||
Optional<ResourceKey<Biome>> key = InternalBiomeAPI.biomeRegistry.getResourceKey(biome);
|
||||
if (key.isPresent()) return key.get();
|
||||
}
|
||||
return BuiltinRegistries.BIOME
|
||||
|
@ -426,8 +363,8 @@ public class BiomeAPI {
|
|||
*/
|
||||
public static ResourceLocation getBiomeID(Biome biome) {
|
||||
ResourceLocation id = null;
|
||||
if (biomeRegistry != null) {
|
||||
id = biomeRegistry.getKey(biome);
|
||||
if (InternalBiomeAPI.biomeRegistry != null) {
|
||||
id = InternalBiomeAPI.biomeRegistry.getKey(biome);
|
||||
}
|
||||
if (id == null) {
|
||||
id = BuiltinRegistries.BIOME.getKey(biome);
|
||||
|
@ -468,17 +405,17 @@ public class BiomeAPI {
|
|||
}
|
||||
|
||||
public static Holder<Biome> getBiomeHolder(Biome biome) {
|
||||
if (biomeRegistry != null) {
|
||||
Optional<ResourceKey<Biome>> key = biomeRegistry.getResourceKey(biome);
|
||||
if (key.isPresent()) return biomeRegistry.getOrCreateHolderOrThrow(key.get());
|
||||
if (InternalBiomeAPI.biomeRegistry != null) {
|
||||
Optional<ResourceKey<Biome>> key = InternalBiomeAPI.biomeRegistry.getResourceKey(biome);
|
||||
if (key.isPresent()) return InternalBiomeAPI.biomeRegistry.getOrCreateHolderOrThrow(key.get());
|
||||
}
|
||||
|
||||
return BuiltinRegistries.BIOME.getOrCreateHolderOrThrow(BiomeAPI.getBiomeKey(biome));
|
||||
}
|
||||
|
||||
public static Holder<Biome> getBiomeHolder(ResourceLocation biome) {
|
||||
if (biomeRegistry != null) {
|
||||
return getBiomeHolder(biomeRegistry.get(biome));
|
||||
if (InternalBiomeAPI.biomeRegistry != null) {
|
||||
return getBiomeHolder(InternalBiomeAPI.biomeRegistry.get(biome));
|
||||
}
|
||||
return getBiomeHolder(BuiltinRegistries.BIOME.get(biome));
|
||||
}
|
||||
|
@ -523,38 +460,6 @@ public class BiomeAPI {
|
|||
return ID_MAP.containsKey(biomeID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load biomes from Fabric API. For internal usage only.
|
||||
*/
|
||||
public static void loadFabricAPIBiomes() {
|
||||
FabricBiomesData.NETHER_BIOMES.forEach((key) -> {
|
||||
if (!hasBiome(key.location())) {
|
||||
Optional<Holder<Biome>> optional = BuiltinRegistries.BIOME.getHolder(key);
|
||||
if (optional.isPresent()) {
|
||||
registerNetherBiome(optional.get().value());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
FabricBiomesData.END_LAND_BIOMES.forEach((key, weight) -> {
|
||||
if (!hasBiome(key.location())) {
|
||||
Optional<Holder<Biome>> optional = BuiltinRegistries.BIOME.getHolder(key);
|
||||
if (optional.isPresent()) {
|
||||
registerEndLandBiome(optional.get(), weight);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
FabricBiomesData.END_VOID_BIOMES.forEach((key, weight) -> {
|
||||
if (!hasBiome(key.location())) {
|
||||
Optional<Holder<Biome>> optional = BuiltinRegistries.BIOME.getHolder(key);
|
||||
if (optional.isPresent()) {
|
||||
registerEndVoidBiome(optional.get(), weight);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Holder<Biome> getFromRegistry(ResourceLocation key) {
|
||||
return BuiltinRegistries.BIOME.getHolder(ResourceKey.create(Registry.BIOME_REGISTRY, key)).orElseThrow();
|
||||
|
@ -602,7 +507,8 @@ public class BiomeAPI {
|
|||
*/
|
||||
public static void registerBiomeModification(ResourceKey<LevelStem> dimensionID,
|
||||
BiConsumer<ResourceLocation, Holder<Biome>> modification) {
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.computeIfAbsent(dimensionID,
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = InternalBiomeAPI.MODIFICATIONS.computeIfAbsent(
|
||||
dimensionID,
|
||||
k -> Lists.newArrayList());
|
||||
modifications.add(modification);
|
||||
}
|
||||
|
@ -635,46 +541,25 @@ public class BiomeAPI {
|
|||
}
|
||||
|
||||
/**
|
||||
* For internal use only
|
||||
*/
|
||||
public static void _runBiomeTagAdders() {
|
||||
for (var mod : TAG_ADDERS.entrySet()) {
|
||||
Stream<ResourceLocation> s = null;
|
||||
if (mod.getKey() == Level.NETHER) s = BiomeType.BIOME_TYPE_MAP.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue()
|
||||
.is(BiomeType.NETHER))
|
||||
.map(e -> e.getKey());
|
||||
else if (mod.getKey() == Level.END) s = BiomeType.BIOME_TYPE_MAP.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue().is(BiomeType.END))
|
||||
.map(e -> e.getKey());
|
||||
if (s != null) {
|
||||
s.forEach(id -> {
|
||||
Holder<Biome> biomeHolder = BiomeAPI.getBiomeHolder(id);
|
||||
if (biomeHolder.isBound()) {
|
||||
mod.getValue().forEach(c -> c.accept(id, biomeHolder));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new biome modification for specified dimension. Will work both for mod and datapack biomes.
|
||||
* Registers new biome modification for specified dimension that is executed when all
|
||||
* BiomeTags are finalized by the game during level load. Will work both for mod and
|
||||
* datapack biomes.
|
||||
*
|
||||
* @param dimensionID {@link ResourceLocation} dimension ID, example: Level.OVERWORLD or "minecraft:overworld".
|
||||
* @param modification {@link BiConsumer} with {@link ResourceKey} biome ID and {@link Biome} parameters.
|
||||
*/
|
||||
public static void onFinishingBiomeTags(ResourceKey dimensionID,
|
||||
BiConsumer<ResourceLocation, Holder<Biome>> modification) {
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = TAG_ADDERS.computeIfAbsent(dimensionID,
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = InternalBiomeAPI.TAG_ADDERS.computeIfAbsent(
|
||||
dimensionID,
|
||||
k -> Lists.newArrayList());
|
||||
modifications.add(modification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers new biome modification for the Nether. Will work both for mod and datapack biomes.
|
||||
* Registers new biome modification for the Nether dimension that is executed when all
|
||||
* BiomeTags are finalized by the game during level load. Will work both for mod and
|
||||
* datapack biomes.
|
||||
*
|
||||
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
|
||||
*/
|
||||
|
@ -683,7 +568,9 @@ public class BiomeAPI {
|
|||
}
|
||||
|
||||
/**
|
||||
* Registers new biome modification for the End. Will work both for mod and datapack biomes.
|
||||
* Registers new biome modification for the End that is executed when all
|
||||
* BiomeTags are finalized by the game during level load. Will work both for mod and
|
||||
* datapack biomes.
|
||||
*
|
||||
* @param modification {@link BiConsumer} with {@link ResourceLocation} biome ID and {@link Biome} parameters.
|
||||
*/
|
||||
|
@ -691,91 +578,10 @@ public class BiomeAPI {
|
|||
onFinishingBiomeTags(Level.END, modification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will apply biome modiffications to world, internal usage only.
|
||||
*
|
||||
* @param level
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void applyModificationsDeprecated(ServerLevel level) {
|
||||
//TODO: Now Disabled, because we fix the settings when everything gets loaded
|
||||
if (level != null) return;
|
||||
|
||||
NoiseGeneratorSettings noiseGeneratorSettings = null;
|
||||
final ChunkGenerator chunkGenerator = level.getChunkSource().getGenerator();
|
||||
final BiomeSource source = chunkGenerator.getBiomeSource();
|
||||
final Set<Holder<Biome>> biomes = source.possibleBiomes();
|
||||
|
||||
if (chunkGenerator instanceof NoiseGeneratorSettingsProvider gen)
|
||||
noiseGeneratorSettings = gen.bclib_getNoiseGeneratorSettings();
|
||||
|
||||
// Datapacks (like Amplified Nether)will change the GeneratorSettings upon load, so we will
|
||||
// only use the default Setting for Nether/End if we were unable to find a settings object
|
||||
if (noiseGeneratorSettings == null) {
|
||||
if (level.dimension() == Level.NETHER) {
|
||||
noiseGeneratorSettings = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.NETHER);
|
||||
} else if (level.dimension() == Level.END) {
|
||||
noiseGeneratorSettings = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.END);
|
||||
}
|
||||
}
|
||||
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(level
|
||||
.dimensionTypeRegistration()
|
||||
.unwrapKey()
|
||||
.orElseThrow());
|
||||
for (Holder<Biome> biomeHolder : biomes) {
|
||||
if (biomeHolder.isBound()) {
|
||||
applyModificationsAndUpdateFeatures(modifications, biomeHolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (noiseGeneratorSettings != null) {
|
||||
final SurfaceRuleProvider provider = SurfaceRuleProvider.class.cast(noiseGeneratorSettings);
|
||||
// Multiple Biomes can use the same generator. So we need to keep track of all Biomes that are
|
||||
// Provided by all the BiomeSources that use the same generator.
|
||||
// This happens for example when using the MiningDimensions, which reuses the generator for the
|
||||
// Nethering Dimension
|
||||
//MODIFIED_SURFACE_PROVIDERS.add(provider);
|
||||
provider.bclib_addBiomeSource(source);
|
||||
} else {
|
||||
BCLib.LOGGER.warning("No generator for " + source);
|
||||
}
|
||||
|
||||
((BiomeSourceAccessor) source).bclRebuildFeatures();
|
||||
}
|
||||
|
||||
public static void applyModifications(BiomeSource source, ResourceKey<LevelStem> dimension) {
|
||||
BCLib.LOGGER.info("Apply Modifications for " + dimension.location() + " BiomeSource " + source);
|
||||
/*if (dimension.location().equals(LevelStem.NETHER)){
|
||||
if (source instanceof BCLBiomeSource s) {
|
||||
NetherBiomes.useLegacyGeneration = s.biomeSourceVersion==BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE;
|
||||
}
|
||||
}*/
|
||||
final Set<Holder<Biome>> biomes = source.possibleBiomes();
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(dimension);
|
||||
for (Holder<Biome> biomeHolder : biomes) {
|
||||
if (biomeHolder.isBound()) {
|
||||
applyModificationsAndUpdateFeatures(modifications, biomeHolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void applyModificationsAndUpdateFeatures(List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications,
|
||||
Holder<Biome> biome) {
|
||||
ResourceLocation biomeID = getBiomeID(biome);
|
||||
if (modifications != null) {
|
||||
modifications.forEach(consumer -> {
|
||||
consumer.accept(biomeID, biome);
|
||||
});
|
||||
}
|
||||
|
||||
sortBiomeFeatures(biome);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a unique sort order for all Features of the Biome
|
||||
* Create a unique sort order for all Features of the Biome. This method is automatically called for each Biome
|
||||
* after all biome Modifications were executed.
|
||||
*
|
||||
* @param biome The {@link Biome} to sort the features for
|
||||
*/
|
||||
|
@ -939,7 +745,7 @@ public class BiomeAPI {
|
|||
}
|
||||
|
||||
private static void sortFeatures(List<Holder<PlacedFeature>> features) {
|
||||
initFeatureOrder();
|
||||
InternalBiomeAPI.initFeatureOrder();
|
||||
|
||||
Set<Holder<PlacedFeature>> featuresWithoutDuplicates = Sets.newHashSet();
|
||||
features.forEach(holder -> featuresWithoutDuplicates.add(holder));
|
||||
|
@ -950,12 +756,13 @@ public class BiomeAPI {
|
|||
}
|
||||
|
||||
features.forEach(feature -> {
|
||||
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
|
||||
InternalBiomeAPI.FEATURE_ORDER.computeIfAbsent(feature,
|
||||
f -> InternalBiomeAPI.FEATURE_ORDER_ID.getAndIncrement());
|
||||
});
|
||||
|
||||
features.sort((f1, f2) -> {
|
||||
int v1 = FEATURE_ORDER.getOrDefault(f1, 70000);
|
||||
int v2 = FEATURE_ORDER.getOrDefault(f2, 70000);
|
||||
int v1 = InternalBiomeAPI.FEATURE_ORDER.getOrDefault(f1, 70000);
|
||||
int v2 = InternalBiomeAPI.FEATURE_ORDER.getOrDefault(f2, 70000);
|
||||
return Integer.compare(v1, v2);
|
||||
});
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.biomes;
|
||||
package org.betterx.bclib.api.v2.levelgen.biomes;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
|
@ -0,0 +1,229 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.biomes;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.interfaces.BiomeSourceAccessor;
|
||||
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
|
||||
import org.betterx.bclib.interfaces.SurfaceRuleProvider;
|
||||
import org.betterx.bclib.mixin.common.BiomeGenerationSettingsAccessor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class InternalBiomeAPI {
|
||||
static final Map<Biome, BCLBiome> CLIENT = Maps.newHashMap();
|
||||
static final Map<Holder<PlacedFeature>, Integer> FEATURE_ORDER = Maps.newHashMap();
|
||||
static final MutableInt FEATURE_ORDER_ID = new MutableInt(0);
|
||||
static final Map<ResourceKey<LevelStem>, List<BiConsumer<ResourceLocation, Holder<Biome>>>> MODIFICATIONS = Maps.newHashMap();
|
||||
static final Map<ResourceKey, List<BiConsumer<ResourceLocation, Holder<Biome>>>> TAG_ADDERS = Maps.newHashMap();
|
||||
static Registry<Biome> biomeRegistry;
|
||||
static RegistryAccess registryAccess;
|
||||
|
||||
static void initFeatureOrder() {
|
||||
if (!FEATURE_ORDER.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BuiltinRegistries.BIOME
|
||||
.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> entry
|
||||
.getKey()
|
||||
.location()
|
||||
.getNamespace()
|
||||
.equals("minecraft"))
|
||||
.map(Map.Entry::getValue)
|
||||
.map(biome -> (BiomeGenerationSettingsAccessor) biome.getGenerationSettings())
|
||||
.map(BiomeGenerationSettingsAccessor::bclib_getFeatures)
|
||||
.forEach(stepFeatureSuppliers -> stepFeatureSuppliers.forEach(step -> step.forEach(feature -> {
|
||||
FEATURE_ORDER.computeIfAbsent(feature, f -> FEATURE_ORDER_ID.getAndIncrement());
|
||||
})));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize registry for current server.
|
||||
*
|
||||
* @param access - The new, active {@link RegistryAccess} for the current session.
|
||||
*/
|
||||
public static void initRegistry(RegistryAccess access) {
|
||||
if (access != registryAccess) {
|
||||
registryAccess = access;
|
||||
Registry<Biome> biomeRegistry = access.registry(Registry.BIOME_REGISTRY).orElse(null);
|
||||
|
||||
if (biomeRegistry != InternalBiomeAPI.biomeRegistry) {
|
||||
InternalBiomeAPI.biomeRegistry = biomeRegistry;
|
||||
CLIENT.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
* <p>
|
||||
* This method gets called before a world is loaded/created to flush cashes we build.
|
||||
*/
|
||||
public static void prepareNewLevel() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Load biomes from Fabric API. For internal usage only.
|
||||
*/
|
||||
public static void loadFabricAPIBiomes() {
|
||||
FabricBiomesData.NETHER_BIOMES.forEach((key) -> {
|
||||
if (!BiomeAPI.hasBiome(key.location())) {
|
||||
Optional<Holder<Biome>> optional = BuiltinRegistries.BIOME.getHolder(key);
|
||||
if (optional.isPresent()) {
|
||||
BiomeAPI.registerNetherBiome(optional.get().value());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
FabricBiomesData.END_LAND_BIOMES.forEach((key, weight) -> {
|
||||
if (!BiomeAPI.hasBiome(key.location())) {
|
||||
Optional<Holder<Biome>> optional = BuiltinRegistries.BIOME.getHolder(key);
|
||||
if (optional.isPresent()) {
|
||||
BiomeAPI.registerEndLandBiome(optional.get(), weight);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
FabricBiomesData.END_VOID_BIOMES.forEach((key, weight) -> {
|
||||
if (!BiomeAPI.hasBiome(key.location())) {
|
||||
Optional<Holder<Biome>> optional = BuiltinRegistries.BIOME.getHolder(key);
|
||||
if (optional.isPresent()) {
|
||||
BiomeAPI.registerEndVoidBiome(optional.get(), weight);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* For internal use only
|
||||
*/
|
||||
public static void _runBiomeTagAdders() {
|
||||
for (var mod : TAG_ADDERS.entrySet()) {
|
||||
Stream<ResourceLocation> s = null;
|
||||
if (mod.getKey() == Level.NETHER) s = BiomeAPI.BiomeType.BIOME_TYPE_MAP.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue()
|
||||
.is(BiomeAPI.BiomeType.NETHER))
|
||||
.map(e -> e.getKey());
|
||||
else if (mod.getKey() == Level.END) s = BiomeAPI.BiomeType.BIOME_TYPE_MAP.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue().is(
|
||||
BiomeAPI.BiomeType.END))
|
||||
.map(e -> e.getKey());
|
||||
if (s != null) {
|
||||
s.forEach(id -> {
|
||||
Holder<Biome> biomeHolder = BiomeAPI.getBiomeHolder(id);
|
||||
if (biomeHolder.isBound()) {
|
||||
mod.getValue().forEach(c -> c.accept(id, biomeHolder));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will apply biome modifications to world, internal usage only.
|
||||
*
|
||||
* @param level
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void applyModificationsDeprecated(ServerLevel level) {
|
||||
//TODO: Now Disabled, because we fix the settings when everything gets loaded
|
||||
if (level != null) return;
|
||||
|
||||
NoiseGeneratorSettings noiseGeneratorSettings = null;
|
||||
final ChunkGenerator chunkGenerator = level.getChunkSource().getGenerator();
|
||||
final BiomeSource source = chunkGenerator.getBiomeSource();
|
||||
final Set<Holder<Biome>> biomes = source.possibleBiomes();
|
||||
|
||||
if (chunkGenerator instanceof NoiseGeneratorSettingsProvider gen)
|
||||
noiseGeneratorSettings = gen.bclib_getNoiseGeneratorSettings();
|
||||
|
||||
// Datapacks (like Amplified Nether)will change the GeneratorSettings upon load, so we will
|
||||
// only use the default Setting for Nether/End if we were unable to find a settings object
|
||||
if (noiseGeneratorSettings == null) {
|
||||
if (level.dimension() == Level.NETHER) {
|
||||
noiseGeneratorSettings = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.NETHER);
|
||||
} else if (level.dimension() == Level.END) {
|
||||
noiseGeneratorSettings = BuiltinRegistries.NOISE_GENERATOR_SETTINGS.get(NoiseGeneratorSettings.END);
|
||||
}
|
||||
}
|
||||
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(level
|
||||
.dimensionTypeRegistration()
|
||||
.unwrapKey()
|
||||
.orElseThrow());
|
||||
for (Holder<Biome> biomeHolder : biomes) {
|
||||
if (biomeHolder.isBound()) {
|
||||
applyModificationsAndUpdateFeatures(modifications, biomeHolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (noiseGeneratorSettings != null) {
|
||||
final SurfaceRuleProvider provider = SurfaceRuleProvider.class.cast(noiseGeneratorSettings);
|
||||
// Multiple Biomes can use the same generator. So we need to keep track of all Biomes that are
|
||||
// Provided by all the BiomeSources that use the same generator.
|
||||
// This happens for example when using the MiningDimensions, which reuses the generator for the
|
||||
// Nethering Dimension
|
||||
//MODIFIED_SURFACE_PROVIDERS.add(provider);
|
||||
provider.bclib_addBiomeSource(source);
|
||||
} else {
|
||||
BCLib.LOGGER.warning("No generator for " + source);
|
||||
}
|
||||
|
||||
((BiomeSourceAccessor) source).bclRebuildFeatures();
|
||||
}
|
||||
|
||||
public static void applyModifications(BiomeSource source, ResourceKey<LevelStem> dimension) {
|
||||
BCLib.LOGGER.info("Apply Modifications for " + dimension.location() + " BiomeSource " + source);
|
||||
/*if (dimension.location().equals(LevelStem.NETHER)){
|
||||
if (source instanceof BCLBiomeSource s) {
|
||||
NetherBiomes.useLegacyGeneration = s.biomeSourceVersion==BCLBiomeSource.BIOME_SOURCE_VERSION_SQUARE;
|
||||
}
|
||||
}*/
|
||||
final Set<Holder<Biome>> biomes = source.possibleBiomes();
|
||||
List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications = MODIFICATIONS.get(dimension);
|
||||
for (Holder<Biome> biomeHolder : biomes) {
|
||||
if (biomeHolder.isBound()) {
|
||||
applyModificationsAndUpdateFeatures(modifications, biomeHolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyModificationsAndUpdateFeatures(List<BiConsumer<ResourceLocation, Holder<Biome>>> modifications,
|
||||
Holder<Biome> biome) {
|
||||
ResourceLocation biomeID = BiomeAPI.getBiomeID(biome);
|
||||
if (modifications != null) {
|
||||
modifications.forEach(consumer -> {
|
||||
consumer.accept(biomeID, biome);
|
||||
});
|
||||
}
|
||||
|
||||
BiomeAPI.sortBiomeFeatures(biome);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.biomes;
|
||||
package org.betterx.bclib.api.v2.levelgen.biomes;
|
||||
|
||||
|
||||
public class VanillaBiomeSettings extends BCLBiomeSettings {
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
|
@ -17,7 +17,7 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
|||
import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
import org.betterx.bclib.api.features.config.*;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.*;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
|
@ -18,7 +18,8 @@ import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvi
|
|||
import net.minecraft.world.level.levelgen.placement.*;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
|
||||
import org.betterx.bclib.api.features.placement.*;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.placement.*;
|
||||
import org.betterx.bclib.api.v2.tag.CommonBlockTags;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -324,7 +325,7 @@ public class BCLFeatureBuilder<FC extends FeatureConfiguration, F extends Featur
|
|||
/**
|
||||
* Cast a ray with max {@code distance} length to find the next solid Block. The ray will travel through replaceable
|
||||
* Blocks (see {@link Material#isReplaceable()}) and will be accepted if it hits a block with the
|
||||
* {@link org.betterx.bclib.api.tag.CommonBlockTags#TERRAIN}-tag
|
||||
* {@link CommonBlockTags#TERRAIN}-tag
|
||||
*
|
||||
* @param dir The direction the ray is cast
|
||||
* @param distance The maximum search Distance
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
|
@ -9,7 +9,7 @@ import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
|||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementContext;
|
||||
|
||||
import org.betterx.bclib.api.features.config.ConditionFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.ConditionFeatureConfig;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.valueproviders.UniformInt;
|
||||
|
@ -14,8 +14,8 @@ import net.minecraft.world.level.levelgen.feature.configurations.SimpleBlockConf
|
|||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.RandomizedIntStateProvider;
|
||||
|
||||
import org.betterx.bclib.api.features.config.PlaceFacingBlockConfig;
|
||||
import org.betterx.bclib.api.features.config.ScatterFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.PlaceFacingBlockConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.ScatterFeatureConfig;
|
||||
|
||||
public class FastFeatures {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
|
@ -21,10 +21,10 @@ import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
|||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.tag.CommonBlockTags;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.templatesystem.DestructionStructureProcessor;
|
||||
import org.betterx.bclib.api.v2.tag.CommonBlockTags;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.bclib.world.processors.DestructionStructureProcessor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
|
@ -1,10 +1,10 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.api.features.config.PlaceBlockFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.PlaceBlockFeatureConfig;
|
||||
|
||||
public class PlaceBlockFeature<FC extends PlaceBlockFeatureConfig> extends Feature<FC> {
|
||||
public PlaceBlockFeature(Codec<FC> codec) {
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
|
@ -21,8 +21,8 @@ import net.minecraft.world.level.levelgen.feature.configurations.SimpleRandomFea
|
|||
import net.minecraft.world.level.levelgen.placement.*;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.api.features.config.ScatterFeatureConfig;
|
||||
import org.betterx.bclib.api.tag.CommonBlockTags;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.ScatterFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.tag.CommonBlockTags;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
|
||||
import java.util.ArrayList;
|
|
@ -1,9 +1,9 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
|
||||
import org.betterx.bclib.api.features.config.SequenceFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.SequenceFeatureConfig;
|
||||
|
||||
public class SequenceFeature extends Feature<SequenceFeatureConfig> {
|
||||
public SequenceFeature() {
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
@ -7,9 +7,9 @@ import net.minecraft.world.level.levelgen.feature.Feature;
|
|||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.api.features.config.TemplateFeatureConfig;
|
||||
import org.betterx.bclib.world.structures.StructureNBT;
|
||||
import org.betterx.bclib.world.structures.StructureWorldNBT;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.config.TemplateFeatureConfig;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.StructureNBT;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT;
|
||||
|
||||
public class TemplateFeature<FC extends TemplateFeatureConfig> extends Feature<FC> {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features;
|
||||
package org.betterx.bclib.api.v2.levelgen.features;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.blockpredicates;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.blockpredicates;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.blockpredicates;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.blockpredicates;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.config;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
|
@ -8,7 +8,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementModifier;
|
|||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.api.features.BCLFeature;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.jetbrains.annotations.NotNull;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.config;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.config;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.config;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.config;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
|
@ -8,7 +8,7 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
|||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.api.features.BCLFeature;
|
||||
import org.betterx.bclib.api.v2.levelgen.features.BCLFeature;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.config;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.config;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
|
@ -6,8 +6,8 @@ import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfigur
|
|||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.world.structures.StructurePlacementType;
|
||||
import org.betterx.bclib.world.structures.StructureWorldNBT;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.StructurePlacementType;
|
||||
import org.betterx.bclib.api.v2.levelgen.structures.StructureWorldNBT;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
||||
|
@ -25,7 +25,7 @@ public class IsEmptyAboveSampledFilter extends PlacementFilter {
|
|||
.group(
|
||||
Codec.intRange(-32, 32).fieldOf("d1").orElse(4).forGetter((p) -> p.distance1),
|
||||
Codec.intRange(-32, 32).fieldOf("d2").orElse(2).forGetter((p) -> p.distance1)
|
||||
)
|
||||
)
|
||||
.apply(instance, IsEmptyAboveSampledFilter::new));
|
||||
|
||||
public static PlacementFilter emptyAbove4() {
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.ExtraCodecs;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.features.placement;
|
||||
package org.betterx.bclib.api.v2.levelgen.features.placement;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.util.RandomSource;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.structures;
|
||||
package org.betterx.bclib.api.v2.levelgen.structures;
|
||||
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.data.BuiltinRegistries;
|
||||
|
@ -14,7 +14,7 @@ import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.api.biomes.BCLBiomeBuilder;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeBuilder;
|
||||
import org.betterx.bclib.mixin.common.StructuresAccessor;
|
||||
|
||||
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.structures;
|
||||
package org.betterx.bclib.api.v2.levelgen.structures;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
|
@ -11,7 +11,7 @@ import net.minecraft.world.level.levelgen.structure.placement.RandomSpreadType;
|
|||
import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import org.betterx.bclib.api.tag.TagAPI;
|
||||
import org.betterx.bclib.api.v2.tag.TagAPI;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.structures;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
public class StructureNBT {
|
||||
public final ResourceLocation location;
|
||||
protected StructureTemplate structure;
|
||||
|
||||
|
||||
protected StructureNBT(ResourceLocation location) {
|
||||
this.location = location;
|
||||
this.structure = readStructureFromJar(location);
|
||||
}
|
||||
|
||||
protected StructureNBT(ResourceLocation location, StructureTemplate structure) {
|
||||
this.location = location;
|
||||
this.structure = structure;
|
||||
}
|
||||
|
||||
public static Rotation getRandomRotation(RandomSource random) {
|
||||
return Rotation.getRandom(random);
|
||||
}
|
||||
|
||||
public static Mirror getRandomMirror(RandomSource random) {
|
||||
return Mirror.values()[random.nextInt(3)];
|
||||
}
|
||||
|
||||
private static final Map<ResourceLocation, StructureNBT> STRUCTURE_CACHE = Maps.newHashMap();
|
||||
|
||||
public static StructureNBT create(ResourceLocation location) {
|
||||
return STRUCTURE_CACHE.computeIfAbsent(location, r -> new StructureNBT(r));
|
||||
}
|
||||
|
||||
public boolean generateCentered(ServerLevelAccessor world, BlockPos pos, Rotation rotation, Mirror mirror) {
|
||||
if (structure == null) {
|
||||
BCLib.LOGGER.error("No structure: " + location.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
MutableBlockPos blockpos2 = new MutableBlockPos().set(structure.getSize());
|
||||
if (mirror == Mirror.FRONT_BACK)
|
||||
blockpos2.setX(-blockpos2.getX());
|
||||
if (mirror == Mirror.LEFT_RIGHT)
|
||||
blockpos2.setZ(-blockpos2.getZ());
|
||||
blockpos2.set(blockpos2.rotate(rotation));
|
||||
StructurePlaceSettings data = new StructurePlaceSettings().setRotation(rotation).setMirror(mirror);
|
||||
BlockPos newPos = pos.offset(-blockpos2.getX() >> 1, 0, -blockpos2.getZ() >> 1);
|
||||
structure.placeInWorld(
|
||||
world,
|
||||
newPos,
|
||||
newPos,
|
||||
data,
|
||||
world.getRandom(),
|
||||
Block.UPDATE_CLIENTS
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final Map<ResourceLocation, StructureTemplate> READER_CACHE = Maps.newHashMap();
|
||||
|
||||
private static StructureTemplate readStructureFromJar(ResourceLocation resource) {
|
||||
return READER_CACHE.computeIfAbsent(resource, r -> _readStructureFromJar(r));
|
||||
}
|
||||
|
||||
private static StructureTemplate _readStructureFromJar(ResourceLocation resource) {
|
||||
String ns = resource.getNamespace();
|
||||
String nm = resource.getPath();
|
||||
|
||||
try {
|
||||
InputStream inputstream = MinecraftServer.class.getResourceAsStream("/data/" + ns + "/structures/" + nm + ".nbt");
|
||||
return readStructureFromStream(inputstream);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static StructureTemplate readStructureFromStream(InputStream stream) throws IOException {
|
||||
CompoundTag nbttagcompound = NbtIo.readCompressed(stream);
|
||||
|
||||
StructureTemplate template = new StructureTemplate();
|
||||
template.load(nbttagcompound);
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
public BlockPos getSize(Rotation rotation) {
|
||||
if (rotation == Rotation.NONE || rotation == Rotation.CLOCKWISE_180)
|
||||
return new BlockPos(structure.getSize());
|
||||
else {
|
||||
Vec3i size = structure.getSize();
|
||||
int x = size.getX();
|
||||
int z = size.getZ();
|
||||
return new BlockPos(z, size.getY(), x);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return location.getPath();
|
||||
}
|
||||
|
||||
public BoundingBox getBoundingBox(BlockPos pos, Rotation rotation, Mirror mirror) {
|
||||
return structure.getBoundingBox(new StructurePlaceSettings().setRotation(rotation).setMirror(mirror), pos);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.structures;
|
||||
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
public enum StructurePlacementType implements StringRepresentable {
|
||||
FLOOR, WALL, CEIL, LAVA, UNDER;
|
||||
|
||||
public static final Codec<StructurePlacementType> CODEC = StringRepresentable.fromEnum(StructurePlacementType::values);
|
||||
|
||||
public String getName() {
|
||||
return this.getSerializedName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSerializedName() {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.structures;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class StructureWorld {
|
||||
private final Map<ChunkPos, Part> parts = Maps.newHashMap();
|
||||
private ChunkPos lastPos;
|
||||
private Part lastPart;
|
||||
private int minX = Integer.MAX_VALUE;
|
||||
private int minY = Integer.MAX_VALUE;
|
||||
private int minZ = Integer.MAX_VALUE;
|
||||
private int maxX = Integer.MIN_VALUE;
|
||||
private int maxY = Integer.MIN_VALUE;
|
||||
private int maxZ = Integer.MIN_VALUE;
|
||||
|
||||
public StructureWorld() {
|
||||
}
|
||||
|
||||
public StructureWorld(CompoundTag tag) {
|
||||
minX = tag.getInt("minX");
|
||||
maxX = tag.getInt("maxX");
|
||||
minY = tag.getInt("minY");
|
||||
maxY = tag.getInt("maxY");
|
||||
minZ = tag.getInt("minZ");
|
||||
maxZ = tag.getInt("maxZ");
|
||||
|
||||
ListTag map = tag.getList("parts", 10);
|
||||
map.forEach((element) -> {
|
||||
CompoundTag compound = (CompoundTag) element;
|
||||
Part part = new Part(compound);
|
||||
int x = compound.getInt("x");
|
||||
int z = compound.getInt("z");
|
||||
parts.put(new ChunkPos(x, z), part);
|
||||
});
|
||||
}
|
||||
|
||||
public void setBlock(BlockPos pos, BlockState state) {
|
||||
ChunkPos cPos = new ChunkPos(pos);
|
||||
|
||||
if (cPos.equals(lastPos)) {
|
||||
lastPart.addBlock(pos, state);
|
||||
return;
|
||||
}
|
||||
|
||||
Part part = parts.get(cPos);
|
||||
if (part == null) {
|
||||
part = new Part();
|
||||
parts.put(cPos, part);
|
||||
|
||||
if (cPos.x < minX) minX = cPos.x;
|
||||
if (cPos.x > maxX) maxX = cPos.x;
|
||||
if (cPos.z < minZ) minZ = cPos.z;
|
||||
if (cPos.z > maxZ) maxZ = cPos.z;
|
||||
}
|
||||
if (pos.getY() < minY) minY = pos.getY();
|
||||
if (pos.getY() > maxY) maxY = pos.getY();
|
||||
part.addBlock(pos, state);
|
||||
|
||||
lastPos = cPos;
|
||||
lastPart = part;
|
||||
}
|
||||
|
||||
public boolean placeChunk(WorldGenLevel world, ChunkPos chunkPos) {
|
||||
Part part = parts.get(chunkPos);
|
||||
if (part != null) {
|
||||
ChunkAccess chunk = world.getChunk(chunkPos.x, chunkPos.z);
|
||||
part.placeChunk(chunk);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public CompoundTag toBNT() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("minX", minX);
|
||||
tag.putInt("maxX", maxX);
|
||||
tag.putInt("minY", minY);
|
||||
tag.putInt("maxY", maxY);
|
||||
tag.putInt("minZ", minZ);
|
||||
tag.putInt("maxZ", maxZ);
|
||||
ListTag map = new ListTag();
|
||||
tag.put("parts", map);
|
||||
parts.forEach((pos, part) -> {
|
||||
map.add(part.toNBT(pos.x, pos.z));
|
||||
});
|
||||
return tag;
|
||||
}
|
||||
|
||||
public BoundingBox getBounds() {
|
||||
if (minX == Integer.MAX_VALUE || maxX == Integer.MIN_VALUE || minZ == Integer.MAX_VALUE || maxZ == Integer.MIN_VALUE) {
|
||||
return BoundingBox.infinite();
|
||||
}
|
||||
return new BoundingBox(minX << 4, minY, minZ << 4, (maxX << 4) | 15, maxY, (maxZ << 4) | 15);
|
||||
}
|
||||
|
||||
private static final class Part {
|
||||
Map<BlockPos, BlockState> blocks = Maps.newHashMap();
|
||||
|
||||
public Part() {
|
||||
}
|
||||
|
||||
public Part(CompoundTag tag) {
|
||||
ListTag map = tag.getList("blocks", 10);
|
||||
ListTag map2 = tag.getList("states", 10);
|
||||
BlockState[] states = new BlockState[map2.size()];
|
||||
for (int i = 0; i < states.length; i++) {
|
||||
states[i] = NbtUtils.readBlockState((CompoundTag) map2.get(i));
|
||||
}
|
||||
|
||||
map.forEach((element) -> {
|
||||
CompoundTag block = (CompoundTag) element;
|
||||
BlockPos pos = NbtUtils.readBlockPos(block.getCompound("pos"));
|
||||
int stateID = block.getInt("state");
|
||||
BlockState state = stateID < states.length ? states[stateID] : Block.stateById(stateID);
|
||||
blocks.put(pos, state);
|
||||
});
|
||||
}
|
||||
|
||||
void addBlock(BlockPos pos, BlockState state) {
|
||||
BlockPos inner = new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15);
|
||||
blocks.put(inner, state);
|
||||
}
|
||||
|
||||
void placeChunk(ChunkAccess chunk) {
|
||||
blocks.forEach((pos, state) -> {
|
||||
chunk.setBlockState(pos, state, false);
|
||||
});
|
||||
}
|
||||
|
||||
CompoundTag toNBT(int x, int z) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("x", x);
|
||||
tag.putInt("z", z);
|
||||
ListTag map = new ListTag();
|
||||
tag.put("blocks", map);
|
||||
ListTag stateMap = new ListTag();
|
||||
tag.put("states", stateMap);
|
||||
|
||||
int[] id = new int[1];
|
||||
Map<BlockState, Integer> states = Maps.newHashMap();
|
||||
|
||||
blocks.forEach((pos, state) -> {
|
||||
int stateID = states.getOrDefault(states, -1);
|
||||
if (stateID < 0) {
|
||||
stateID = id[0]++;
|
||||
states.put(state, stateID);
|
||||
stateMap.add(NbtUtils.writeBlockState(state));
|
||||
}
|
||||
|
||||
CompoundTag block = new CompoundTag();
|
||||
block.put("pos", NbtUtils.writeBlockPos(pos));
|
||||
block.putInt("state", stateID);
|
||||
map.add(block);
|
||||
});
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,272 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.structures;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class StructureWorldNBT extends StructureNBT {
|
||||
public static final Codec<StructureWorldNBT> CODEC =
|
||||
RecordCodecBuilder.create((instance) ->
|
||||
instance.group(
|
||||
ResourceLocation.CODEC
|
||||
.fieldOf("location")
|
||||
.forGetter((cfg) -> cfg.location),
|
||||
|
||||
Codec
|
||||
.INT
|
||||
.fieldOf("offset_y")
|
||||
.orElse(0)
|
||||
.forGetter((cfg) -> cfg.offsetY),
|
||||
|
||||
StructurePlacementType.CODEC
|
||||
.fieldOf("placement")
|
||||
.orElse(StructurePlacementType.FLOOR)
|
||||
.forGetter((cfg) -> cfg.type),
|
||||
Codec
|
||||
.FLOAT
|
||||
.fieldOf("chance")
|
||||
.orElse(1.0f)
|
||||
.forGetter((cfg) -> cfg.chance)
|
||||
)
|
||||
.apply(instance, StructureWorldNBT::new)
|
||||
);
|
||||
|
||||
public final StructurePlacementType type;
|
||||
public final int offsetY;
|
||||
public final float chance;
|
||||
|
||||
protected StructureWorldNBT(ResourceLocation location, int offsetY, StructurePlacementType type, float chance) {
|
||||
super(location);
|
||||
this.offsetY = offsetY;
|
||||
this.type = type;
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
private static final Map<String, StructureWorldNBT> READER_CACHE = Maps.newHashMap();
|
||||
|
||||
public static StructureWorldNBT create(ResourceLocation location, int offsetY, StructurePlacementType type) {
|
||||
return create(location, offsetY, type, 1.0f);
|
||||
}
|
||||
|
||||
public static StructureWorldNBT create(ResourceLocation location,
|
||||
int offsetY,
|
||||
StructurePlacementType type,
|
||||
float chance) {
|
||||
String key = location.toString() + "::" + offsetY + "::" + type.getSerializedName();
|
||||
return READER_CACHE.computeIfAbsent(key, r -> new StructureWorldNBT(location, offsetY, type, chance));
|
||||
}
|
||||
|
||||
public boolean generateIfPlaceable(ServerLevelAccessor level,
|
||||
BlockPos pos,
|
||||
RandomSource random
|
||||
) {
|
||||
return generateIfPlaceable(level,
|
||||
pos,
|
||||
getRandomRotation(random),
|
||||
getRandomMirror(random)
|
||||
);
|
||||
}
|
||||
|
||||
public boolean generateIfPlaceable(ServerLevelAccessor level,
|
||||
BlockPos pos,
|
||||
Rotation r,
|
||||
Mirror m) {
|
||||
if (canGenerate(level, pos, r)) {
|
||||
return generate(level, pos, r, m);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean generate(ServerLevelAccessor level, BlockPos pos, Rotation r, Mirror m) {
|
||||
return generateCentered(level, pos.above(offsetY), r, m);
|
||||
}
|
||||
|
||||
protected boolean canGenerate(LevelAccessor level, BlockPos pos, Rotation rotation) {
|
||||
if (type == StructurePlacementType.FLOOR)
|
||||
return canGenerateFloor(level, pos, rotation);
|
||||
else if (type == StructurePlacementType.LAVA)
|
||||
return canGenerateLava(level, pos, rotation);
|
||||
else if (type == StructurePlacementType.UNDER)
|
||||
return canGenerateUnder(level, pos, rotation);
|
||||
else if (type == StructurePlacementType.CEIL)
|
||||
return canGenerateCeil(level, pos, rotation);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean containsBedrock(LevelAccessor level, BlockPos startPos) {
|
||||
for (int i = 0; i < this.structure.getSize().getY(); i += 2) {
|
||||
if (level.getBlockState(startPos.above(i)).is(Blocks.BEDROCK)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean canGenerateFloorFreeAbove(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getAirFractionFoundation(world, pos, rotation) < 0.5
|
||||
&& world.getBlockState(pos.above(2)).is(Blocks.AIR)
|
||||
&& world.getBlockState(pos.above(4)).is(Blocks.AIR);
|
||||
}
|
||||
|
||||
protected boolean canGenerateFloor(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getAirFraction(world, pos, rotation) > 0.6 && getAirFractionFoundation(world, pos, rotation) < 0.5;
|
||||
}
|
||||
|
||||
protected boolean canGenerateLava(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getLavaFractionFoundation(world, pos, rotation) > 0.9 && getAirFraction(world, pos, rotation) > 0.9;
|
||||
}
|
||||
|
||||
protected boolean canGenerateUnder(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getAirFraction(world, pos, rotation) < 0.2;
|
||||
}
|
||||
|
||||
protected boolean canGenerateCeil(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
if (containsBedrock(world, pos)) return false;
|
||||
|
||||
return getAirFractionBottom(world, pos, rotation) > 0.8 && getAirFraction(world, pos, rotation) < 0.6;
|
||||
}
|
||||
|
||||
public BoundingBox boundingBox(Rotation r, BlockPos p) {
|
||||
return getBoundingBox(p, r, Mirror.NONE);
|
||||
}
|
||||
|
||||
protected float getAirFraction(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
final MutableBlockPos POS = new MutableBlockPos();
|
||||
int airCount = 0;
|
||||
|
||||
MutableBlockPos size = new MutableBlockPos().set(new BlockPos(structure.getSize()).rotate(rotation));
|
||||
size.setX(Math.abs(size.getX()) >> 1);
|
||||
size.setZ(Math.abs(size.getZ()) >> 1);
|
||||
|
||||
BlockPos start = pos.offset(-size.getX(), 0, -size.getZ());
|
||||
BlockPos end = pos.offset(size.getX(), size.getY() + offsetY, size.getZ());
|
||||
int count = 0;
|
||||
|
||||
for (int x = start.getX(); x <= end.getX(); x++) {
|
||||
POS.setX(x);
|
||||
for (int y = start.getY(); y <= end.getY(); y++) {
|
||||
POS.setY(y);
|
||||
for (int z = start.getZ(); z <= end.getZ(); z++) {
|
||||
POS.setZ(z);
|
||||
if (world.isEmptyBlock(POS))
|
||||
airCount++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (float) airCount / count;
|
||||
}
|
||||
|
||||
private float getLavaFractionFoundation(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
final MutableBlockPos POS = new MutableBlockPos();
|
||||
int lavaCount = 0;
|
||||
|
||||
MutableBlockPos size = new MutableBlockPos().set(new BlockPos(structure.getSize()).rotate(rotation));
|
||||
size.setX(Math.abs(size.getX()) >> 1);
|
||||
size.setZ(Math.abs(size.getZ()) >> 1);
|
||||
|
||||
BlockPos start = pos.offset(-(size.getX()), 0, -(size.getZ()));
|
||||
BlockPos end = pos.offset(size.getX(), 0, size.getZ());
|
||||
int count = 0;
|
||||
|
||||
POS.setY(pos.getY() - 1);
|
||||
for (int x = start.getX(); x <= end.getX(); x++) {
|
||||
POS.setX(x);
|
||||
for (int z = start.getZ(); z <= end.getZ(); z++) {
|
||||
POS.setZ(z);
|
||||
|
||||
if (BlocksHelper.isLava(world.getBlockState(POS)))
|
||||
lavaCount++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return (float) lavaCount / count;
|
||||
}
|
||||
|
||||
private float getAirFractionFoundation(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
final MutableBlockPos POS = new MutableBlockPos();
|
||||
int airCount = 0;
|
||||
|
||||
MutableBlockPos size = new MutableBlockPos().set(new BlockPos(structure.getSize()).rotate(rotation));
|
||||
size.setX(Math.abs(size.getX()) >> 1);
|
||||
size.setZ(Math.abs(size.getZ()) >> 1);
|
||||
|
||||
BlockPos start = pos.offset(-(size.getX()), -1, -(size.getZ()));
|
||||
BlockPos end = pos.offset(size.getX(), 0, size.getZ());
|
||||
int count = 0;
|
||||
|
||||
for (int x = start.getX(); x <= end.getX(); x++) {
|
||||
POS.setX(x);
|
||||
for (int y = start.getY(); y <= end.getY(); y++) {
|
||||
POS.setY(y);
|
||||
for (int z = start.getZ(); z <= end.getZ(); z++) {
|
||||
POS.setZ(z);
|
||||
if (world.getBlockState(POS).getMaterial().isReplaceable())
|
||||
airCount++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (float) airCount / count;
|
||||
}
|
||||
|
||||
private float getAirFractionBottom(LevelAccessor world, BlockPos pos, Rotation rotation) {
|
||||
final MutableBlockPos POS = new MutableBlockPos();
|
||||
int airCount = 0;
|
||||
|
||||
MutableBlockPos size = new MutableBlockPos().set(new BlockPos(structure.getSize()).rotate(rotation));
|
||||
size.setX(Math.abs(size.getX()));
|
||||
size.setZ(Math.abs(size.getZ()));
|
||||
|
||||
float y1 = Math.min(offsetY, 0);
|
||||
float y2 = Math.max(offsetY, 0);
|
||||
BlockPos start = pos.offset(-(size.getX() >> 1), y1, -(size.getZ() >> 1));
|
||||
BlockPos end = pos.offset(size.getX() >> 1, y2, size.getZ() >> 1);
|
||||
int count = 0;
|
||||
|
||||
for (int x = start.getX(); x <= end.getX(); x++) {
|
||||
POS.setX(x);
|
||||
for (int y = start.getY(); y <= end.getY(); y++) {
|
||||
POS.setY(y);
|
||||
for (int z = start.getZ(); z <= end.getZ(); z++) {
|
||||
POS.setZ(z);
|
||||
if (world.getBlockState(POS).getMaterial().isReplaceable())
|
||||
airCount++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (float) airCount / count;
|
||||
}
|
||||
|
||||
public boolean loaded() {
|
||||
return structure != null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.structures;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.TemplateStructurePiece;
|
||||
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext;
|
||||
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockIgnoreProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
|
||||
import org.betterx.bclib.BCLib;
|
||||
|
||||
public class TemplatePiece extends TemplateStructurePiece {
|
||||
public static final StructurePieceType INSTANCE = setTemplatePieceId(TemplatePiece::new,
|
||||
"template_piece");
|
||||
|
||||
|
||||
private static StructurePieceType setFullContextPieceId(StructurePieceType structurePieceType, String id) {
|
||||
return Registry.register(Registry.STRUCTURE_PIECE, BCLib.makeID(id), structurePieceType);
|
||||
}
|
||||
|
||||
private static StructurePieceType setTemplatePieceId(StructurePieceType.StructureTemplateType structureTemplateType,
|
||||
String string) {
|
||||
return setFullContextPieceId(structureTemplateType, string);
|
||||
}
|
||||
|
||||
|
||||
public static void ensureStaticInitialization() {
|
||||
}
|
||||
|
||||
|
||||
public TemplatePiece(StructureTemplateManager structureTemplateManager,
|
||||
ResourceLocation resourceLocation,
|
||||
BlockPos centerPos,
|
||||
Rotation rotation,
|
||||
Mirror mirror,
|
||||
BlockPos halfSize) {
|
||||
super(INSTANCE,
|
||||
0,
|
||||
structureTemplateManager,
|
||||
resourceLocation,
|
||||
resourceLocation.toString(),
|
||||
makeSettings(rotation, mirror, halfSize),
|
||||
shiftPos(rotation, mirror, halfSize, centerPos));
|
||||
}
|
||||
|
||||
public TemplatePiece(StructureTemplateManager structureTemplateManager, CompoundTag compoundTag) {
|
||||
super(INSTANCE,
|
||||
compoundTag,
|
||||
structureTemplateManager,
|
||||
(ResourceLocation resourceLocation) -> makeSettings(compoundTag));
|
||||
}
|
||||
|
||||
private static BlockPos shiftPos(Rotation rotation,
|
||||
Mirror mirror,
|
||||
BlockPos halfSize,
|
||||
BlockPos pos) {
|
||||
halfSize = StructureTemplate.transform(halfSize, mirror, rotation, halfSize);
|
||||
return pos.offset(-halfSize.getX(), 0, -halfSize.getZ());
|
||||
}
|
||||
|
||||
private static StructurePlaceSettings makeSettings(CompoundTag compoundTag) {
|
||||
return makeSettings(
|
||||
Rotation.valueOf(compoundTag.getString("R")),
|
||||
Mirror.valueOf(compoundTag.getString("M")),
|
||||
new BlockPos(compoundTag.getInt("RX"), compoundTag.getInt("RY"), compoundTag.getInt("RZ")));
|
||||
|
||||
}
|
||||
|
||||
private static StructurePlaceSettings makeSettings(Rotation rotation, Mirror mirror, BlockPos halfSize) {
|
||||
return new StructurePlaceSettings().setRotation(rotation)
|
||||
.setMirror(mirror)
|
||||
.setRotationPivot(halfSize)
|
||||
.addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAdditionalSaveData(StructurePieceSerializationContext structurePieceSerializationContext,
|
||||
CompoundTag tag) {
|
||||
super.addAdditionalSaveData(structurePieceSerializationContext, tag);
|
||||
tag.putString("R", this.placeSettings.getRotation().name());
|
||||
tag.putString("M", this.placeSettings.getMirror().name());
|
||||
tag.putInt("RX", this.placeSettings.getRotationPivot().getX());
|
||||
tag.putInt("RY", this.placeSettings.getRotationPivot().getY());
|
||||
tag.putInt("RZ", this.placeSettings.getRotationPivot().getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleDataMarker(String string,
|
||||
BlockPos blockPos,
|
||||
ServerLevelAccessor serverLevelAccessor,
|
||||
RandomSource randomSource,
|
||||
BoundingBox boundingBox) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.structures;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.NoiseColumn;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.WorldGenerationContext;
|
||||
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
public abstract class TemplateStructure extends Structure {
|
||||
protected final List<Config> configs;
|
||||
|
||||
public static <T extends TemplateStructure> Codec<T> simpleTemplateCodec(BiFunction<StructureSettings, List<Config>, T> instancer) {
|
||||
return RecordCodecBuilder.create((instance) -> instance
|
||||
.group(
|
||||
Structure.settingsCodec(instance),
|
||||
ExtraCodecs.nonEmptyList(Config.CODEC.listOf())
|
||||
.fieldOf("configs")
|
||||
.forGetter((T ruinedPortalStructure) -> ruinedPortalStructure.configs)
|
||||
)
|
||||
.apply(instance, instancer)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected TemplateStructure(StructureSettings structureSettings,
|
||||
ResourceLocation location,
|
||||
int offsetY,
|
||||
StructurePlacementType type,
|
||||
float chance) {
|
||||
this(structureSettings, List.of(new Config(location, offsetY, type, chance)));
|
||||
}
|
||||
|
||||
protected TemplateStructure(StructureSettings structureSettings,
|
||||
List<Config> configs) {
|
||||
super(structureSettings);
|
||||
this.configs = configs;
|
||||
}
|
||||
|
||||
protected Config randomConfig(RandomSource random) {
|
||||
if (this.configs.size() > 1) {
|
||||
final float chanceSum = configs.parallelStream().map(c -> c.chance()).reduce(0.0f, (p, c) -> p + c);
|
||||
float rnd = random.nextFloat() * chanceSum;
|
||||
|
||||
for (Config c : configs) {
|
||||
rnd -= c.chance();
|
||||
if (rnd <= 0) return c;
|
||||
}
|
||||
} else {
|
||||
return this.configs.get(0);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean isLavaPlaceable(BlockState state, BlockState before) {
|
||||
return state.is(Blocks.AIR) && before.is(Blocks.LAVA);
|
||||
}
|
||||
|
||||
protected boolean isFloorPlaceable(BlockState state, BlockState before) {
|
||||
return state.is(Blocks.AIR) && before.getMaterial().isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<GenerationStub> findGenerationPoint(GenerationContext ctx) {
|
||||
|
||||
WorldGenerationContext worldGenerationContext = new WorldGenerationContext(ctx.chunkGenerator(),
|
||||
ctx.heightAccessor());
|
||||
final Config config = randomConfig(ctx.random());
|
||||
if (config == null) return Optional.empty();
|
||||
ChunkPos chunkPos = ctx.chunkPos();
|
||||
final int x = chunkPos.getMiddleBlockX();
|
||||
final int z = chunkPos.getMiddleBlockZ();
|
||||
NoiseColumn column = ctx.chunkGenerator().getBaseColumn(x, z, ctx.heightAccessor(), ctx.randomState());
|
||||
StructureTemplate structureTemplate = ctx.structureTemplateManager().getOrCreate(config.location);
|
||||
|
||||
|
||||
BiPredicate<BlockState, BlockState> isCorrectBase;
|
||||
int searchStep;
|
||||
if (config.type == StructurePlacementType.LAVA) {
|
||||
isCorrectBase = this::isLavaPlaceable;
|
||||
searchStep = 1;
|
||||
} else if (config.type == StructurePlacementType.CEIL) {
|
||||
isCorrectBase = this::isFloorPlaceable;
|
||||
searchStep = -1;
|
||||
} else {
|
||||
isCorrectBase = this::isFloorPlaceable;
|
||||
searchStep = 1;
|
||||
}
|
||||
|
||||
|
||||
final int seaLevel =
|
||||
ctx.chunkGenerator().getSeaLevel()
|
||||
+ (searchStep > 0 ? 0 : (structureTemplate.getSize(Rotation.NONE).getY() + config.offsetY));
|
||||
final int maxHeight =
|
||||
worldGenerationContext.getGenDepth()
|
||||
- 4
|
||||
- (searchStep > 0 ? (structureTemplate.getSize(Rotation.NONE).getY() + config.offsetY) : 0);
|
||||
int y = searchStep > 0 ? seaLevel : maxHeight - 1;
|
||||
BlockState state = column.getBlock(y - searchStep);
|
||||
|
||||
for (; y < maxHeight && y >= seaLevel; y += searchStep) {
|
||||
BlockState before = state;
|
||||
state = column.getBlock(y);
|
||||
if (isCorrectBase.test(state, before)) break;
|
||||
}
|
||||
if (y >= maxHeight || y < seaLevel) return Optional.empty();
|
||||
if (!BCLStructure.isValidBiome(ctx, y)) return Optional.empty();
|
||||
|
||||
BlockPos halfSize = new BlockPos(structureTemplate.getSize().getX() / 2,
|
||||
0,
|
||||
structureTemplate.getSize().getZ() / 2);
|
||||
Rotation rotation = StructureNBT.getRandomRotation(ctx.random());
|
||||
Mirror mirror = StructureNBT.getRandomMirror(ctx.random());
|
||||
BlockPos centerPos = new BlockPos(x,
|
||||
y - (searchStep == 1 ? 0 : (structureTemplate.getSize(Rotation.NONE).getY())),
|
||||
z);
|
||||
BoundingBox boundingBox = structureTemplate.getBoundingBox(centerPos, rotation, halfSize, mirror);
|
||||
|
||||
|
||||
// if (!structure.canGenerate(ctx.chunkGenerator()., centerPos))
|
||||
return Optional.of(new GenerationStub(centerPos,
|
||||
structurePiecesBuilder ->
|
||||
structurePiecesBuilder.addPiece(
|
||||
new TemplatePiece(ctx.structureTemplateManager(),
|
||||
config.location,
|
||||
centerPos.offset(
|
||||
0,
|
||||
config.offsetY,
|
||||
0),
|
||||
rotation,
|
||||
mirror,
|
||||
halfSize))
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
public record Config(ResourceLocation location, int offsetY, StructurePlacementType type, float chance) {
|
||||
public static final Codec<Config> CODEC =
|
||||
RecordCodecBuilder.create((instance) ->
|
||||
instance.group(
|
||||
ResourceLocation.CODEC
|
||||
.fieldOf("location")
|
||||
.forGetter((cfg) -> cfg.location),
|
||||
|
||||
Codec
|
||||
.INT
|
||||
.fieldOf("offset_y")
|
||||
.orElse(0)
|
||||
.forGetter((cfg) -> cfg.offsetY),
|
||||
|
||||
StructurePlacementType.CODEC
|
||||
.fieldOf("placement")
|
||||
.orElse(StructurePlacementType.FLOOR)
|
||||
.forGetter((cfg) -> cfg.type),
|
||||
Codec
|
||||
.FLOAT
|
||||
.fieldOf("chance")
|
||||
.orElse(1.0f)
|
||||
.forGetter((cfg) -> cfg.chance)
|
||||
)
|
||||
.apply(instance, Config::new)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.structures.templatesystem;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
|
||||
public class DestructionStructureProcessor extends StructureProcessor {
|
||||
private int chance = 4;
|
||||
|
||||
public void setChance(int chance) {
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureBlockInfo processBlock(LevelReader worldView,
|
||||
BlockPos pos,
|
||||
BlockPos blockPos,
|
||||
StructureBlockInfo structureBlockInfo,
|
||||
StructureBlockInfo structureBlockInfo2,
|
||||
StructurePlaceSettings structurePlacementData) {
|
||||
if (!BlocksHelper.isInvulnerable(
|
||||
structureBlockInfo2.state,
|
||||
worldView,
|
||||
structureBlockInfo2.pos
|
||||
) && MHelper.RANDOM.nextInt(chance) == 0) {
|
||||
return null;
|
||||
}
|
||||
return structureBlockInfo2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructureProcessorType<?> getType() {
|
||||
return StructureProcessorType.RULE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package org.betterx.bclib.api.v2.levelgen.structures.templatesystem;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||
|
||||
public class TerrainStructureProcessor extends StructureProcessor {
|
||||
private final Block defaultBlock;
|
||||
|
||||
public TerrainStructureProcessor(Block defaultBlock) {
|
||||
this.defaultBlock = defaultBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructureBlockInfo processBlock(LevelReader worldView,
|
||||
BlockPos pos,
|
||||
BlockPos blockPos,
|
||||
StructureBlockInfo structureBlockInfo,
|
||||
StructureBlockInfo structureBlockInfo2,
|
||||
StructurePlaceSettings structurePlacementData) {
|
||||
BlockPos bpos = structureBlockInfo2.pos;
|
||||
if (structureBlockInfo2.state.is(defaultBlock) && worldView.isEmptyBlock(bpos.above())) {
|
||||
final BlockState top = BiomeAPI.findTopMaterial(worldView.getBiome(pos))
|
||||
.orElse(defaultBlock.defaultBlockState());
|
||||
return new StructureBlockInfo(bpos, top, structureBlockInfo2.nbt);
|
||||
}
|
||||
return structureBlockInfo2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected StructureProcessorType<?> getType() {
|
||||
return StructureProcessorType.RULE;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.surface;
|
||||
package org.betterx.bclib.api.v2.levelgen.surface;
|
||||
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
|
@ -9,10 +9,10 @@ import net.minecraft.world.level.levelgen.placement.CaveSurface;
|
|||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.surface.rules.Conditions;
|
||||
import org.betterx.bclib.api.surface.rules.DoubleBlockSurfaceNoiseCondition;
|
||||
import org.betterx.bclib.api.surface.rules.NoiseCondition;
|
||||
import org.betterx.bclib.api.v2.levelgen.surface.rules.DoubleBlockSurfaceNoiseCondition;
|
||||
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.v2.levelgen.surface.rules.Conditions;
|
||||
import org.betterx.bclib.api.v2.levelgen.surface.rules.NoiseCondition;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
|
@ -1,4 +1,4 @@
|
|||
package org.betterx.bclib.api.surface;
|
||||
package org.betterx.bclib.api.v2.levelgen.surface;
|
||||
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.level.levelgen.SurfaceRules;
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue