Sync ore depths to all clients via a packet on server login.
This commit is contained in:
parent
32368f8388
commit
5b596aa5f8
10 changed files with 224 additions and 78 deletions
|
@ -47,8 +47,6 @@ import reborncore.common.blockentity.MachineBaseBlockEntity;
|
|||
import reborncore.common.blockentity.SlotConfiguration;
|
||||
import reborncore.common.chunkloading.ChunkLoaderManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ClientBoundPacketHandlers {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ClientBoundPacketHandlers.class);
|
||||
|
@ -137,11 +135,7 @@ public class ClientBoundPacketHandlers {
|
|||
});
|
||||
});
|
||||
|
||||
NetworkManager.registerClientBoundHandler(new Identifier("reborncore", "sync_chunks"), (client, handler, packetBuffer, responseSender) -> {
|
||||
List<ChunkLoaderManager.LoadedChunk> chunks = new ExtendedPacketBuffer(packetBuffer).readCodec(ChunkLoaderManager.CODEC);
|
||||
|
||||
client.execute(() -> ClientChunkManager.setLoadedChunks(chunks));
|
||||
});
|
||||
NetworkManager.registerClientBoundHandler(new Identifier("reborncore", "sync_chunks"), ChunkLoaderManager.CODEC, ClientChunkManager::setLoadedChunks);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -76,9 +76,7 @@ public class ClientBoundPackets {
|
|||
}
|
||||
|
||||
public static IdentifiedPacket createPacketSyncLoadedChunks(List<ChunkLoaderManager.LoadedChunk> chunks) {
|
||||
return NetworkManager.createClientBoundPacket(new Identifier("reborncore", "sync_chunks"), extendedPacketBuffer -> {
|
||||
extendedPacketBuffer.writeCodec(ChunkLoaderManager.CODEC, chunks);
|
||||
});
|
||||
return NetworkManager.createClientBoundPacket(new Identifier("reborncore", "sync_chunks"), ChunkLoaderManager.CODEC, chunks);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,11 +24,16 @@
|
|||
|
||||
package reborncore.common.network;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
@ -58,10 +63,24 @@ public class NetworkManager {
|
|||
return new IdentifiedPacket(identifier, buf);
|
||||
}
|
||||
|
||||
public static <T> IdentifiedPacket createClientBoundPacket(Identifier identifier, Codec<T> codec, T value) {
|
||||
return createClientBoundPacket(identifier, extendedPacketBuffer -> extendedPacketBuffer.writeCodec(codec, value));
|
||||
}
|
||||
|
||||
// TODO move to own class
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void registerClientBoundHandler(Identifier identifier, ClientPlayNetworking.PlayChannelHandler handler) {
|
||||
ClientPlayNetworking.registerGlobalReceiver(identifier, handler);
|
||||
}
|
||||
|
||||
// TODO move to own class
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static <T> void registerClientBoundHandler(Identifier identifier, Codec<T> codec, Consumer<T> consumer) {
|
||||
registerClientBoundHandler(identifier, (client, handler, buf, responseSender) -> {
|
||||
T value = new ExtendedPacketBuffer(buf).readCodec(codec);
|
||||
client.execute(() -> consumer.accept(value));
|
||||
});
|
||||
}
|
||||
|
||||
public static void sendToServer(IdentifiedPacket packet) {
|
||||
ClientPlayNetworking.send(packet.channel(), packet.packetByteBuf());
|
||||
|
@ -90,5 +109,9 @@ public class NetworkManager {
|
|||
}
|
||||
}
|
||||
|
||||
public static void sendTo(IdentifiedPacket packet, PacketSender sender) {
|
||||
Packet<?> s2CPacket = ServerPlayNetworking.createS2CPacket(packet.channel(), packet.packetByteBuf());
|
||||
sender.sendPacket(s2CPacket);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,12 +43,11 @@ import techreborn.client.GuiType;
|
|||
import techreborn.compat.trinkets.Trinkets;
|
||||
import techreborn.config.TechRebornConfig;
|
||||
import techreborn.events.ApplyArmorToDamageHandler;
|
||||
import techreborn.events.ModRegistry;
|
||||
import techreborn.events.OreDepthSyncHandler;
|
||||
import techreborn.events.UseBlockHandler;
|
||||
import techreborn.init.*;
|
||||
import techreborn.init.template.TechRebornTemplates;
|
||||
import techreborn.items.DynamicCellItem;
|
||||
import techreborn.packets.ClientboundPackets;
|
||||
import techreborn.packets.ServerboundPackets;
|
||||
import techreborn.utils.PoweredCraftingHandler;
|
||||
import techreborn.world.WorldGenerator;
|
||||
|
@ -77,8 +76,8 @@ public class TechReborn implements ModInitializer {
|
|||
ModRecipes.GRINDER.hashCode();
|
||||
TRContent.SCRAP_BOX.asItem();
|
||||
|
||||
ClientboundPackets.init();
|
||||
ServerboundPackets.init();
|
||||
OreDepthSyncHandler.setup();
|
||||
|
||||
if (TechRebornConfig.machineSoundVolume > 0) {
|
||||
if (TechRebornConfig.machineSoundVolume > 1) TechRebornConfig.machineSoundVolume = 1F;
|
||||
|
|
|
@ -70,6 +70,7 @@ import techreborn.items.FrequencyTransmitterItem;
|
|||
import techreborn.items.armor.BatpackItem;
|
||||
import techreborn.items.tool.ChainsawItem;
|
||||
import techreborn.items.tool.industrial.NanosaberItem;
|
||||
import techreborn.packets.ClientboundPackets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -146,6 +147,7 @@ public class TechRebornClient implements ClientModInitializer {
|
|||
});
|
||||
|
||||
StackToolTipHandler.setup();
|
||||
ClientboundPackets.init();
|
||||
|
||||
GuiBase.wrenchStack = new ItemStack(TRContent.WRENCH);
|
||||
GuiBase.fluidCellProvider = DynamicCellItem::getCellWithFluid;
|
||||
|
|
64
src/main/java/techreborn/events/OreDepthSyncHandler.java
Normal file
64
src/main/java/techreborn/events/OreDepthSyncHandler.java
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* This file is part of TechReborn, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2020 TechReborn
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package techreborn.events;
|
||||
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import reborncore.common.network.NetworkManager;
|
||||
import techreborn.packets.ClientboundPackets;
|
||||
import techreborn.world.OreDepth;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class OreDepthSyncHandler {
|
||||
private static Map<Block, OreDepth> oreDepthMap = new HashMap<>();
|
||||
|
||||
private OreDepthSyncHandler() {
|
||||
}
|
||||
|
||||
public static void setup() {
|
||||
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) ->
|
||||
NetworkManager.sendTo(ClientboundPackets.createPacketSyncOreDepth(OreDepth.create(server)), sender)
|
||||
);
|
||||
}
|
||||
|
||||
public static void updateDepths(List<OreDepth> list) {
|
||||
synchronized (OreDepthSyncHandler.class) {
|
||||
oreDepthMap = list.stream()
|
||||
.collect(Collectors.toMap(oreDepth -> Registry.BLOCK.get(oreDepth.identifier()), Function.identity()));
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<Block, OreDepth> getOreDepthMap() {
|
||||
synchronized (OreDepthSyncHandler.class) {
|
||||
return oreDepthMap;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,31 +36,26 @@ import net.minecraft.fluid.Fluid;
|
|||
import net.minecraft.fluid.Fluids;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.HeightContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import reborncore.common.BaseBlockEntityProvider;
|
||||
import techreborn.init.TRContent;
|
||||
import techreborn.items.DynamicCellItem;
|
||||
import techreborn.items.UpgradeItem;
|
||||
import techreborn.utils.ToolTipAssistUtils;
|
||||
import techreborn.world.OreDistribution;
|
||||
import techreborn.world.OreDepth;
|
||||
import techreborn.world.TargetDimension;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class StackToolTipHandler implements ItemTooltipCallback {
|
||||
|
||||
public static final Map<Item, Boolean> ITEM_ID = Maps.newHashMap();
|
||||
private static final Map<Block, OreDistribution> ORE_DISTRIBUTION_MAP = Maps.newHashMap();
|
||||
private static final List<Block> UNOBTAINABLE_ORES = Lists.newLinkedList();
|
||||
|
||||
public static void setup() {
|
||||
|
@ -71,21 +66,6 @@ public class StackToolTipHandler implements ItemTooltipCallback {
|
|||
TRContent.Ores normal = ore.getUnDeepslate();
|
||||
if (normal.distribution != null && normal.distribution.dimension != TargetDimension.OVERWORLD)
|
||||
UNOBTAINABLE_ORES.add(ore.block);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ore.distribution != null) {
|
||||
ORE_DISTRIBUTION_MAP.put(ore.block, ore.distribution);
|
||||
|
||||
if (ore.distribution.dimension != TargetDimension.OVERWORLD) {
|
||||
continue; // No Deepslate in other dims
|
||||
}
|
||||
|
||||
TRContent.Ores deepslate = ore.getDeepslate();
|
||||
if (deepslate != null) {
|
||||
// Deepslate shares the same distribution as the stone version.
|
||||
ORE_DISTRIBUTION_MAP.put(deepslate.block, ore.distribution);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,56 +100,23 @@ public class StackToolTipHandler implements ItemTooltipCallback {
|
|||
ToolTipAssistUtils.addInfo("unplaceable_fluid", tooltipLines, false);
|
||||
}
|
||||
|
||||
Text text = null;
|
||||
if (UNOBTAINABLE_ORES.contains(block))
|
||||
text = new TranslatableText("techreborn.tooltip.unobtainable");
|
||||
OreDistribution oreDistribution = ORE_DISTRIBUTION_MAP.get(block);
|
||||
if (oreDistribution != null && text == null) {
|
||||
text = switch (oreDistribution.dimension) {
|
||||
case OVERWORLD -> getOverworldOreText(oreDistribution);
|
||||
case END -> new TranslatableText("techreborn.tooltip.ores.end");
|
||||
case NETHER -> new TranslatableText("techreborn.tooltip.ores.nether");
|
||||
};
|
||||
}
|
||||
if (text != null)
|
||||
if (UNOBTAINABLE_ORES.contains(block)) {
|
||||
tooltipLines.add(new TranslatableText("techreborn.tooltip.unobtainable").formatted(Formatting.AQUA));
|
||||
} else if (OreDepthSyncHandler.getOreDepthMap().containsKey(block)) {
|
||||
OreDepth oreDepth = OreDepthSyncHandler.getOreDepthMap().get(block);
|
||||
Text text = getOreDepthText(oreDepth);
|
||||
tooltipLines.add(text.copy().formatted(Formatting.AQUA));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isTRItem(Item item) {
|
||||
return Registry.ITEM.getId(item).getNamespace().equals("techreborn");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static HeightContext getHeightContextSafely() {
|
||||
final IntegratedServer server = MinecraftClient.getInstance().getServer();
|
||||
|
||||
if (server == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ServerWorld world = server.getWorld(World.OVERWORLD);
|
||||
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new HeightContext(world.getChunkManager().getChunkGenerator(), world);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Text getOverworldOreText(OreDistribution oreDistribution) {
|
||||
final HeightContext heightContext = getHeightContextSafely();
|
||||
|
||||
if (heightContext == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int minY = oreDistribution.minOffset.getY(heightContext);
|
||||
final int maxY = oreDistribution.maxY;
|
||||
|
||||
return new TranslatableText("techreborn.tooltip.ores.overworld",
|
||||
new LiteralText(String.valueOf(minY)).formatted(Formatting.YELLOW),
|
||||
new LiteralText(String.valueOf(maxY)).formatted(Formatting.YELLOW)
|
||||
private static TranslatableText getOreDepthText(OreDepth depth) {
|
||||
return new TranslatableText("techreborn.tooltip.ores.%s".formatted(depth.dimension().name().toLowerCase(Locale.ROOT)),
|
||||
new LiteralText(String.valueOf(depth.minY())).formatted(Formatting.YELLOW),
|
||||
new LiteralText(String.valueOf(depth.maxY())).formatted(Formatting.YELLOW)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,28 @@
|
|||
|
||||
package techreborn.packets;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.util.Identifier;
|
||||
import reborncore.common.network.IdentifiedPacket;
|
||||
import reborncore.common.network.NetworkManager;
|
||||
import techreborn.TechReborn;
|
||||
import techreborn.events.OreDepthSyncHandler;
|
||||
import techreborn.world.OreDepth;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ClientboundPackets {
|
||||
public static final Identifier ORE_DEPTH = new Identifier(TechReborn.MOD_ID, "ore_depth");
|
||||
|
||||
// TODO move to own class
|
||||
@Environment(EnvType.CLIENT)
|
||||
public static void init() {
|
||||
NetworkManager.registerClientBoundHandler(ORE_DEPTH, OreDepth.LIST_CODEC, OreDepthSyncHandler::updateDepths);
|
||||
}
|
||||
|
||||
public static IdentifiedPacket createPacketSyncOreDepth(List<OreDepth> oreDepths) {
|
||||
return NetworkManager.createClientBoundPacket(ORE_DEPTH, OreDepth.LIST_CODEC, oreDepths);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
93
src/main/java/techreborn/world/OreDepth.java
Normal file
93
src/main/java/techreborn/world/OreDepth.java
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* This file is part of TechReborn, licensed under the MIT License (MIT).
|
||||
*
|
||||
* Copyright (c) 2020 TechReborn
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package techreborn.world;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.HeightContext;
|
||||
import techreborn.init.TRContent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Client synced DTO for ore depth
|
||||
*/
|
||||
public record OreDepth(Identifier identifier, int minY, int maxY, TargetDimension dimension) {
|
||||
public static final Codec<OreDepth> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
Identifier.CODEC.fieldOf("identifier").forGetter(OreDepth::identifier),
|
||||
Codec.INT.fieldOf("minY").forGetter(OreDepth::minY),
|
||||
Codec.INT.fieldOf("maxY").forGetter(OreDepth::maxY),
|
||||
TargetDimension.CODEC.fieldOf("dimension").forGetter(OreDepth::dimension)
|
||||
).apply(instance, OreDepth::new)
|
||||
);
|
||||
public static Codec<List<OreDepth>> LIST_CODEC = Codec.list(OreDepth.CODEC);
|
||||
|
||||
public static List<OreDepth> create(MinecraftServer server) {
|
||||
|
||||
final List<OreDepth> depths = new ArrayList<>();
|
||||
|
||||
for (TRContent.Ores ore : TRContent.Ores.values()) {
|
||||
if (ore.isDeepslate()) continue;
|
||||
|
||||
if (ore.distribution != null) {
|
||||
final Identifier blockId = Registry.BLOCK.getId(ore.block);
|
||||
final HeightContext heightContext = getHeightContext(server, ore.distribution.dimension);
|
||||
|
||||
final int minY = ore.distribution.minOffset.getY(heightContext);
|
||||
final int maxY = ore.distribution.maxY;
|
||||
|
||||
depths.add(new OreDepth(blockId, minY, maxY, ore.distribution.dimension));
|
||||
|
||||
TRContent.Ores deepslate = ore.getDeepslate();
|
||||
if (deepslate == null) continue;
|
||||
|
||||
final Identifier deepSlateBlockId = Registry.BLOCK.getId(deepslate.block);
|
||||
depths.add(new OreDepth(deepSlateBlockId, minY, maxY, ore.distribution.dimension));
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(depths);
|
||||
}
|
||||
|
||||
private static HeightContext getHeightContext(MinecraftServer server, TargetDimension dimension) {
|
||||
RegistryKey<World> key = switch (dimension) {
|
||||
case OVERWORLD -> World.OVERWORLD;
|
||||
case NETHER -> World.NETHER;
|
||||
case END -> World.END;
|
||||
};
|
||||
|
||||
final ServerWorld world = server.getWorld(key);
|
||||
return new HeightContext(world.getChunkManager().getChunkGenerator(), world);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
package techreborn.world;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
|
||||
|
||||
|
@ -34,6 +36,12 @@ public enum TargetDimension {
|
|||
NETHER(BiomeSelectors.foundInTheNether()),
|
||||
END(BiomeSelectors.foundInTheEnd());
|
||||
|
||||
public static final Codec<TargetDimension> CODEC = RecordCodecBuilder.create(instance ->
|
||||
instance.group(
|
||||
Codec.STRING.fieldOf("name").forGetter(TargetDimension::name)
|
||||
).apply(instance, TargetDimension::valueOf)
|
||||
);
|
||||
|
||||
public final Predicate<BiomeSelectionContext> biomeSelector;
|
||||
|
||||
TargetDimension(Predicate<BiomeSelectionContext> biomeSelector) {
|
||||
|
|
Loading…
Reference in a new issue