Merge pull request #185 from CreepyCre/1.16-fabric

Various fixes + Pocket Loader & Placer Rewrite
This commit is contained in:
Waterpicker 2021-02-10 17:30:35 -06:00 committed by GitHub
commit 751a9d1770
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
89 changed files with 3432 additions and 490 deletions

View file

@ -1,26 +1,27 @@
package org.dimdev.dimdoors;
import net.minecraft.nbt.CompoundTag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes;
import org.dimdev.dimdoors.client.ModSkyRendering;
import org.dimdev.dimdoors.entity.ModEntityTypes;
import org.dimdev.dimdoors.entity.MonolithEntity;
import org.dimdev.dimdoors.fluid.ModFluids;
import org.dimdev.dimdoors.network.s2c.PlayerInventorySlotUpdateS2CPacket;
import org.dimdev.dimdoors.particle.ModParticleTypes;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.PacketByteBuf;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import java.io.IOException;
@Environment(EnvType.CLIENT)
public class DimensionalDoorsClientInitializer implements ClientModInitializer {
private static final Logger LOGGER = LogManager.getLogger();
@Override
public void onInitializeClient() {
ModEntityTypes.initClient();
@ -31,5 +32,18 @@ public class DimensionalDoorsClientInitializer implements ClientModInitializer {
ModParticleTypes.initClient();
ClientPlayNetworking.registerGlobalReceiver(DimensionalDoorsInitializer.MONOLITH_PARTICLE_PACKET, (client, networkHandler, buf, sender) -> MonolithEntity.spawnParticles(buf, client));
// TODO: change this to a normal Receiver with the inventory network handler attached. Will have to register/ unregister when a player joins/ leaves a world
ClientPlayNetworking.registerGlobalReceiver(PlayerInventorySlotUpdateS2CPacket.ID, (minecraftClient, clientPlayNetworkHandler, packetByteBuf, packetSender) -> {
PlayerInventorySlotUpdateS2CPacket packet = new PlayerInventorySlotUpdateS2CPacket();
try {
packet.read(packetByteBuf);
minecraftClient.player.inventory.setStack(packet.getSlot(), packet.getStack());
// TODO: remove commented out debug code
//LOGGER.info("Synced slot " + packet.getSlot() + " with item stack " + packet.getStack().toTag(new CompoundTag()));
} catch (IOException e) {
LOGGER.error(e);
}
});
}
}

View file

@ -1,8 +1,13 @@
package org.dimdev.dimdoors;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import me.sargunvohra.mcmods.autoconfig1u.ConfigHolder;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes;
import org.dimdev.dimdoors.command.ModCommands;
@ -10,13 +15,17 @@ import org.dimdev.dimdoors.entity.ModEntityTypes;
import org.dimdev.dimdoors.entity.stat.ModStats;
import org.dimdev.dimdoors.fluid.ModFluids;
import org.dimdev.dimdoors.item.ModItems;
import org.dimdev.dimdoors.item.RiftConfigurationToolItem;
import org.dimdev.dimdoors.network.c2s.HitBlockS2CPacket;
import org.dimdev.dimdoors.particle.ModParticleTypes;
import org.dimdev.dimdoors.pockets.SchematicHandler;
import org.dimdev.dimdoors.pockets.SchematicV2Handler;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
import org.dimdev.dimdoors.pockets.virtual.VirtualSingularPocket;
import org.dimdev.dimdoors.pockets.modifier.Modifier;
import org.dimdev.dimdoors.rift.targets.Targets;
import org.dimdev.dimdoors.rift.targets.VirtualTarget;
import org.dimdev.dimdoors.sound.ModSoundEvents;
import org.dimdev.dimdoors.util.schematic.v2.SchematicTest;
import org.dimdev.dimdoors.world.ModBiomes;
import org.dimdev.dimdoors.world.ModDimensions;
import org.dimdev.dimdoors.world.feature.ModFeatures;
@ -30,13 +39,13 @@ import net.minecraft.world.World;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.loader.api.FabricLoader;
public class DimensionalDoorsInitializer implements ModInitializer {
public static final Identifier MONOLITH_PARTICLE_PACKET = new Identifier("dimdoors", "monolith_particle_packet");
public static ConfigHolder<ModConfig> CONFIG_MANAGER;
public static ModConfig CONFIG;
private static Map<UUID, ServerPlayNetworkHandler> UUID_SERVER_PLAY_NETWORK_HANDLER_MAP = new HashMap<>();
private static MinecraftServer server;
@NotNull
@ -55,13 +64,6 @@ public class DimensionalDoorsInitializer implements ModInitializer {
public void onInitialize() {
ServerLifecycleEvents.SERVER_STARTING.register((minecraftServer) -> {
server = minecraftServer;
if (FabricLoader.getInstance().isDevelopmentEnvironment()) {
try {
SchematicTest.test();
} catch (IOException e) {
e.printStackTrace();
}
}
});
ModBlocks.init();
@ -81,7 +83,18 @@ public class DimensionalDoorsInitializer implements ModInitializer {
Targets.registerDefaultTargets();
VirtualTarget.VirtualTargetType.register();
VirtualSingularPocket.VirtualSingularPocketType.register();
Modifier.ModifierType.register();
PocketGenerator.PocketGeneratorType.register();
SchematicV2Handler.getInstance().load();
SchematicHandler.INSTANCE.loadSchematics();
AttackBlockCallback.EVENT.register(RiftConfigurationToolItem::onAttackBlockCallback);
ServerPlayNetworking.registerGlobalReceiver(HitBlockS2CPacket.ID, RiftConfigurationToolItem::receiveHitBlock);
}
}

View file

@ -0,0 +1,16 @@
package org.dimdev.dimdoors.block;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.block.Material;
import net.minecraft.util.DyeColor;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public class AncientFabricBlock extends Block {
public AncientFabricBlock(DyeColor color) {
super(FabricBlockSettings.of(Material.STONE, color).strength(-1.0F, 3600000.0F).dropsNothing());
}
}

View file

@ -11,10 +11,13 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.MaterialColor;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
@ -79,4 +82,13 @@ public class DetachedRiftBlock extends Block implements RiftProvider<DetachedRif
public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.ENTITYBLOCK_ANIMATED;
}
@Override
public VoxelShape getRaycastShape(BlockState state, BlockView world, BlockPos pos) {
return VoxelShapes.fullCube();
}
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return VoxelShapes.fullCube();
}
}

View file

@ -17,6 +17,8 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
@ -96,4 +98,9 @@ public class DimensionalDoorBlock extends DoorBlock implements RiftProvider<Entr
throw new IllegalStateException("Dimensional door at " + pos + " in world " + world + " contained no rift.");
}
}
@Override
public VoxelShape getRaycastShape(BlockState state, BlockView world, BlockPos pos) {
return VoxelShapes.fullCube();
}
}

View file

@ -20,6 +20,8 @@ import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
@ -70,4 +72,9 @@ public class DimensionalPortalBlock extends Block implements RiftProvider<Entran
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(FACING);
}
@Override
public VoxelShape getRaycastShape(BlockState state, BlockView world, BlockPos pos) {
return VoxelShapes.fullCube();
}
}

View file

@ -13,6 +13,8 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
@ -53,4 +55,9 @@ public class DimensionalTrapdoorBlock extends TrapdoorBlock implements RiftProvi
public EntranceRiftBlockEntity getRift(World world, BlockPos pos, BlockState state) {
return (EntranceRiftBlockEntity) world.getBlockEntity(pos);
}
@Override
public VoxelShape getRaycastShape(BlockState state, BlockView world, BlockPos pos) {
return VoxelShapes.fullCube();
}
}

View file

@ -1,5 +1,8 @@
package org.dimdev.dimdoors.block;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
@ -15,8 +18,9 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import org.dimdev.dimdoors.util.InstanceMap;
class FabricBlock extends Block {
public class FabricBlock extends Block {
FabricBlock(DyeColor color) {
super(FabricBlockSettings.of(Material.STONE, color).lightLevel(15));
}

View file

@ -1,5 +1,6 @@
package org.dimdev.dimdoors.block;
import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.Maps;
@ -18,6 +19,9 @@ import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
public final class ModBlocks {
private static final Map<String, Block> BLOCKS = Maps.newLinkedHashMap();
private static final Map<DyeColor, Block> FABRIC_BLOCKS = new HashMap<>();
private static final Map<DyeColor, Block> ANCIENT_FABRIC_BLOCKS = new HashMap<>();
public static final Block GOLD_DOOR = register("dimdoors:gold_door", new DoorBlock(FabricBlockSettings.of(Material.METAL, MaterialColor.GOLD).nonOpaque()));
public static final Block QUARTZ_DOOR = register("dimdoors:quartz_door", new DoorBlock(FabricBlockSettings.of(Material.STONE, MaterialColor.QUARTZ).nonOpaque()));
public static final Block OAK_DIMENSIONAL_DOOR = register("dimdoors:oak_dimensional_door", new DimensionalDoorBlock(FabricBlockSettings.of(Material.WOOD, MaterialColor.WOOD).nonOpaque().lightLevel(state -> ((DimensionalDoorBlock) state.getBlock()).hasBlockEntity(state) ? 10 : 0)));
@ -74,11 +78,15 @@ public final class ModBlocks {
}
private static Block registerAncientFabric(String id, DyeColor color) {
return register(id, new Block(FabricBlockSettings.of(Material.STONE, color).strength(-1.0F, 3600000.0F).dropsNothing()));
Block block = new AncientFabricBlock(color);
ANCIENT_FABRIC_BLOCKS.put(color, block);
return register(id, block);
}
private static Block registerFabric(String id, DyeColor color) {
return register(id, new FabricBlock(color));
Block block = new FabricBlock(color);
FABRIC_BLOCKS.put(color, block);
return register(id, block);
}
public static void init() {
@ -93,6 +101,14 @@ public final class ModBlocks {
BlockRenderLayerMap.INSTANCE.putBlocks(RenderLayer.getCutout(), ModBlocks.OAK_DIMENSIONAL_DOOR, ModBlocks.GOLD_DIMENSIONAL_DOOR, ModBlocks.IRON_DIMENSIONAL_DOOR, ModBlocks.OAK_DIMENSIONAL_TRAPDOOR, ModBlocks.QUARTZ_DIMENSIONAL_DOOR, ModBlocks.QUARTZ_DOOR);
}
public static Block ancientFabricFromDye(DyeColor color) {
return ANCIENT_FABRIC_BLOCKS.get(color);
}
public static Block fabricFromDye(DyeColor color) {
return FABRIC_BLOCKS.get(color);
}
private static class DoorBlock extends net.minecraft.block.DoorBlock {
public DoorBlock(Settings settings) {
super(settings);

View file

@ -27,8 +27,8 @@ public class ModBlockEntityTypes {
EntranceRiftBlockEntity::new,
ModBlocks.OAK_DIMENSIONAL_DOOR, ModBlocks.IRON_DIMENSIONAL_DOOR, ModBlocks.GOLD_DIMENSIONAL_DOOR, ModBlocks.QUARTZ_DIMENSIONAL_DOOR, ModBlocks.DIMENSIONAL_PORTAL);
private static <E extends BlockEntity> BlockEntityType<E> register(String id, Supplier<? extends E> supplier, Block... blocks) {
return Registry.register(Registry.BLOCK_ENTITY_TYPE, id, new BlockEntityType<>(supplier, Sets.newHashSet(blocks), null));
private static <E extends BlockEntity> BlockEntityType<E> register(String id, Supplier<E> supplier, Block... blocks) {
return Registry.register(Registry.BLOCK_ENTITY_TYPE, id, BlockEntityType.Builder.create(supplier, blocks).build(null));
}
public static void init() {

View file

@ -46,6 +46,7 @@ public abstract class RiftBlockEntity extends BlockEntity implements BlockEntity
// NBT
@Override
public void fromTag(BlockState state, CompoundTag nbt) {
super.fromTag(state, nbt);
this.deserialize(nbt);
}
@ -55,9 +56,8 @@ public abstract class RiftBlockEntity extends BlockEntity implements BlockEntity
@Override
public CompoundTag toTag(CompoundTag tag) {
this.serialize(tag);
return super.toTag(tag);
super.toTag(tag);
return this.serialize(tag);
}
public CompoundTag serialize(CompoundTag tag) {
@ -110,7 +110,7 @@ public abstract class RiftBlockEntity extends BlockEntity implements BlockEntity
}
public boolean isRegistered() {
return !PocketTemplate.isReplacingPlaceholders() && DimensionalRegistry.getRiftRegistry().isRiftAt(new Location((ServerWorld) this.world, this.pos));
return !PocketTemplate.isReplacingPlaceholders() && this.world != null && DimensionalRegistry.getRiftRegistry().isRiftAt(new Location((ServerWorld) this.world, this.pos));
}
public void register() {

View file

@ -4,6 +4,7 @@ import java.util.Objects;
import com.flowpowered.math.TrigMath;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.ModConfig;
import org.dimdev.dimdoors.block.entity.DetachedRiftBlockEntity;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.client.tesseract.Tesseract;
@ -48,7 +49,7 @@ public class DetachedRiftBlockEntityRenderer extends BlockEntityRenderer<Detache
private void renderCrack(VertexConsumer vc, MatrixStack matrices, DetachedRiftBlockEntity rift) {
matrices.push();
matrices.translate(0.5, 0.5, 0.5);
RiftCrackRenderer.drawCrack(matrices.peek().getModel(), vc, 0, CURVE, ModConfig.INSTANCE.getGraphicsConfig().riftSize * rift.size / 150, 0);//0xF1234568L * rift.hashCode());
RiftCrackRenderer.drawCrack(matrices.peek().getModel(), vc, 0, CURVE, DimensionalDoorsInitializer.CONFIG.getGraphicsConfig().riftSize * rift.size / 150, 0);//0xF1234568L * rift.hashCode());
matrices.pop();
}

View file

@ -3,6 +3,9 @@ package org.dimdev.dimdoors.item;
import java.util.Objects;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.block.DimensionalPortalBlock;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import net.minecraft.entity.LivingEntity;

View file

@ -1,8 +1,22 @@
package org.dimdev.dimdoors.item;
import java.io.IOException;
import java.util.List;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
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.ServerPlayNetworking;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import net.minecraft.client.item.TooltipContext;
@ -16,14 +30,19 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.fabricmc.api.Environment;
import org.dimdev.dimdoors.network.c2s.HitBlockS2CPacket;
import org.dimdev.dimdoors.network.s2c.PlayerInventorySlotUpdateS2CPacket;
import org.dimdev.dimdoors.rift.targets.IdMarker;
import org.dimdev.dimdoors.util.EntityUtils;
import org.dimdev.dimdoors.world.level.Counter;
import static net.fabricmc.api.EnvType.CLIENT;
public class RiftConfigurationToolItem extends Item {
private static final Logger LOGGER = LogManager.getLogger();
public static final String ID = "rift_configuration_tool";
@ -37,24 +56,80 @@ public class RiftConfigurationToolItem extends Item {
HitResult hit = player.raycast(RaycastHelper.REACH_DISTANCE, 0, false);
if (world.isClient) {
if (!RaycastHelper.hitsRift(hit, world)) {
player.sendMessage(new TranslatableText("tools.rift_miss"), true);
RiftBlockEntity.showRiftCoreUntil = System.currentTimeMillis() + DimensionalDoorsInitializer.CONFIG.getGraphicsConfig().highlightRiftCoreFor;
return TypedActionResult.fail(stack);
} else {
Counter counter = Counter.get(stack);
if (RaycastHelper.hitsRift(hit, world)) {
RiftBlockEntity rift = (RiftBlockEntity) world.getBlockEntity(((BlockHitResult) hit).getBlockPos());
if (rift.getDestination() instanceof IdMarker && ((IdMarker) rift.getDestination()).getId() >= 0) {
EntityUtils.chat(player, Text.of("Id: " + ((IdMarker) rift.getDestination()).getId()));
} else {
int id = counter.increment();
sync(stack, player, hand);
EntityUtils.chat(player, Text.of("Rift stripped of data and set to target id: " + id));
rift.setDestination(new IdMarker(id));
}
return TypedActionResult.success(stack);
} else {
EntityUtils.chat(player, Text.of("Current Count: " + counter.count()));
}
return new TypedActionResult<>(ActionResult.FAIL, stack);
}
if (RaycastHelper.hitsRift(hit, world)) {
RiftBlockEntity rift = (RiftBlockEntity) world.getBlockEntity(new BlockPos(hit.getPos()));
System.out.println(rift);
//TODO: implement this tool's functionality
return new TypedActionResult<>(ActionResult.SUCCESS, stack);
}
return new TypedActionResult<>(ActionResult.FAIL, stack);
return TypedActionResult.success(stack);
}
public static ActionResult onAttackBlockCallback(PlayerEntity player, World world, Hand hand, BlockPos pos, Direction direction) {
if (world.isClient && player.isSneaking() && player.getStackInHand(hand).getItem() instanceof RiftConfigurationToolItem) {
if(Counter.get(player.getStackInHand(hand)).count() != -1 || world.getBlockEntity(pos) instanceof RiftBlockEntity) {
HitBlockS2CPacket packet = new HitBlockS2CPacket(hand, pos, direction);
try {
PacketByteBuf buf = PacketByteBufs.create();
packet.write(buf);
ClientPlayNetworking.send(HitBlockS2CPacket.ID, buf);
} catch (IOException e) {
LOGGER.error(e);
return ActionResult.FAIL;
}
}
return ActionResult.SUCCESS;
}
return ActionResult.PASS;
}
public static void receiveHitBlock(MinecraftServer server, ServerPlayerEntity player, ServerPlayNetworkHandler networkHandler, PacketByteBuf buf, PacketSender sender) {
HitBlockS2CPacket packet = new HitBlockS2CPacket();
try {
packet.read(buf);
server.execute(() -> serverThreadReceiveHitBlock(player, packet.getHand(), packet.getPos()));
} catch (IOException e) {
LOGGER.error(e);
}
}
private static void serverThreadReceiveHitBlock(ServerPlayerEntity player, Hand hand, BlockPos pos) {
ItemStack stack = player.getStackInHand(hand);
if (player.isSneaking() && stack.getItem() instanceof RiftConfigurationToolItem) {
BlockEntity blockEntity = player.getServerWorld().getBlockEntity(pos);
if (blockEntity instanceof RiftBlockEntity) {
RiftBlockEntity rift = (RiftBlockEntity) blockEntity;
if (!(rift.getDestination() instanceof IdMarker) || ((IdMarker) rift.getDestination()).getId() != -1) {
rift.setDestination(new IdMarker(-1));
EntityUtils.chat(player, Text.of("Rift stripped of data and set to invalid id: -1"));
}
} else if (Counter.get(stack).count() != -1){
Counter.get(stack).set(-1);
((RiftConfigurationToolItem) stack.getItem()).sync(stack, player, hand);
EntityUtils.chat(player, Text.of("Counter has been reset."));
}
}
}
@Override
@Environment(CLIENT)
public void appendTooltip(ItemStack itemStack, World world, List<Text> list, TooltipContext tooltipContext) {
@ -62,4 +137,28 @@ public class RiftConfigurationToolItem extends Item {
list.add(new TranslatableText(this.getTranslationKey() + ".info"));
}
}
@Override
public ItemStack getDefaultStack() {
ItemStack defaultStack = super.getDefaultStack();
Counter.get(defaultStack).set(-1);
return defaultStack;
}
private void sync(ItemStack stack, PlayerEntity player, Hand hand) {
ServerPlayerEntity serverPlayer = (ServerPlayerEntity) player;
PlayerInventorySlotUpdateS2CPacket packet;
if (hand == Hand.OFF_HAND) {
packet = new PlayerInventorySlotUpdateS2CPacket(45, stack);
} else {
packet = new PlayerInventorySlotUpdateS2CPacket(serverPlayer.inventory.selectedSlot, stack);
}
PacketByteBuf buf = PacketByteBufs.create();
try {
packet.write(buf);
ServerPlayNetworking.send(serverPlayer, PlayerInventorySlotUpdateS2CPacket.ID, buf);
} catch (IOException e) {
LOGGER.error(e);
}
}
}

View file

@ -0,0 +1,66 @@
package org.dimdev.dimdoors.network.c2s;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import java.io.IOException;
// TODO: replace ClientPlayPackListener
public class HitBlockS2CPacket implements Packet<ClientPlayPacketListener> {
public static Identifier ID = new Identifier("dimdoors:hit_block");
private Hand hand;
private BlockPos pos;
private Direction direction;
public HitBlockS2CPacket() {
}
@Environment(EnvType.CLIENT)
public HitBlockS2CPacket(Hand hand, BlockPos pos, Direction direction) {
this.hand = hand;
this.pos = pos;
this.direction = direction;
}
@Override
public void read(PacketByteBuf buf) throws IOException {
hand = buf.readEnumConstant(Hand.class);
pos = buf.readBlockPos();
direction = buf.readEnumConstant(Direction.class);
}
@Override
public void write(PacketByteBuf buf) throws IOException {
buf.writeEnumConstant(hand);
buf.writeBlockPos(pos);
buf.writeEnumConstant(direction);
}
@Override
public void apply(ClientPlayPacketListener listener) {
// TODO: write method
}
public Hand getHand() {
return hand;
}
public BlockPos getPos() {
return pos;
}
public Direction getDirection() {
return direction;
}
}

View file

@ -0,0 +1,55 @@
package org.dimdev.dimdoors.network.s2c;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.util.Identifier;
import java.io.IOException;
// TODO: replace ClientPlayPackListener
public class PlayerInventorySlotUpdateS2CPacket implements Packet<ClientPlayPacketListener> {
public static Identifier ID = new Identifier("dimdoors:player_inventory_slot_update");
private int slot;
private ItemStack stack;
public PlayerInventorySlotUpdateS2CPacket() {
this.stack = ItemStack.EMPTY;
}
public PlayerInventorySlotUpdateS2CPacket(int slot, ItemStack stack) {
this.slot = slot;
this.stack = stack;
}
@Override
public void read(PacketByteBuf buf) throws IOException {
slot = buf.readInt();
stack = buf.readItemStack();
}
@Override
public void write(PacketByteBuf buf) throws IOException {
buf.writeInt(slot);
buf.writeItemStack(stack);
}
@Override
public void apply(ClientPlayPacketListener listener) {
// TODO: write method
}
@Environment(EnvType.CLIENT)
public int getSlot() {
return slot;
}
@Environment(EnvType.CLIENT)
public ItemStack getStack() {
return stack;
}
}

View file

@ -5,8 +5,11 @@ import java.util.Random;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.ModConfig;
import org.dimdev.dimdoors.pockets.virtual.reference.PocketGeneratorReference;
import org.dimdev.dimdoors.rift.registry.LinkProperties;
import org.dimdev.dimdoors.rift.targets.VirtualTarget;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.world.ModDimensions;
import org.dimdev.dimdoors.world.pocket.Pocket;
@ -26,50 +29,25 @@ public final class PocketGenerator {
return pocket;
}
private static Pocket prepareAndPlaceV2Pocket(ServerWorld world, PocketTemplateV2 pocketTemplate, VirtualLocation virtualLocation, boolean setup) {
LOGGER.info("Generating pocket from template " + pocketTemplate.getId() + " at virtual location " + virtualLocation);
Pocket pocket = DimensionalRegistry.getPocketDirectory(world.getRegistryKey()).newPocket();
pocketTemplate.place(pocket);
pocket.virtualLocation = virtualLocation;
return pocket;
}
public static Pocket generatePocketFromTemplate(ServerWorld world, PocketTemplate pocketTemplate, VirtualLocation virtualLocation, boolean setup) {
Pocket pocket = prepareAndPlacePocket(world, pocketTemplate, virtualLocation, setup);
if (setup) pocketTemplate.setup(pocket, null, null);
return pocket;
}
public static Pocket generateV2PocketFromTemplate(ServerWorld world, PocketTemplateV2 pocketTemplate, VirtualLocation virtualLocation, boolean setup) {
Pocket pocket = prepareAndPlaceV2Pocket(world, pocketTemplate, virtualLocation, setup);
if (setup) {
pocketTemplate.setup(pocket, null, null);
}
return pocket;
}
public static Pocket generatePocketFromTemplate(ServerWorld world, PocketTemplate pocketTemplate, VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) {
Pocket pocket = prepareAndPlacePocket(world, pocketTemplate, virtualLocation, true);
pocketTemplate.setup(pocket, linkTo, linkProperties);
return pocket;
}
public static Pocket generateV2PocketFromTemplate(ServerWorld world, PocketTemplateV2 pocketTemplate, VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) {
Pocket pocket = prepareAndPlaceV2Pocket(world, pocketTemplate, virtualLocation, true);
pocketTemplate.setup(pocket, linkTo, linkProperties);
return pocket;
}
public static Pocket generatePrivatePocket(VirtualLocation virtualLocation) {
PocketTemplate pocketTemplate = SchematicHandler.INSTANCE.getPersonalPocketTemplate();
return generatePocketFromTemplate(DimensionalDoorsInitializer.getWorld(ModDimensions.PERSONAL), pocketTemplate, virtualLocation, true);
}
public static Pocket generatePrivatePocketV2(VirtualLocation virtualLocation) {
PocketTemplateV2 pocketTemplate = SchematicV2Handler.getInstance().getRandomPrivatePocket();
return generateV2PocketFromTemplate(DimensionalDoorsInitializer.getWorld(ModDimensions.PERSONAL), pocketTemplate, virtualLocation, true);
return generateFromPocketGroupV2(DimensionalDoorsInitializer.getWorld(ModDimensions.PERSONAL), "private", virtualLocation, null, null);
}
// TODO: size of public pockets should increase with depth
@ -79,10 +57,22 @@ public final class PocketGenerator {
}
public static Pocket generatePublicPocketV2(VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) {
PocketTemplateV2 pocketTemplate = SchematicV2Handler.getInstance().getRandomPublicPocket();
return generateV2PocketFromTemplate(DimensionalDoorsInitializer.getWorld(ModDimensions.PUBLIC), pocketTemplate, virtualLocation, linkTo, linkProperties);
return generateFromPocketGroupV2(DimensionalDoorsInitializer.getWorld(ModDimensions.PUBLIC), "public", virtualLocation, linkTo, linkProperties);
}
public static Pocket generateFromPocketGroupV2(ServerWorld world, String group, VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) {
PocketGenerationParameters parameters = new PocketGenerationParameters(world, group, virtualLocation, linkTo, linkProperties);
return generatePocketV2(SchematicV2Handler.getInstance().getGroup(group).getNextPocketGeneratorReference(parameters), parameters);
}
public static Pocket generatePocketV2(PocketGeneratorReference pocketGeneratorReference, PocketGenerationParameters parameters) {
return pocketGeneratorReference.prepareAndPlacePocket(parameters);
}
public static Pocket generateDungeonPocketV2(VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) {
return generateFromPocketGroupV2(DimensionalDoorsInitializer.getWorld(ModDimensions.DUNGEON), "dungeon", virtualLocation, linkTo, linkProperties);
}
/**
* Create a dungeon pockets at a certain depth.
*

View file

@ -1,44 +1,28 @@
package org.dimdev.dimdoors.pockets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import net.minecraft.util.math.Vec3i;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.rift.registry.LinkProperties;
import org.dimdev.dimdoors.rift.targets.VirtualTarget;
import org.dimdev.dimdoors.util.Location;
import org.dimdev.dimdoors.util.schematic.v2.Schematic;
import org.dimdev.dimdoors.util.schematic.v2.SchematicPlacer;
import org.dimdev.dimdoors.world.pocket.Pocket;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.block.entity.DispenserBlockEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
public class PocketTemplateV2 {
private static final Logger LOGGER = LogManager.getLogger();
private static final boolean replacingPlaceholders = false;
private final Schematic schematic;
private final String group;
private final int size;
private final String id;
public PocketTemplateV2(Schematic schematic, String group, int size, String id, float weight) {
public PocketTemplateV2(Schematic schematic, String id) {
this.schematic = schematic;
this.group = group;
this.size = size;
this.id = id;
}
/*
public void setup(Pocket pocket, VirtualTarget linkTo, LinkProperties linkProperties) {
ServerWorld world = DimensionalDoorsInitializer.getWorld(pocket.world);
@ -71,11 +55,12 @@ public class PocketTemplateV2 {
TemplateUtils.registerRifts(rifts, linkTo, linkProperties, pocket);
}
*/
public void place(Pocket pocket) {
pocket.setSize(this.size * 16, this.size * 16, this.size * 16);
pocket.setSize(schematic.getWidth(), schematic.getHeight(), schematic.getLength());
ServerWorld world = DimensionalDoorsInitializer.getWorld(pocket.world);
BlockPos origin = new BlockPos(pocket.box.minX, pocket.box.minY, pocket.box.minZ);
BlockPos origin = pocket.getOrigin();
LOGGER.info("Placing new pocket using schematic " + this.id + " at x = " + origin.getX() + ", z = " + origin.getZ());
SchematicPlacer.place(this.schematic, world, origin);
}
@ -84,10 +69,6 @@ public class PocketTemplateV2 {
return replacingPlaceholders;
}
public String getGroup() {
return this.group;
}
public Schematic getSchematic() {
return this.schematic;
}

View file

@ -1,104 +0,0 @@
package org.dimdev.dimdoors.pockets;
import java.util.List;
import java.util.Objects;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
public final class PocketType {
public static final Codec<PocketType> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.STRING.fieldOf("group").forGetter(PocketType::getGroup),
PocketEntry.CODEC.listOf().fieldOf("pockets").forGetter(PocketType::getEntries)
).apply(instance, PocketType::new));
private final String group;
private final List<PocketEntry> entries;
public PocketType(String group, List<PocketEntry> entries) {
this.group = group;
this.entries = entries;
}
public String getGroup() {
return this.group;
}
public List<PocketEntry> getEntries() {
return this.entries;
}
@Override
public String toString() {
return "PocketType{" +
"group='" + this.group + '\'' +
", entries=" + this.entries +
'}';
}
@Override
public boolean equals(Object o) {
if (super.equals(o)) return true;
if (o == null || this.getClass() != o.getClass()) return false;
PocketType that = (PocketType) o;
return Objects.equals(this.group, that.group) &&
Objects.equals(this.entries, that.entries);
}
@Override
public int hashCode() {
return Objects.hash(this.group, this.entries);
}
public static final class PocketEntry {
public static final Codec<PocketEntry> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.INT.fieldOf("size").forGetter(PocketEntry::getSize),
Codec.STRING.fieldOf("id").forGetter(PocketEntry::getName),
Codec.INT.optionalFieldOf("weight", 5).forGetter(PocketEntry::getWeight)
).apply(instance, PocketEntry::new));
private final int size;
private final String name;
private final int weight;
PocketEntry(int size, String name, int weight) {
this.size = size;
this.name = name;
this.weight = weight;
}
public int getSize() {
return this.size;
}
public String getName() {
return this.name;
}
public int getWeight() {
return this.weight;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || this.getClass() != o.getClass()) return false;
PocketEntry that = (PocketEntry) o;
return this.size == that.size &&
Float.compare(that.weight, this.weight) == 0 &&
this.name.equals(that.name);
}
@Override
public int hashCode() {
return Objects.hash(this.size, this.name, this.weight);
}
@Override
public String toString() {
return "PocketEntry{" +
"size=" + this.size +
", name='" + this.name + '\'' +
", weight=" + this.weight +
'}';
}
}
}

View file

@ -1,40 +1,39 @@
package org.dimdev.dimdoors.pockets;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.common.collect.*;
import com.google.gson.*;
import com.mojang.serialization.JsonOps;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.nbt.*;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
import org.dimdev.dimdoors.pockets.virtual.VirtualPocket;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.WeightedList;
import org.dimdev.dimdoors.util.schematic.v2.Schematic;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
public class SchematicV2Handler {
private static final Logger LOGGER = LogManager.getLogger();
private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create();
private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create();
private static final SchematicV2Handler INSTANCE = new SchematicV2Handler();
private final List<PocketTemplateV2> templates = Lists.newArrayList();
private final Multimap<String, PocketTemplateV2> templateMap = HashMultimap.create();
private final List<PocketType> pocketTypes = Lists.newArrayList();
private static final Random RANDOM = new Random(new Random().nextLong());
private final Map<String, PocketGenerator> pocketGeneratorMap = Maps.newHashMap();
private final Map<String, VirtualPocket> pocketGroups = Maps.newHashMap();
private final Map<Identifier, PocketTemplateV2> templates = Maps.newHashMap();
private boolean loaded = false;
private SchematicV2Handler() {
@ -42,67 +41,127 @@ public class SchematicV2Handler {
public void load() {
if (this.loaded) {
throw new UnsupportedOperationException("Attempted to load schematics twice!");
throw new UnsupportedOperationException("Attempted to load pockets twice!");
}
this.loaded = true;
long startTime = System.currentTimeMillis();
Set<String> names = ImmutableSet.of("default_private", "default_public");
for (String name : names) {
try (BufferedReader reader = Files.newBufferedReader(Paths.get(SchematicV2Handler.class.getResource(String.format("/data/dimdoors/pockets/json/v2/%s.json", name)).toURI()))) {
List<String> result = new ArrayList<>();
while (true) {
String line = reader.readLine();
if (line == null) {
break;
}
result.add(line);
}
JsonObject json = GSON.fromJson(String.join("", result), JsonObject.class);
PocketType type = PocketType.CODEC.decode(JsonOps.INSTANCE, json).getOrThrow(false, System.err::println).getFirst();
this.pocketTypes.add(type);
this.loadResourceSchematics(type);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
}
LOGGER.info("Loaded schematics in {} seconds", System.currentTimeMillis() - startTime);
try {
Path path = Paths.get(SchematicV2Handler.class.getResource("/data/dimdoors/pockets/generators").toURI());
loadJson(path, new String[0], this::loadPocketGenerator);
LOGGER.info("Loaded pockets in {} seconds", System.currentTimeMillis() - startTime);
} catch (URISyntaxException e) {
LOGGER.error(e);
}
startTime = System.currentTimeMillis();
try {
Path path = Paths.get(SchematicV2Handler.class.getResource("/data/dimdoors/pockets/groups").toURI());
loadJson(path, new String[0], this::loadPocketGroup);
LOGGER.info("Loaded pocket groups in {} seconds", System.currentTimeMillis() - startTime);
} catch (URISyntaxException e) {
LOGGER.error(e);
}
}
private void loadResourceSchematics(PocketType type) throws URISyntaxException, IOException {
String group = type.getGroup();
Path basePath = Paths.get(SchematicV2Handler.class.getResource(String.format("/data/dimdoors/pockets/schematic/v2/%s/", group)).toURI());
for (PocketType.PocketEntry entry : type.getEntries()) {
Path schemPath = basePath.resolve(entry.getName() + ".schem");
CompoundTag schemTag = NbtIo.readCompressed(Files.newInputStream(schemPath));
Schematic schematic = Schematic.fromTag(schemTag);
for (int i = 0; i < entry.getWeight(); i++) {
this.templateMap.put(group, new PocketTemplateV2(schematic, group, entry.getSize(), entry.getName(), entry.getWeight()));
}
}
}
public Tag readNbtFromJson(String id) {
try {
Path path = Paths.get(SchematicV2Handler.class.getResource("/data/dimdoors/pockets/json/" + id + ".json").toURI());
if (!Files.isRegularFile(path)) {
return null;
}
try {
JsonElement json = GSON.fromJson(String.join("", Files.readAllLines(path)), JsonElement.class);
return JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, json);
} catch (IOException e) {
LOGGER.error(e);
}
} catch (URISyntaxException e) {
LOGGER.error(e);
}
return null;
}
public PocketTemplateV2 getRandomPublicPocket() {
Collection<PocketTemplateV2> publicPockets = this.templateMap.get("public");
int index = RANDOM.nextInt(publicPockets.size());
return Lists.newArrayList(publicPockets).get(0);
}
public <T> T readNbtSerializableFromJson(String id, Function<Tag, T> reader) {
Tag tag = readNbtFromJson(id);
if (tag == null) return null;
return reader.apply(tag);
}
public PocketTemplateV2 getRandomPrivatePocket() {
Collection<PocketTemplateV2> publicPockets = this.templateMap.get("private");
int index = RANDOM.nextInt(publicPockets.size());
return Lists.newArrayList(publicPockets).get(0);
}
// TODO: fix, some weird "/" stuff
private void loadJson(Path path, String[] idParts, BiConsumer<String, Tag> loader) {
if (Files.isDirectory(path)) {
try {
for (Path directoryPath : Files.newDirectoryStream(path)) {
String[] directoryIdParts = Arrays.copyOf(idParts, idParts.length + 1);
String fileName = directoryPath.getFileName().toString();
if (fileName.endsWith("/")) fileName = fileName.substring(0, fileName.length()-1); // https://bugs.openjdk.java.net/browse/JDK-8153248
if (Files.isRegularFile(directoryPath)) fileName = fileName.substring(0, fileName.lastIndexOf('.')); // cut extension
directoryIdParts[directoryIdParts.length - 1] = fileName;
loadJson(directoryPath, directoryIdParts, loader);
}
} catch (IOException e) {
LOGGER.error("could not load pocket data in path " + path.toString() + " due to malformed json.", e);
}
} else if(Files.isRegularFile(path) && path.getFileName().toString().endsWith(".json")) {
String id = String.join("/", idParts);
try {
JsonElement json = GSON.fromJson(String.join("", Files.readAllLines(path)), JsonElement.class);
loader.accept(id, JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, json));
} catch (IOException e) {
LOGGER.error("could not load pocket data in path " + path.toString() + " due to malformed json.", e);
}
}
}
private void loadPocketGroup(String id, Tag tag) {
VirtualPocket group = VirtualPocket.deserialize(tag);
pocketGroups.put(id, group);
}
private void loadPocketGenerator(String id, Tag tag) {
if (tag == null || tag.getType() != NbtType.COMPOUND) {
LOGGER.error("Could not load PocketGenerator " + id + " since the json does not represent a CompoundTag!");
return;
}
PocketGenerator gen = PocketGenerator.deserialize((CompoundTag) tag);
if (gen != null) pocketGeneratorMap.put(id, gen);
}
public void loadSchematic(Identifier templateID, String id) {
try {
if (templates.containsKey(templateID)) return;
Path schemPath = Paths.get(SchematicV2Handler.class.getResource(String.format("/data/dimdoors/pockets/schematic/%s.schem", id.replaceAll("\\.", "/"))).toURI());
CompoundTag schemTag = NbtIo.readCompressed(Files.newInputStream(schemPath));
Schematic schematic = Schematic.fromTag(schemTag);
PocketTemplateV2 template = new PocketTemplateV2(schematic, id);
templates.put(templateID, template);
} catch (URISyntaxException | IOException e) {
LOGGER.error("Could not load schematic!", e);
}
}
public WeightedList<PocketGenerator, PocketGenerationParameters> getPocketsMatchingTags(List<String> required, List<String> blackList, boolean exact) {
return new WeightedList<>(pocketGeneratorMap.values().stream().filter(pocketGenerator -> pocketGenerator.checkTags(required, blackList, exact)).collect(Collectors.toList()));
}
public VirtualPocket getGroup(String group) {
return pocketGroups.get(group);
}
public static SchematicV2Handler getInstance() {
return INSTANCE;
}
public List<PocketTemplateV2> getTemplates() {
public Map<Identifier, PocketTemplateV2> getTemplates() {
return this.templates;
}
public List<PocketType> getPocketTypes() {
return this.pocketTypes;
public Map<String, VirtualPocket> getPocketGroups() {
return this.pocketGroups;
}
public PocketGenerator getGenerator(String id) {
return pocketGeneratorMap.get(id);
}
}

View file

@ -5,6 +5,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import net.minecraft.loot.context.LootContextParameters;
import net.minecraft.util.math.Vec3d;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity;
@ -59,7 +61,7 @@ public class TemplateUtils {
}
}
static void setupLootTable(ServerWorld world, BlockEntity tile, Inventory inventory, Logger logger) {
public static void setupLootTable(ServerWorld world, BlockEntity tile, Inventory inventory, Logger logger) {
LootTable table;
if (tile instanceof ChestBlockEntity) {
logger.debug("Now populating chest.");
@ -68,11 +70,11 @@ public class TemplateUtils {
logger.debug("Now populating dispenser.");
table = world.getServer().getLootManager().getTable(new Identifier("dimdoors:dispenser_projectiles"));
}
LootContext ctx = new LootContext.Builder(world).random(world.random).build(LootContextTypes.CHEST);
LootContext ctx = new LootContext.Builder(world).random(world.random).parameter(LootContextParameters.ORIGIN, Vec3d.of(tile.getPos())).build(LootContextTypes.CHEST);
table.supplyInventory(inventory, ctx);
}
static void registerRifts(List<? extends RiftBlockEntity> rifts, VirtualTarget linkTo, LinkProperties linkProperties, Pocket pocket) {
static public void registerRifts(List<? extends RiftBlockEntity> rifts, VirtualTarget linkTo, LinkProperties linkProperties, Pocket pocket) {
ServerWorld world = DimensionalDoorsInitializer.getWorld(pocket.world);
HashMap<RiftBlockEntity, Float> entranceWeights = new HashMap<>();

View file

@ -0,0 +1,228 @@
package org.dimdev.dimdoors.pockets.generator;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerLightingProvider;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.*;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.ChunkRegion;
import net.minecraft.world.Heightmap;
import net.minecraft.world.chunk.*;
import net.minecraft.world.gen.GenerationStep;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.entity.DetachedRiftBlockEntity;
import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes;
import org.dimdev.dimdoors.rift.targets.PocketEntranceMarker;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.TeleportUtil;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.world.pocket.Pocket;
import org.dimdev.dimdoors.world.pocket.VirtualLocation;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ChunkGenerator extends PocketGenerator {
private static final Logger LOGGER = LogManager.getLogger();
public static final String KEY = "chunk";
private Identifier dimensionID;
private Vec3i size; // TODO: equation-ify
private Vec3i offset; // TODO: equation-ify
private int virtualYOffset; // TODO: equation-ify
public ChunkGenerator() {
}
@Override
public PocketGenerator fromTag(CompoundTag tag) {
super.fromTag(tag);
this.dimensionID = new Identifier(tag.getString("dimension_id"));
int[] temp = tag.getIntArray("size");
this.size = new Vec3i(temp[0], temp[1], temp[2]);
temp = tag.contains("offset") ? tag.getIntArray("offset") : new int[]{0, 0, 0};
this.offset = new Vec3i(temp[0], temp[1], temp[2]);
this.virtualYOffset = tag.contains("virtual_y_offset") ? tag.getInt("virtual_y_offset") : 0;
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
tag.putString("dimension_id", dimensionID.toString());
tag.putIntArray("size", new int[]{this.size.getX(), this.size.getY(), this.size.getZ()});
if (!(offset.getX() == 0 && offset.getY() == 0 && offset.getZ() == 0)) {
tag.putIntArray("offset", new int[]{this.offset.getX(), this.offset.getY(), this.offset.getZ()});
}
tag.putInt("virtual_y_offset", this.virtualYOffset);
return tag;
}
@Override
public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters) {
ServerWorld world = parameters.getWorld();
VirtualLocation sourceVirtualLocation = parameters.getSourceVirtualLocation();
int chunkSizeX = ((this.size.getX() >> 4) + (this.size.getX() % 16 == 0 ? 0 : 1));
int chunkSizeZ = ((this.size.getZ() >> 4) + (this.size.getZ() % 16 == 0 ? 0 : 1));
Pocket pocket = DimensionalRegistry.getPocketDirectory(world.getRegistryKey()).newPocket();
pocket.setSize(size);
pocket.offsetOrigin(offset);
LOGGER.info("Generating chunk pocket at location " + pocket.getOrigin());
ServerWorld genWorld = DimensionalDoorsInitializer.getWorld(RegistryKey.of(Registry.DIMENSION, dimensionID));
net.minecraft.world.gen.chunk.ChunkGenerator genWorldChunkGenerator = genWorld.getChunkManager().getChunkGenerator();
ArrayList<Chunk> protoChunks = new ArrayList<>();
for (int z = 0; z < chunkSizeZ; z++) {
for (int x = 0; x < chunkSizeX; x++) {
ProtoChunk protoChunk = new ProtoChunk(new ChunkPos(pocket.getOrigin().add(x * 16, 0, z * 16)), UpgradeData.NO_UPGRADE_DATA);
protoChunk.setLightingProvider(genWorld.getLightingProvider());
protoChunks.add(protoChunk);
}
}
ChunkRegion protoRegion = new ChunkRegionHack(genWorld, protoChunks);
for (Chunk protoChunk : protoChunks) { // TODO: check wether structures are even activated
genWorldChunkGenerator.setStructureStarts(genWorld.getRegistryManager(), genWorld.getStructureAccessor().forRegion(protoRegion), protoChunk, genWorld.getStructureManager(), genWorld.getSeed());
((ProtoChunk) protoChunk).setStatus(ChunkStatus.STRUCTURE_STARTS);
}
for (Chunk protoChunk : protoChunks) {
genWorldChunkGenerator.addStructureReferences(protoRegion, genWorld.getStructureAccessor().forRegion(protoRegion), protoChunk);
((ProtoChunk) protoChunk).setStatus(ChunkStatus.STRUCTURE_REFERENCES);
}
for (Chunk protoChunk : protoChunks) {
genWorldChunkGenerator.populateBiomes(BuiltinRegistries.BIOME, protoChunk);
((ProtoChunk) protoChunk).setStatus(ChunkStatus.BIOMES);
}
for (Chunk protoChunk : protoChunks) {
genWorldChunkGenerator.populateNoise(genWorld, genWorld.getStructureAccessor().forRegion(protoRegion), protoChunk);
((ProtoChunk) protoChunk).setStatus(ChunkStatus.NOISE);
}
for (Chunk protoChunk : protoChunks) {
genWorldChunkGenerator.buildSurface(protoRegion, protoChunk);
((ProtoChunk) protoChunk).setStatus(ChunkStatus.SURFACE);
}
for (GenerationStep.Carver carver : GenerationStep.Carver.values()) {
for (Chunk protoChunk : protoChunks) {
genWorldChunkGenerator.carve(genWorld.getSeed(), genWorld.getBiomeAccess(), protoChunk, carver);
ProtoChunk pChunk = ((ProtoChunk) protoChunk);
if (pChunk.getStatus() == ChunkStatus.SURFACE) pChunk.setStatus(ChunkStatus.CARVERS);
else pChunk.setStatus(ChunkStatus.LIQUID_CARVERS);
}
}
for (Chunk protoChunk : protoChunks) {
ChunkRegion tempRegion = new ChunkRegionHack(genWorld, ChunkPos.stream(protoChunk.getPos(), 10).map(chunkPos -> protoRegion.getChunk(chunkPos.x, chunkPos.z)).collect(Collectors.toList()));
genWorldChunkGenerator.generateFeatures(tempRegion, genWorld.getStructureAccessor().forRegion(tempRegion));
((ProtoChunk) protoChunk).setStatus(ChunkStatus.FEATURES);
}
for (Chunk protoChunk : protoChunks) { // likely only necessary for spawn step since we copy over anyways
((ServerLightingProvider) genWorld.getLightingProvider()).light(protoChunk, false);
((ProtoChunk) protoChunk).setStatus(ChunkStatus.LIGHT);
}
for (Chunk protoChunk : protoChunks) { // TODO: does this even work?
ChunkRegion tempRegion = new ChunkRegionHack(genWorld, ChunkPos.stream(protoChunk.getPos(), 5).map(chunkPos -> protoRegion.getChunk(chunkPos.x, chunkPos.z)).collect(Collectors.toList()));
genWorldChunkGenerator.populateEntities(tempRegion);
((ProtoChunk) protoChunk).setStatus(ChunkStatus.SPAWN);
}
BlockPos firstCorner = pocket.getOrigin();
BlockPos secondCorner = new BlockPos(firstCorner.getX() + size.getX() - 1, Math.min(firstCorner.getY() + size.getY() - 1, world.getHeight() - virtualYOffset - 1), firstCorner.getZ() + size.getZ() - 1); // subtracting 1 here since it should be 0 inclusive and size exclusive
BlockPos pocketOriginChunkOffset = new ChunkPos(pocket.getOrigin()).getStartPos().subtract(firstCorner);
for (BlockPos blockPos : BlockPos.iterate(firstCorner, secondCorner)) {
BlockPos sourcePos = blockPos.add(pocketOriginChunkOffset).add(0, virtualYOffset, 0);
BlockState blockState = protoRegion.getBlockState(sourcePos);
if (!blockState.isAir()) {
world.setBlockState(blockPos, protoRegion.getBlockState(blockPos.add(pocketOriginChunkOffset).add(0, virtualYOffset, 0)));
}
}
Box realBox = new Box(firstCorner, secondCorner);
for (Chunk protoChunk : protoChunks) {
for(BlockPos virtualBlockPos : protoChunk.getBlockEntityPositions()) {
BlockPos realBlockPos = virtualBlockPos.subtract(pocketOriginChunkOffset).add(0, -virtualYOffset, 0);
if (realBox.contains(realBlockPos.getX(), realBlockPos.getY(), realBlockPos.getZ())) {
world.setBlockEntity(realBlockPos, protoChunk.getBlockEntity(virtualBlockPos)); // TODO: ensure this works, likely bugged
}
}
}
Box virtualBox = realBox.offset(pocketOriginChunkOffset.add(0, virtualYOffset, 0));
for (Entity entity : protoRegion.getOtherEntities(null, virtualBox)) { // TODO: does this even work?
TeleportUtil.teleport(entity, world, entity.getPos().add(-pocketOriginChunkOffset.getX(), -pocketOriginChunkOffset.getY() - virtualYOffset, -pocketOriginChunkOffset.getZ()), entity.yaw);
} // TODO: Entities?/ Biomes/ Structure Data
world.setBlockState(world.getTopPosition(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, pocket.getOrigin()), ModBlocks.DETACHED_RIFT.getDefaultState());
DetachedRiftBlockEntity rift = ModBlockEntityTypes.DETACHED_RIFT.instantiate();
world.setBlockEntity(world.getTopPosition(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, pocket.getOrigin()), rift);
rift.setDestination(new PocketEntranceMarker());
pocket.virtualLocation = sourceVirtualLocation;
return pocket;
}
@Override
public PocketGeneratorType<? extends PocketGenerator> getType() {
return PocketGeneratorType.CHUNK;
}
@Override
public String getKey() {
return KEY;
}
private static class ChunkRegionHack extends ChunkRegion { // Please someone tell me if there is a better way
ChunkRegionHack(ServerWorld world, List<Chunk> chunks) {
super(world, chunks);
}
@Override
public Chunk getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
Chunk chunk = super.getChunk(chunkX, chunkZ, leastStatus, false);
return chunk == null ? new ProtoChunkHack(new ChunkPos(chunkX, chunkZ), UpgradeData.NO_UPGRADE_DATA) : chunk;
}
// TODO: Override getSeed()
}
private static class ProtoChunkHack extends ProtoChunk { // exists solely to make some calls in the non utilized chunks faster
public ProtoChunkHack(ChunkPos pos, UpgradeData upgradeData) {
super(pos, upgradeData);
}
@Override
public BlockState setBlockState(BlockPos pos, BlockState state, boolean moved) {
return Blocks.VOID_AIR.getDefaultState();
}
@Override
public BlockState getBlockState(BlockPos pos) {
return Blocks.VOID_AIR.getDefaultState();
}
@Override
public FluidState getFluidState(BlockPos pos) {
return Fluids.EMPTY.getDefaultState();
}
}
}

View file

@ -0,0 +1,213 @@
package org.dimdev.dimdoors.pockets.generator;
import com.mojang.serialization.Lifecycle;
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.block.entity.DispenserBlockEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
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.util.registry.SimpleRegistry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.pockets.TemplateUtils;
import org.dimdev.dimdoors.pockets.modifier.Modifier;
import org.dimdev.dimdoors.pockets.modifier.RiftManager;
import org.dimdev.dimdoors.util.Location;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.Weighted;
import org.dimdev.dimdoors.util.math.Equation;
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
import org.dimdev.dimdoors.world.pocket.Pocket;
import java.util.*;
import java.util.function.Supplier;
public abstract class PocketGenerator implements Weighted<PocketGenerationParameters> {
private static final Logger LOGGER = LogManager.getLogger();
public static final Registry<PocketGeneratorType<? extends PocketGenerator>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<PocketGeneratorType<? extends PocketGenerator>>(RegistryKey.ofRegistry(new Identifier("dimdoors", "pocket_generator_type")), Lifecycle.stable())).buildAndRegister();
private static final String defaultWeightEquation = "5"; // TODO: make config
private static final int fallbackWeight = 5; // TODO: make config
private final List<Modifier> modifierList = new ArrayList<>();
private String weight;
private Equation weightEquation;
private final List<String> tags = new ArrayList<>();
public PocketGenerator() { }
public PocketGenerator(String weight) {
this.weight = weight;
parseWeight();
}
public static PocketGenerator deserialize(CompoundTag tag) {
Identifier id = Identifier.tryParse(tag.getString("type")); // TODO: return some NONE PocketGenerator if type cannot be found or deserialization fails.
PocketGeneratorType<? extends PocketGenerator> type = REGISTRY.get(id);
if (type == null) {
LOGGER.error("Could not deserialize PocketGenerator: " + tag.toString());
return null;
}
return type.fromTag(tag);
}
public static CompoundTag serialize(PocketGenerator pocketGenerator) {
return pocketGenerator.toTag(new CompoundTag());
}
private void parseWeight() {
try {
this.weightEquation = Equation.parse(weight);
} catch (EquationParseException e) {
LOGGER.error("Could not parse weight equation \"" + weight + "\", defaulting to default weight equation \"" + defaultWeightEquation + "\"", e);
try {
this.weightEquation = Equation.parse(defaultWeightEquation);
} catch (EquationParseException equationParseException) {
LOGGER.error("Could not parse default weight equation \"" + defaultWeightEquation + "\", defaulting to fallback weight \"" + fallbackWeight + "\"", equationParseException);
this.weightEquation = stringDoubleMap -> fallbackWeight;
}
}
}
public PocketGenerator fromTag(CompoundTag tag) {
this.weight = tag.contains("weight") ? tag.getString("weight") : defaultWeightEquation;
parseWeight();
if (tag.contains("modifiers")) {
ListTag modifiersTag = tag.getList("modifiers", 10);
for (int i = 0; i < modifiersTag.size(); i++) {
modifierList.add(Modifier.deserialize(modifiersTag.getCompound(i)));
}
}
if (tag.contains("tags")) {
ListTag listTag = tag.getList("tags", NbtType.STRING);
for (int i = 0; i < listTag.size(); i++) {
tags.add(listTag.getString(i));
}
}
return this;
}
public CompoundTag toTag(CompoundTag tag) {
this.getType().toTag(tag);
if (!weight.equals("5")) tag.putString("weight", weight);
ListTag modifiersTag = new ListTag();
for (Modifier modifier : modifierList) {
modifiersTag.add(modifier.toTag(new CompoundTag()));
}
if (modifiersTag.size() > 0) tag.put("modifiers", modifiersTag);
if (tags.size() > 0) {
ListTag listTag = new ListTag();
for (String tagString : tags) {
listTag.add(StringTag.of(tagString));
}
tag.put("tags", listTag);
}
return tag;
}
public abstract Pocket prepareAndPlacePocket(PocketGenerationParameters parameters);
public abstract PocketGeneratorType<? extends PocketGenerator> getType();
public abstract String getKey();
@Override
public double getWeight(PocketGenerationParameters parameters) {
return this.weightEquation.apply(parameters.toVariableMap(new HashMap<>()));
}
public void applyModifiers(PocketGenerationParameters parameters, RiftManager manager) {
for (Modifier modifier : modifierList) {
modifier.apply(parameters, manager);
}
}
public void setup(Pocket pocket, PocketGenerationParameters parameters, boolean setupLootTables) {
ServerWorld world = DimensionalDoorsInitializer.getWorld(pocket.world);
List<RiftBlockEntity> rifts = new ArrayList<>();
pocket.getBlockEntities().forEach((blockPos, blockEntity) -> {
if (blockEntity instanceof RiftBlockEntity) {
LOGGER.debug("Rift found in pocket at " + blockPos);
RiftBlockEntity rift = (RiftBlockEntity) blockEntity;
rift.getDestination().setLocation(new Location((ServerWorld) Objects.requireNonNull(rift.getWorld()), rift.getPos()));
rifts.add(rift);
} else if (setupLootTables && blockEntity instanceof Inventory) {
Inventory inventory = (Inventory) blockEntity;
if (inventory.isEmpty()) {
if (blockEntity instanceof ChestBlockEntity || blockEntity instanceof DispenserBlockEntity) {
TemplateUtils.setupLootTable(world, blockEntity, inventory, LOGGER);
if (inventory.isEmpty()) {
LOGGER.error(", however Inventory is: empty!");
}
}
}
}
});
TemplateUtils.registerRifts(rifts, parameters.getLinkTo(), parameters.getLinkProperties(), pocket);
pocket.virtualLocation = parameters.getSourceVirtualLocation(); //TODO: this makes very little sense
}
// why would you want to check for exact tags, but still need a blackList? Good question, but there is probably some use case for it.
public boolean checkTags(List<String> required, List<String> blackList, boolean exact) {
if (exact && required.size() != tags.size()) return false;
if (required != null) {
for (String req : required) {
if (!tags.contains(req)) return false;
}
}
if (blackList != null) {
for (String black : blackList) {
if (tags.contains(black)) return false;
}
}
return true;
}
public interface PocketGeneratorType<T extends PocketGenerator> {
PocketGeneratorType<SchematicGenerator> SCHEMATIC = register(new Identifier("dimdoors", SchematicGenerator.KEY), SchematicGenerator::new);
PocketGeneratorType<ChunkGenerator> CHUNK = register(new Identifier("dimdoors", ChunkGenerator.KEY), ChunkGenerator::new);
PocketGeneratorType<VoidGenerator> VOID = register(new Identifier("dimdoors", VoidGenerator.KEY), VoidGenerator::new);
PocketGenerator fromTag(CompoundTag tag);
CompoundTag toTag(CompoundTag tag);
static void register() {
}
static <U extends PocketGenerator> PocketGeneratorType<U> register(Identifier id, Supplier<U> constructor) {
return Registry.register(REGISTRY, id, new PocketGeneratorType<U>() {
@Override
public PocketGenerator fromTag(CompoundTag tag) {
return constructor.get().fromTag(tag);
}
@Override
public CompoundTag toTag(CompoundTag tag) {
tag.putString("type", id.toString());
return tag;
}
});
}
}
}

View file

@ -0,0 +1,121 @@
package org.dimdev.dimdoors.pockets.generator;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.pockets.PocketTemplateV2;
import org.dimdev.dimdoors.pockets.SchematicV2Handler;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.math.Equation;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.world.pocket.Pocket;
import java.util.HashMap;
import java.util.Map;
public class SchematicGenerator extends PocketGenerator {
private static final Logger LOGGER = LogManager.getLogger();
public static final String KEY = "schematic";
/*
public static final Codec<SchematicGenerator> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.INT.fieldOf("size").forGetter(SchematicGenerator::getSize),
Codec.STRING.fieldOf("id").forGetter(SchematicGenerator::getName),
Codec.INT.optionalFieldOf("weight", 5).forGetter(schematicGenerator -> schematicGenerator.getWeight(null))
).apply(instance, SchematicGenerator::new));
*/
private String id;
private Identifier templateID;
private Equation lengthEquation;
private String offsetX;
private Equation offsetXEquation;
private String offsetY;
private Equation offsetYEquation;
private String offsetZ;
private Equation offsetZEquation;
public SchematicGenerator() {
}
public SchematicGenerator(String id) {
this.id = id;
this.templateID = new Identifier("dimdoors", id);
}
public String getId() {
return this.id;
}
public Identifier getTemplateID() {
return templateID;
}
@Override
public PocketGenerator fromTag(CompoundTag tag) {
super.fromTag(tag);
this.id = tag.getString("id");
this.templateID = new Identifier("dimdoors", id);
SchematicV2Handler.getInstance().loadSchematic(templateID, id);
try {
offsetX = tag.contains("offset_x") ? tag.getString("offset_x") : "0";
offsetXEquation = Equation.parse(offsetX);
offsetY = tag.contains("offset_y") ? tag.getString("offset_y") : "0";
offsetYEquation = Equation.parse(offsetY);
offsetZ = tag.contains("offset_z") ? tag.getString("offset_z") : "0";
offsetZEquation = Equation.parse(offsetZ);
} catch (Equation.EquationParseException e) {
LOGGER.error(e);
}
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
tag.putString("id", this.id);
if (!offsetX.equals("0")) tag.putString("offset_x", offsetX);
if (!offsetY.equals("0")) tag.putString("offset_y", offsetY);
if (!offsetZ.equals("0")) tag.putString("offset_z", offsetZ);
return tag;
}
@Override
public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters) {
ServerWorld world = parameters.getWorld();
Map<String, Double> variableMap = parameters.toVariableMap(new HashMap<>());
PocketTemplateV2 template = SchematicV2Handler.getInstance().getTemplates().get(templateID);
if (template == null) throw new RuntimeException("Pocket template of id " + templateID + " not found!");
Pocket pocket = DimensionalRegistry.getPocketDirectory(world.getRegistryKey()).newPocket();
LOGGER.info("Generating pocket from template " + template.getId() + " at location " + pocket.getOrigin());
pocket.offsetOrigin((int) offsetXEquation.apply(variableMap), (int) offsetYEquation.apply(variableMap), (int) offsetZEquation.apply(variableMap));
template.place(pocket);
return pocket;
}
@Override
public PocketGeneratorType<? extends PocketGenerator> getType() {
return PocketGeneratorType.SCHEMATIC;
}
@Override
public String getKey() {
return KEY;
}
}

View file

@ -0,0 +1,90 @@
package org.dimdev.dimdoors.pockets.generator;
import net.minecraft.nbt.CompoundTag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.math.Equation;
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.world.pocket.Pocket;
import java.util.HashMap;
import java.util.Map;
public class VoidGenerator extends PocketGenerator {
private static final Logger LOGGER = LogManager.getLogger();
public static final String KEY = "void";
private String width;
private Equation heightEquation;
private String height;
private Equation widthEquation;
private String length;
private Equation lengthEquation;
private String offsetX;
private Equation offsetXEquation;
private String offsetY;
private Equation offsetYEquation;
private String offsetZ;
private Equation offsetZEquation;
@Override
public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters) {
Pocket pocket = DimensionalRegistry.getPocketDirectory(parameters.getWorld().getRegistryKey()).newPocket();
Map<String, Double> variableMap = parameters.toVariableMap(new HashMap<>());
pocket.setSize((int) widthEquation.apply(variableMap), (int) heightEquation.apply(variableMap), (int) lengthEquation.apply(variableMap));
pocket.offsetOrigin((int) offsetXEquation.apply(variableMap), (int) offsetYEquation.apply(variableMap), (int) offsetZEquation.apply(variableMap));
return pocket;
}
@Override
public PocketGeneratorType<? extends PocketGenerator> getType() {
return PocketGeneratorType.VOID;
}
@Override
public String getKey() {
return KEY;
}
@Override
public PocketGenerator fromTag(CompoundTag tag) {
super.fromTag(tag);
try {
width = tag.getString("width");
widthEquation = Equation.parse(width);
height = tag.getString("height");
heightEquation = Equation.parse(height);
length = tag.getString("length");
lengthEquation = Equation.parse(length);
offsetX = tag.contains("offset_x") ? tag.getString("offset_x") : "0";
offsetXEquation = Equation.parse(offsetX);
offsetY = tag.contains("offset_y") ? tag.getString("offset_y") : "0";
offsetYEquation = Equation.parse(offsetY);
offsetZ = tag.contains("offset_z") ? tag.getString("offset_z") : "0";
offsetZEquation = Equation.parse(offsetZ);
} catch (EquationParseException e) {
LOGGER.error(e);
}
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
tag.putString("width", width);
tag.putString("height", height);
tag.putString("length", length);
if (!offsetX.equals("0")) tag.putString("offset_x", offsetX);
if (!offsetY.equals("0")) tag.putString("offset_y", offsetY);
if (!offsetZ.equals("0")) tag.putString("offset_z", offsetZ);
return tag;
}
}

View file

@ -0,0 +1,135 @@
package org.dimdev.dimdoors.pockets.modifier;
import java.util.HashMap;
import java.util.Map;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.enums.DoubleBlockHalf;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.block.DimensionalDoorBlock;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.entity.EntranceRiftBlockEntity;
import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes;
import org.dimdev.dimdoors.block.entity.RiftData;
import org.dimdev.dimdoors.pockets.SchematicV2Handler;
import org.dimdev.dimdoors.rift.targets.IdMarker;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.TagEquations;
import org.dimdev.dimdoors.util.math.Equation;
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
public class DimensionalDoorModifier implements Modifier {
private static final Logger LOGGER = LogManager.getLogger();
public static final String KEY = "door";
private Direction facing;
private String doorTypeString;
private DimensionalDoorBlock doorType;
private CompoundTag doorData;
private String doorDataReference;
private String x;
private String y;
private String z;
private Equation xEquation;
private Equation yEquation;
private Equation zEquation;
@Override
public Modifier fromTag(CompoundTag tag) {
String facingString = tag.getString("facing");
facing = Direction.byName(tag.getString("facing"));
if (facing == null || facing.getAxis().isVertical()) {
LOGGER.error("Could not interpret facing direction \"" + facingString + "\"");
facing = Direction.NORTH;
}
doorTypeString = tag.getString("door_type");
Block doorBlock = Registry.BLOCK.get(Identifier.tryParse(doorTypeString));
if (!(doorBlock instanceof DimensionalDoorBlock)) {
LOGGER.error("Could not interpret door type \"" + doorTypeString + "\"");
doorBlock = ModBlocks.IRON_DIMENSIONAL_DOOR;
}
doorType = (DimensionalDoorBlock) doorBlock;
if (tag.getType("rift_data") == NbtType.STRING) {
doorDataReference = tag.getString("rift_data");
doorData = (CompoundTag) SchematicV2Handler.getInstance().readNbtFromJson(doorDataReference);
}
else if (tag.getType("rift_data") == NbtType.COMPOUND) doorData = tag.getCompound("rift_data");
try {
x = tag.getString("x");
y = tag.getString("y");
z = tag.getString("z");
xEquation = Equation.parse(x);
yEquation = Equation.parse(y);
zEquation = Equation.parse(z);
} catch (EquationParseException e) {
LOGGER.error(e);
}
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
Modifier.super.toTag(tag);
tag.putString("facing", facing.asString());
tag.putString("door_type", doorTypeString);
if (doorDataReference != null) tag.putString("rift_data", doorDataReference);
else if (doorData != null) tag.put("rift_data", doorData);
tag.putString("x", x);
tag.putString("y", y);
tag.putString("z", z);
return tag;
}
@Override
public ModifierType<? extends Modifier> getType() {
return ModifierType.DIMENSIONAL_DOOR_MODIFIER_TYPE;
}
@Override
public String getKey() {
return KEY;
}
@Override
public void apply(PocketGenerationParameters parameters, RiftManager manager) {
Map<String, Double> variableMap = manager.getPocket().toVariableMap(new HashMap<>());
BlockPos pocketOrigin = manager.getPocket().getOrigin();
BlockPos pos = new BlockPos(xEquation.apply(variableMap) + pocketOrigin.getX(), yEquation.apply(variableMap) + pocketOrigin.getY(), zEquation.apply(variableMap) + pocketOrigin.getZ());
ServerWorld world = parameters.getWorld();
BlockState lower = doorType.getDefaultState().with(DimensionalDoorBlock.HALF, DoubleBlockHalf.LOWER).with(DimensionalDoorBlock.FACING, facing);
world.setBlockState(pos, lower);
world.setBlockState(pos.up(), doorType.getDefaultState().with(DimensionalDoorBlock.HALF, DoubleBlockHalf.UPPER).with(DimensionalDoorBlock.FACING, facing));
EntranceRiftBlockEntity rift = ModBlockEntityTypes.ENTRANCE_RIFT.instantiate();
if (doorData == null) {
rift.setDestination(new IdMarker(manager.nextId()));
} else {
CompoundTag solvedDoorData = TagEquations.solveCompoundTagEquations(doorData, variableMap);
rift.setData(RiftData.fromTag(solvedDoorData));
}
manager.add(rift);
world.setBlockEntity(pos, rift);
}
}

View file

@ -0,0 +1,73 @@
package org.dimdev.dimdoors.pockets.modifier;
import com.mojang.serialization.Lifecycle;
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.util.registry.SimpleRegistry;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.block.entity.RiftData;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.world.pocket.Pocket;
import java.util.Map;
import java.util.function.Supplier;
public interface Modifier {
Registry<ModifierType<? extends Modifier>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<ModifierType<? extends Modifier>>(RegistryKey.ofRegistry(new Identifier("dimdoors", "modifier_type")), Lifecycle.stable())).buildAndRegister();
static Modifier deserialize(CompoundTag tag) {
Identifier id = Identifier.tryParse(tag.getString("type")); // TODO: return some NONE Modifier if type cannot be found or deserialization fails.
return REGISTRY.get(id).fromTag(tag);
}
static CompoundTag serialize(Modifier modifier) {
return modifier.toTag(new CompoundTag());
}
Modifier fromTag(CompoundTag tag);
default CompoundTag toTag(CompoundTag tag) {
return this.getType().toTag(tag);
}
ModifierType<? extends Modifier> getType();
String getKey();
void apply(PocketGenerationParameters parameters, RiftManager manager);
interface ModifierType<T extends Modifier> {
ModifierType<ShellModifier> SHELL_MODIFIER_TYPE = register(new Identifier("dimdoors", ShellModifier.KEY), ShellModifier::new);
ModifierType<DimensionalDoorModifier> DIMENSIONAL_DOOR_MODIFIER_TYPE = register(new Identifier("dimdoors", DimensionalDoorModifier.KEY), DimensionalDoorModifier::new);
ModifierType<PocketEntranceModifier> PUBLIC_MODIFIER_TYPE = register(new Identifier("dimdoors", PocketEntranceModifier.KEY), PocketEntranceModifier::new);
ModifierType<RiftDataModifier> RIFT_DATA_MODIFIER_TYPE = register(new Identifier("dimdoors", RiftDataModifier.KEY), RiftDataModifier::new);
ModifierType<RelativeReferenceModifier> RELATIVE_REFERENCE_MODIFIER_TYPE = register(new Identifier("dimdoors", RelativeReferenceModifier.KEY), RelativeReferenceModifier::new);
Modifier fromTag(CompoundTag tag);
CompoundTag toTag(CompoundTag tag);
static void register() {
}
static <U extends Modifier> ModifierType<U> register(Identifier id, Supplier<U> constructor) {
return Registry.register(REGISTRY, id, new ModifierType<U>() {
@Override
public Modifier fromTag(CompoundTag tag) {
return constructor.get().fromTag(tag);
}
@Override
public CompoundTag toTag(CompoundTag tag) {
tag.putString("type", id.toString());
return tag;
}
});
}
}
}

View file

@ -0,0 +1,61 @@
package org.dimdev.dimdoors.pockets.modifier;
import java.util.List;
import java.util.Map;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.rift.registry.PocketEntrancePointer;
import org.dimdev.dimdoors.rift.targets.PocketEntranceMarker;
import org.dimdev.dimdoors.rift.targets.PocketExitMarker;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.world.pocket.Pocket;
public class PocketEntranceModifier implements Modifier {
public static final String KEY = "pocket_entrance";
private int id;
public PocketEntranceModifier(int id) {
this.id = id;
}
public PocketEntranceModifier() {
}
@Override
public Modifier fromTag(CompoundTag tag) {
return new PocketEntranceModifier(tag.getInt("id"));
}
@Override
public CompoundTag toTag(CompoundTag tag) {
Modifier.super.toTag(tag);
tag.putInt("id", id);
return tag;
}
@Override
public ModifierType<? extends Modifier> getType() {
return ModifierType.PUBLIC_MODIFIER_TYPE;
}
@Override
public String getKey() {
return KEY;
}
@Override
public void apply(PocketGenerationParameters parameters, RiftManager manager) {
manager.consume(id, rift -> {
rift.setDestination(PocketEntranceMarker.builder().ifDestination(new PocketExitMarker()).weight(1.0f).build());
return true;
});
}
}

View file

@ -0,0 +1,62 @@
package org.dimdev.dimdoors.pockets.modifier;
import java.util.Optional;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.rift.targets.LocalReference;
import org.dimdev.dimdoors.rift.targets.RiftReference;
import org.dimdev.dimdoors.util.Location;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
public class RelativeReferenceModifier implements Modifier {
public static final String KEY = "relative";
private int point_a, point_b;
@Override
public Modifier fromTag(CompoundTag tag) {
point_a = tag.getInt("point_a");
point_b = tag.getInt("point_b");
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
Modifier.super.toTag(tag);
tag.putInt("point_a", point_a);
tag.putInt("point_b", point_b);
return tag;
}
@Override
public ModifierType<? extends Modifier> getType() {
return ModifierType.RELATIVE_REFERENCE_MODIFIER_TYPE;
}
@Override
public String getKey() {
return KEY;
}
@Override
public void apply(PocketGenerationParameters parameters, RiftManager manager) {
Optional<Location> riftA = manager.get(point_a).map(rift -> new Location((ServerWorld) rift.getWorld(), rift.getPos()));
Optional<Location> riftB = manager.get(point_b).map(rift -> new Location((ServerWorld) rift.getWorld(), rift.getPos()));
if(riftA.isPresent() && riftB.isPresent()) {
RiftReference link1 = LocalReference.tryMakeRelative(riftA.get(), riftB.get());
RiftReference link2 = LocalReference.tryMakeRelative(riftB.get(), riftA.get());
manager.consume(point_a, rift -> addLink(rift, link1));
manager.consume(point_b, rift -> addLink(rift, link2));
}
}
private boolean addLink(RiftBlockEntity rift, RiftReference link) {
rift.setDestination(link);
return true;
}
}

View file

@ -0,0 +1,96 @@
package org.dimdev.dimdoors.pockets.modifier;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import net.minecraft.nbt.CompoundTag;
import net.fabricmc.fabric.api.util.NbtType;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.block.entity.RiftData;
import org.dimdev.dimdoors.pockets.SchematicV2Handler;
import org.dimdev.dimdoors.rift.targets.VirtualTarget;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.TagEquations;
public class RiftDataModifier implements Modifier {
public static final String KEY = "rift_data";
private CompoundTag doorData;
private String doorDataReference;
private List<Integer> ids;
@Override
public Modifier fromTag(CompoundTag tag) {
if (tag.getType("rift_data") == NbtType.STRING) {
doorDataReference = tag.getString("rift_data");
doorData = (CompoundTag) SchematicV2Handler.getInstance().readNbtFromJson(doorDataReference);
}
else if (tag.getType("rift_data") == NbtType.COMPOUND) doorData = tag.getCompound("rift_data");
ids = stream(tag.getByteArray("ids")).boxed().collect(Collectors.toList());
return this;
}
public static IntStream stream(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.wrap(bytes);
return IntStream.generate(buffer::get).limit(buffer.remaining());
}
private static byte[] toByteArray(int[] ints) {
byte[] bytes = new byte[ints.length];
for (int i = 0; i < ints.length; i++) {
bytes[i] = (byte) ints[i];
}
return bytes;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
Modifier.super.toTag(tag);
if (doorDataReference != null) tag.putString("rift_data", doorDataReference);
else if (doorData != null) tag.put("rift_data", doorData);
tag.putByteArray("ids", toByteArray(ids.stream().mapToInt(Integer::intValue).toArray()));
return tag;
}
@Override
public ModifierType<? extends Modifier> getType() {
return ModifierType.RIFT_DATA_MODIFIER_TYPE;
}
@Override
public String getKey() {
return KEY;
}
@Override
public void apply(PocketGenerationParameters parameters, RiftManager manager) {
Map<String, Double> variableMap = manager.getPocket().toVariableMap(new HashMap<>());
Consumer<RiftBlockEntity> riftBlockEntityConsumer;
if (doorData == null) {
riftBlockEntityConsumer = rift -> rift.setDestination(VirtualTarget.NoneTarget.INSTANCE);
} else {
CompoundTag solvedDoorData = TagEquations.solveCompoundTagEquations(doorData, variableMap);
riftBlockEntityConsumer = rift -> rift.setData(RiftData.fromTag(solvedDoorData));
}
manager.foreachConsume((id, rift) -> {
if(ids.contains(id)) {
riftBlockEntityConsumer.accept(rift);
return true;
} else {
return false;
}
});
}
}

View file

@ -0,0 +1,83 @@
package org.dimdev.dimdoors.pockets.modifier;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.rift.targets.IdMarker;
import org.dimdev.dimdoors.world.pocket.Pocket;
public class RiftManager {
private final Map<Integer, RiftBlockEntity> map;
private final Pocket pocket;
private int maxId;
public RiftManager(Pocket pocket) {
this.pocket = pocket;
map = pocket.getBlockEntities().values().stream()
.filter(RiftBlockEntity.class::isInstance).map(RiftBlockEntity.class::cast)
.filter(a -> a.getData().getDestination() instanceof IdMarker)
.filter(a -> ((IdMarker) a.getData().getDestination()).getId() >= 0)
.collect(Collectors.toMap(rift -> ((IdMarker) rift.getData().getDestination()).getId(), rift -> rift));
maxId = map.keySet().stream()
.mapToInt(a -> a)
.max()
.orElse(-1);
}
//TODO add javadocs
public boolean add(RiftBlockEntity rift) {
if(rift.getData().getDestination() instanceof IdMarker) {
int id = ((IdMarker) rift.getData().getDestination()).getId();
if(id < 0) return false;
map.put(id, rift);
maxId = Math.max(id, maxId);
return true;
}
return false;
}
public boolean consume(int id, Predicate<RiftBlockEntity> consumer) {
if (map.containsKey(id) && consumer.test(map.get(id))) {
map.remove(id);
return true;
}
return false;
}
public Pocket getPocket() {
return pocket;
}
public int nextId() {
return maxId + 1;
}
public boolean available(int id) { // TODO: remove? method is likely redundant
return !map.containsKey(id);
}
public void foreachConsume(BiPredicate<Integer, RiftBlockEntity> consumer) {
for(int id : new HashSet<>(map.keySet())) {
if(consumer.test(id, map.get(id))) {
map.remove(id);
}
}
}
public Optional<RiftBlockEntity> get(int id) {
return Optional.ofNullable(map.get(id));
}
}

View file

@ -0,0 +1,139 @@
package org.dimdev.dimdoors.pockets.modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.*;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.fabricmc.fabric.api.util.NbtType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.math.Equation;
import org.dimdev.dimdoors.util.schematic.v2.SchematicBlockPalette;
import org.dimdev.dimdoors.world.pocket.Pocket;
public class ShellModifier implements Modifier{
private static final Logger LOGGER = LogManager.getLogger();
public static final String KEY = "shell";
private final List<Layer> layers = new ArrayList<>();
@Override
public CompoundTag toTag(CompoundTag tag) {
Modifier.super.toTag(tag);
ListTag layersTag = new ListTag();
for (Layer layer : layers) {
layersTag.add(layer.toTag());
}
tag.put("layers", layersTag);
return tag;
}
@Override
public Modifier fromTag(CompoundTag tag) {
for (Tag layerTag : tag.getList("layers", NbtType.COMPOUND)) {
CompoundTag compoundTag = (CompoundTag) layerTag;
try {
Layer layer = Layer.fromTag(compoundTag);
layers.add(layer);
} catch (CommandSyntaxException e) {
LOGGER.error("could not parse Layer: " + compoundTag.toString(), e);
}
}
return this;
}
@Override
public ModifierType<? extends Modifier> getType() {
return ModifierType.SHELL_MODIFIER_TYPE;
}
@Override
public String getKey() {
return KEY;
}
@Override
public void apply(PocketGenerationParameters parameters, RiftManager manager) {
layers.forEach(layer -> drawLayer(layer, manager.getPocket(), parameters.getWorld()));
}
private void drawLayer(Layer layer, Pocket pocket, ServerWorld world) {
int thickness = layer.getThickness(pocket.toVariableMap(new HashMap<>()));
final BlockState blockState = layer.getBlockState();
BlockBox pocketBox = pocket.getBox();
// x-planes
BlockPos.stream(BlockBox.create(pocketBox.maxX + 1, pocketBox.minY - thickness, pocketBox.minZ - thickness, pocketBox.maxX + thickness, pocketBox.maxY + thickness, pocketBox.maxZ + thickness))
.forEach(blockPos -> world.setBlockState(blockPos, blockState));
BlockPos.stream(BlockBox.create(pocketBox.minX - 1, pocketBox.minY - thickness, pocketBox.minZ - thickness, pocketBox.minX - thickness, pocketBox.maxY + thickness, pocketBox.maxZ + thickness))
.forEach(blockPos -> world.setBlockState(blockPos, blockState));
// y-planes
BlockPos.stream(BlockBox.create(pocketBox.minX, pocketBox.maxY + 1, pocketBox.minZ - thickness, pocketBox.maxX, pocketBox.maxY + thickness, pocketBox.maxZ + thickness))
.forEach(blockPos -> world.setBlockState(blockPos, blockState));
BlockPos.stream(BlockBox.create(pocketBox.minX, pocketBox.minY - 1, pocketBox.minZ - thickness, pocketBox.maxX, pocketBox.minY - thickness, pocketBox.maxZ + thickness))
.forEach(blockPos -> world.setBlockState(blockPos, blockState));
// z-planes
BlockPos.stream(BlockBox.create(pocketBox.minX, pocketBox.minY, pocketBox.minZ - 1, pocketBox.maxX, pocketBox.maxY, pocketBox.minZ - thickness))
.forEach(blockPos -> world.setBlockState(blockPos, blockState));
BlockPos.stream(BlockBox.create(pocketBox.minX, pocketBox.minY, pocketBox.maxZ + 1, pocketBox.maxX, pocketBox.maxY, pocketBox.maxZ + thickness))
.forEach(blockPos -> world.setBlockState(blockPos, blockState));
pocket.expand(thickness);
}
public static class Layer {
private final String blockStateString;
private final String thickness;
private Equation thicknessEquation;
private final BlockState blockState;
public Layer(String blockStateString, String thickness) {
this.blockStateString = blockStateString;
this.thickness = thickness;
try {
this.thicknessEquation = Equation.parse(thickness);
} catch (Equation.EquationParseException e) {
LOGGER.error("Could not parse layer thickness equation");
this.thicknessEquation = variableMap -> 1d;
}
this.blockState = SchematicBlockPalette.Entry.to(blockStateString).getOrThrow(false, LOGGER::error);
}
public BlockState getBlockState() {
return blockState;
}
public int getThickness(Map<String, Double> variableMap) {
return (int) thicknessEquation.apply(variableMap);
}
public CompoundTag toTag() {
CompoundTag tag = new CompoundTag();
tag.putString("block_state", blockStateString);
tag.putString("thickness", thickness);
return tag;
}
public static Layer fromTag(CompoundTag tag) throws CommandSyntaxException {
return new Layer(tag.getString("block_state"), tag.getString("thickness"));
}
}
}

View file

@ -0,0 +1,33 @@
package org.dimdev.dimdoors.pockets.virtual;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import org.dimdev.dimdoors.pockets.virtual.reference.PocketGeneratorReference;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.Weighted;
import org.dimdev.dimdoors.world.pocket.Pocket;
public interface VirtualPocket extends Weighted<PocketGenerationParameters> {
static VirtualPocket deserialize(Tag tag) {
if (tag.getType() == 9) { // ListTag
return VirtualPocketList.deserialize((ListTag) tag);
}
return VirtualSingularPocket.deserialize((CompoundTag) tag); // should be CompoundTag
}
static Tag serialize(VirtualPocket virtualPocket) {
if (virtualPocket instanceof VirtualPocketList) {
return VirtualPocketList.serialize((VirtualPocketList) virtualPocket);
}
return VirtualSingularPocket.serialize((VirtualSingularPocket) virtualPocket);
}
Pocket prepareAndPlacePocket(PocketGenerationParameters parameters);
PocketGeneratorReference getNextPocketGeneratorReference(PocketGenerationParameters parameters);
PocketGeneratorReference peekNextPocketGeneratorReference(PocketGenerationParameters parameters);
}

View file

@ -0,0 +1,56 @@
package org.dimdev.dimdoors.pockets.virtual;
import net.minecraft.nbt.ListTag;
import org.dimdev.dimdoors.pockets.virtual.reference.PocketGeneratorReference;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.WeightedList;
import org.dimdev.dimdoors.world.pocket.Pocket;
// TODO: add weight tha
public class VirtualPocketList extends WeightedList<VirtualPocket, PocketGenerationParameters> implements VirtualPocket {
public static VirtualPocketList deserialize(ListTag tag) {
return new VirtualPocketList().fromTag(tag);
}
public static ListTag serialize(VirtualPocketList virtualPocketList) {
return virtualPocketList.toTag(new ListTag());
}
public VirtualPocketList() {
super();
}
public VirtualPocketList fromTag(ListTag tag) { // Keep in mind, this would add onto the list instead of overwriting it if called multiple times.
for (net.minecraft.nbt.Tag value : tag) {
this.add(VirtualPocket.deserialize(value));
}
return this;
}
public ListTag toTag(ListTag tag) {
for(VirtualPocket virtualPocket : this) {
tag.add(VirtualPocket.serialize(virtualPocket));
}
return tag;
}
@Override
public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters) {
return getNextPocketGeneratorReference(parameters).prepareAndPlacePocket(parameters);
}
public PocketGeneratorReference getNextPocketGeneratorReference(PocketGenerationParameters parameters) {
return getNextRandomWeighted(parameters).getNextPocketGeneratorReference(parameters);
}
public PocketGeneratorReference peekNextPocketGeneratorReference(PocketGenerationParameters parameters) {
return peekNextRandomWeighted(parameters).peekNextPocketGeneratorReference(parameters);
}
@Override
public double getWeight(PocketGenerationParameters parameters) {
return peekNextRandomWeighted(parameters).getWeight(parameters);
}
}

View file

@ -0,0 +1,84 @@
package org.dimdev.dimdoors.pockets.virtual;
import com.mojang.serialization.*;
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.util.registry.SimpleRegistry;
import org.dimdev.dimdoors.pockets.virtual.reference.IdReference;
import org.dimdev.dimdoors.pockets.virtual.reference.TagReference;
import org.dimdev.dimdoors.pockets.virtual.selection.ConditionalSelector;
import java.util.function.Supplier;
// TODO: do something about getting correct Pocket sizes
public abstract class VirtualSingularPocket implements VirtualPocket {
public static final Registry<VirtualSingularPocketType<? extends VirtualSingularPocket>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<VirtualSingularPocketType<? extends VirtualSingularPocket>>(RegistryKey.ofRegistry(new Identifier("dimdoors", "virtual_pocket_type")), Lifecycle.stable())).buildAndRegister();
/*
public static final Codec<VirtualPocket> CODEC = new Codec<VirtualPocket>() {
@Override
public <T> DataResult<Pair<VirtualPocket, T>> decode(DynamicOps<T> dynamicOps, T input) {
Identifier id = new Identifier("dimdoors", Codec.STRING.decode(dynamicOps, dynamicOps.get(input, "virtual_type").getOrThrow(false, System.err::println)).getOrThrow(false, System.err::println).getFirst());
return REGISTRY.get(id).getCodec().decode(dynamicOps, input).map(pair -> pair.mapFirst(virtualPocket -> (VirtualPocket) virtualPocket));
}
@Override
public <T> DataResult<T> encode(VirtualPocket input, DynamicOps<T> ops, T prefix) {
return null; // TODO: write encode function
}
};
*/
public static VirtualSingularPocket deserialize(CompoundTag tag) {
Identifier id = Identifier.tryParse(tag.getString("type")); // TODO: return some NONE VirtualPocket if type cannot be found or deserialization fails.
return REGISTRY.get(id).fromTag(tag);
}
public static CompoundTag serialize(VirtualSingularPocket virtualSingularPocket) {
return virtualSingularPocket.toTag(new CompoundTag());
}
public abstract VirtualSingularPocket fromTag(CompoundTag tag);
public CompoundTag toTag(CompoundTag tag) {
return this.getType().toTag(tag);
}
public abstract VirtualSingularPocketType<? extends VirtualSingularPocket> getType();
public abstract String getKey();
public interface VirtualSingularPocketType<T extends VirtualSingularPocket> {
VirtualSingularPocketType<IdReference> ID_REFERENCE = register(new Identifier("dimdoors", IdReference.KEY), IdReference::new);
VirtualSingularPocketType<TagReference> TAG_REFERENCE = register(new Identifier("dimdoors", TagReference.KEY), TagReference::new);
VirtualSingularPocketType<ConditionalSelector> DEPTH_DEPENDENT_SELECTOR = register(new Identifier("dimdoors", ConditionalSelector.KEY), ConditionalSelector::new);
VirtualSingularPocket fromTag(CompoundTag tag);
CompoundTag toTag(CompoundTag tag);
static void register() {
}
static <U extends VirtualSingularPocket> VirtualSingularPocketType<U> register(Identifier id, Supplier<U> constructor) {
return Registry.register(REGISTRY, id, new VirtualSingularPocketType<U>() {
@Override
public VirtualSingularPocket fromTag(CompoundTag tag) {
return constructor.get().fromTag(tag);
}
@Override
public CompoundTag toTag(CompoundTag tag) {
tag.putString("type", id.toString());
return tag;
}
});
}
}
}

View file

@ -0,0 +1,52 @@
package org.dimdev.dimdoors.pockets.virtual.reference;
import net.minecraft.nbt.CompoundTag;
import org.dimdev.dimdoors.pockets.SchematicV2Handler;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
import org.dimdev.dimdoors.pockets.virtual.VirtualSingularPocket;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
public class IdReference extends PocketGeneratorReference {
public static final String KEY = "id";
private String id;
@Override
public VirtualSingularPocket fromTag(CompoundTag tag) {
super.fromTag(tag);
id = tag.getString("id");
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
tag.putString("id", id);
return tag;
}
@Override
public PocketGenerator peekReferencedPocketGenerator(PocketGenerationParameters parameters) {
return getReferencedPocketGenerator(parameters);
}
@Override
public PocketGenerator getReferencedPocketGenerator(PocketGenerationParameters parameters) {
return SchematicV2Handler.getInstance().getGenerator(id);
}
@Override
public VirtualSingularPocketType<? extends VirtualSingularPocket> getType() {
return VirtualSingularPocketType.ID_REFERENCE;
}
@Override
public String getKey() {
return KEY;
}
}

View file

@ -0,0 +1,120 @@
package org.dimdev.dimdoors.pockets.virtual.reference;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
import org.dimdev.dimdoors.pockets.modifier.Modifier;
import org.dimdev.dimdoors.pockets.modifier.RiftManager;
import org.dimdev.dimdoors.pockets.virtual.VirtualSingularPocket;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.math.Equation;
import org.dimdev.dimdoors.util.math.Equation.EquationParseException;
import org.dimdev.dimdoors.world.pocket.Pocket;
import java.util.List;
public abstract class PocketGeneratorReference extends VirtualSingularPocket {
private static final Logger LOGGER = LogManager.getLogger();
private static final String defaultWeightEquation = "5"; // TODO: make config
private static final int fallbackWeight = 5; // TODO: make config
private String weight;
private Equation weightEquation;
private Boolean setupLoot;
private final List<Modifier> modifierList = Lists.newArrayList();
private void parseWeight() {
try {
this.weightEquation = Equation.parse(weight);
} catch (EquationParseException e) {
LOGGER.error("Could not parse weight equation \"" + weight + "\", defaulting to default weight equation \"" + defaultWeightEquation + "\"", e);
try {
this.weightEquation = Equation.parse(defaultWeightEquation);
} catch (EquationParseException equationParseException) {
LOGGER.error("Could not parse default weight equation \"" + defaultWeightEquation + "\", defaulting to fallback weight \"" + fallbackWeight + "\"", equationParseException);
this.weightEquation = stringDoubleMap -> fallbackWeight;
}
}
}
@Override
public VirtualSingularPocket fromTag(CompoundTag tag) {
if (tag.contains("weight")) { // override referenced pockets weight
this.weight = tag.getString("weight");
parseWeight();
}
if (tag.contains("setup_loot")) setupLoot = tag.getBoolean("setup_loot");
if (tag.contains("modifiers")) {
ListTag modifiersTag = tag.getList("modifiers", 10);
for (int i = 0; i < modifiersTag.size(); i++) {
modifierList.add(Modifier.deserialize(modifiersTag.getCompound(i)));
}
}
return null;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
if (weight != null) tag.putString("weight", weight);
if (setupLoot != null) tag.putBoolean("setup_loot", setupLoot);
ListTag modifiersTag = new ListTag();
for (Modifier modifier : modifierList) {
modifiersTag.add(modifier.toTag(new CompoundTag()));
}
if (modifiersTag.size() > 0) tag.put("modifiers", modifiersTag);
return tag;
}
@Override
public double getWeight(PocketGenerationParameters parameters) {
return weightEquation != null ? this.weightEquation.apply(parameters.toVariableMap(Maps.newHashMap())) : peekReferencedPocketGenerator(parameters).getWeight(parameters);
}
public void applyModifiers(PocketGenerationParameters parameters, RiftManager manager) {
for (Modifier modifier : modifierList) {
modifier.apply(parameters, manager);
}
}
@Override
public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters) {
PocketGenerator generator = getReferencedPocketGenerator(parameters);
Pocket pocket = generator.prepareAndPlacePocket(parameters);
RiftManager manager = new RiftManager(pocket);
generator.applyModifiers(parameters, manager);
this.applyModifiers(parameters, manager);
generator.setup(pocket, parameters, setupLoot != null ? setupLoot : true);
return pocket;
}
@Override
public PocketGeneratorReference peekNextPocketGeneratorReference(PocketGenerationParameters parameters) {
return this;
}
@Override
public PocketGeneratorReference getNextPocketGeneratorReference(PocketGenerationParameters parameters) {
return this;
}
public abstract PocketGenerator peekReferencedPocketGenerator(PocketGenerationParameters parameters);
public abstract PocketGenerator getReferencedPocketGenerator(PocketGenerationParameters parameters);
}

View file

@ -0,0 +1,97 @@
package org.dimdev.dimdoors.pockets.virtual.reference;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import org.dimdev.dimdoors.pockets.SchematicV2Handler;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
import org.dimdev.dimdoors.pockets.virtual.VirtualSingularPocket;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.WeightedList;
import java.util.ArrayList;
import java.util.List;
public class TagReference extends PocketGeneratorReference{
public static final String KEY = "tag";
private final List<String> required = new ArrayList<>();
private final List<String> blackList = new ArrayList<>();
private Boolean exact;
private WeightedList<PocketGenerator, PocketGenerationParameters> pockets;
@Override
public VirtualSingularPocket fromTag(CompoundTag tag) {
super.fromTag(tag);
if (tag.contains("required")) {
ListTag listTag = tag.getList("required", NbtType.STRING);
for (int i = 0; i < listTag.size(); i++) {
required.add(listTag.getString(i));
}
}
if (tag.contains("blackList")) {
ListTag listTag = tag.getList("blackList", NbtType.STRING);
for (int i = 0; i < listTag.size(); i++) {
blackList.add(listTag.getString(i));
}
}
if (tag.contains("exact")) exact = tag.getBoolean("exact");
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
if (required.size() > 0) {
ListTag listTag = new ListTag();
for (String tagString : required) {
listTag.add(StringTag.of(tagString));
}
tag.put("required", listTag);
}
if (blackList.size() > 0) {
ListTag listTag = new ListTag();
for (String tagString : blackList) {
listTag.add(StringTag.of(tagString));
}
tag.put("blackList", listTag);
}
if (exact != null) {
tag.putBoolean("exact", exact);
}
return tag;
}
@Override
public VirtualSingularPocketType<? extends VirtualSingularPocket> getType() {
return VirtualSingularPocketType.TAG_REFERENCE;
}
@Override
public String getKey() {
return KEY;
}
// TODO: this will break if pockets change in between (which they could if we add a tool for creating pocket json config stuff ingame)
@Override
public PocketGenerator peekReferencedPocketGenerator(PocketGenerationParameters parameters) {
if (pockets == null) pockets = SchematicV2Handler.getInstance().getPocketsMatchingTags(required, blackList, exact);
return pockets.peekNextRandomWeighted(parameters);
}
@Override
public PocketGenerator getReferencedPocketGenerator(PocketGenerationParameters parameters) {
if (pockets == null) pockets = SchematicV2Handler.getInstance().getPocketsMatchingTags(required, blackList, exact);
return pockets.getNextRandomWeighted(parameters);
}
}

View file

@ -0,0 +1,120 @@
package org.dimdev.dimdoors.pockets.virtual.selection;
import com.google.common.collect.Maps;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.pockets.virtual.VirtualPocket;
import org.dimdev.dimdoors.pockets.virtual.VirtualSingularPocket;
import org.dimdev.dimdoors.pockets.virtual.reference.PocketGeneratorReference;
import org.dimdev.dimdoors.util.PocketGenerationParameters;
import org.dimdev.dimdoors.util.math.Equation;
import org.dimdev.dimdoors.world.pocket.Pocket;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class ConditionalSelector extends VirtualSingularPocket {
private static final Logger LOGGER = LogManager.getLogger();
public static final String KEY = "conditional";
/*
private static final Codec<Pair<String, VirtualPocket>> PAIR_CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.STRING.fieldOf("regex").forGetter(Pair::getLeft),
VirtualPocket.CODEC.fieldOf("pocket").forGetter(Pair::getRight)
).apply(instance, Pair::new));
public static final Codec<DepthDependentSelector> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.STRING.fieldOf("id").forGetter(DepthDependentSelector::getName),
PAIR_CODEC.listOf().fieldOf("pockets").forGetter(DepthDependentSelector::getPocketList)
).apply(instance, DepthDependentSelector::new));
*/
private LinkedHashMap<String, VirtualPocket> pocketMap = Maps.newLinkedHashMap();
private LinkedHashMap<String, Equation> equationMap = Maps.newLinkedHashMap();
public ConditionalSelector() {
}
public ConditionalSelector(LinkedHashMap<String, VirtualPocket> pocketMap) {
this.pocketMap = pocketMap;
}
public LinkedHashMap<String, VirtualPocket> getPocketMap() {
return pocketMap;
}
@Override
public VirtualSingularPocket fromTag(CompoundTag tag) {
ListTag conditionalPockets = tag.getList("pockets", 10);
for (int i = 0; i < conditionalPockets.size(); i++) {
CompoundTag pocket = conditionalPockets.getCompound(i);
String condition = pocket.getString("condition");
if (pocketMap.containsKey(condition)) continue;
try {
equationMap.put(condition, Equation.parse(condition));
pocketMap.put(condition, VirtualPocket.deserialize(pocket.get("pocket")));
} catch (Equation.EquationParseException e) {
LOGGER.error("Could not parse pocket condition equation!", e);
}
}
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
ListTag conditionalPockets = new ListTag();
pocketMap.forEach((condition, pocket) -> {
CompoundTag compound = new CompoundTag();
compound.putString("condition", condition);
compound.put("pocket", VirtualPocket.serialize(pocket));
conditionalPockets.add(compound);
});
tag.put("pockets", conditionalPockets);
return tag;
}
@Override
public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters) {
return getNextPocket(parameters).prepareAndPlacePocket(parameters);
}
@Override
public PocketGeneratorReference getNextPocketGeneratorReference(PocketGenerationParameters parameters) {
return getNextPocket(parameters).getNextPocketGeneratorReference(parameters);
}
@Override
public PocketGeneratorReference peekNextPocketGeneratorReference(PocketGenerationParameters parameters) {
return getNextPocket(parameters).peekNextPocketGeneratorReference(parameters);
}
@Override
public VirtualSingularPocketType<? extends VirtualSingularPocket> getType() {
return VirtualSingularPocketType.DEPTH_DEPENDENT_SELECTOR;
}
@Override
public String getKey() {
return KEY;
}
@Override
public double getWeight(PocketGenerationParameters parameters) {
return getNextPocket(parameters).getWeight(parameters);
}
private VirtualPocket getNextPocket(PocketGenerationParameters parameters) {
for (Map.Entry<String, VirtualPocket> entry : pocketMap.entrySet()) {
if (equationMap.get(entry.getKey()).asBoolean(parameters.toVariableMap(new HashMap<>()))) {
return entry.getValue();
}
}
return pocketMap.values().stream().findFirst().get(); // TODO: orElse() with some NONE VirtualPocket
}
}

View file

@ -13,9 +13,10 @@ import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.util.GraphUtils;
import org.dimdev.dimdoors.util.Location;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.world.pocket.Pocket;
import org.dimdev.dimdoors.world.pocket.PocketDirectory;
import org.dimdev.dimdoors.world.pocket.PrivatePocketData;
import org.dimdev.dimdoors.world.pocket.PrivateRegistry;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
@ -308,7 +309,7 @@ public class RiftRegistry {
if (entrance != null) return entrance.location;
// If there was no last used private entrance, get the first player's private pocket entrance
return this.getPocketEntrance(PrivatePocketData.instance().getPrivatePocket(playerUUID));
return this.getPocketEntrance(DimensionalRegistry.getPrivateRegistry().getPrivatePocket(playerUUID));
}
private void setPlayerRiftPointer(UUID playerUUID, Location rift, Map<UUID, PlayerRiftPointer> map) {

View file

@ -26,7 +26,7 @@ public class GlobalReference extends RiftReference {
public static CompoundTag toTag(GlobalReference virtualTarget) {
CompoundTag tag = new CompoundTag();
tag.put("target", Location.toTag(virtualTarget.location));
tag.put("target", Location.toTag(virtualTarget.getReferencedLocation()));
return tag;
}

View file

@ -0,0 +1,41 @@
package org.dimdev.dimdoors.rift.targets;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.text.Text;
import org.dimdev.dimdoors.util.EntityUtils;
import org.dimdev.dimdoors.util.Location;
public class IdMarker extends VirtualTarget implements EntityTarget {
private final int id;
public IdMarker(int id) {
this.id = id;
}
@Override
public VirtualTargetType<? extends VirtualTarget> getType() {
return VirtualTargetType.ID_MARKER;
}
public static CompoundTag toTag(IdMarker target) {
CompoundTag tag = new CompoundTag();
tag.putInt("id", target.id);
return tag;
}
public static IdMarker fromTag(CompoundTag nbt) {
return new IdMarker(nbt.getInt("id"));
}
public int getId() {
return id;
}
@Override
public boolean receiveEntity(Entity entity, float yawOffset) {
EntityUtils.chat(entity, Text.of("This rift is configured for pocket dungeons. Its id is " + id));
return false;
}
}

View file

@ -79,7 +79,7 @@ public class PocketEntranceMarker extends VirtualTarget implements EntityTarget
private VirtualTarget ifDestination = NoneTarget.INSTANCE;
private VirtualTarget otherwiseDestination = NoneTarget.INSTANCE;
PocketEntranceMarkerBuilder() {
private PocketEntranceMarkerBuilder() {
}
public PocketEntranceMarker.PocketEntranceMarkerBuilder weight(float weight) {

View file

@ -10,7 +10,7 @@ import org.dimdev.dimdoors.util.RGBA;
import org.dimdev.dimdoors.world.ModDimensions;
import org.dimdev.dimdoors.world.pocket.Pocket;
import org.dimdev.dimdoors.world.pocket.PocketDirectory;
import org.dimdev.dimdoors.world.pocket.PrivatePocketData;
import org.dimdev.dimdoors.world.pocket.PrivateRegistry;
import net.minecraft.entity.Entity;
import net.minecraft.text.TranslatableText;
@ -30,8 +30,8 @@ public class PrivatePocketExitTarget extends VirtualTarget implements EntityTarg
UUID uuid = EntityUtils.getOwner(entity).getUuid();
if (uuid != null) {
destLoc = DimensionalRegistry.getRiftRegistry().getPrivatePocketExit(uuid);
Pocket pocket = PrivatePocketData.instance().getPrivatePocket(uuid);
if (ModDimensions.isPocketDimension(this.location.getWorld()) && pocket != null && DimensionalRegistry.getPocketDirectory(pocket.world).getPocketAt(this.location.pos).equals(pocket)) {
Pocket pocket = DimensionalRegistry.getPrivateRegistry().getPrivatePocket(uuid);
if (ModDimensions.isPersonalPocketDimension(this.location.getWorld()) && pocket != null && DimensionalRegistry.getPocketDirectory(pocket.world).getPocketAt(this.location.pos).equals(pocket)) {
DimensionalRegistry.getRiftRegistry().setLastPrivatePocketEntrance(uuid, this.location); // Remember which exit was used for next time the pocket is entered
}
if (destLoc == null || !(destLoc.getBlockEntity() instanceof RiftBlockEntity)) {

View file

@ -10,7 +10,7 @@ import org.dimdev.dimdoors.util.EntityUtils;
import org.dimdev.dimdoors.util.Location;
import org.dimdev.dimdoors.util.RGBA;
import org.dimdev.dimdoors.world.pocket.Pocket;
import org.dimdev.dimdoors.world.pocket.PrivatePocketData;
import org.dimdev.dimdoors.world.pocket.PrivateRegistry;
import org.dimdev.dimdoors.world.pocket.VirtualLocation;
import net.minecraft.block.entity.BlockEntity;
@ -33,12 +33,12 @@ public class PrivatePocketTarget extends VirtualTarget implements EntityTarget {
UUID uuid = EntityUtils.getOwner(entity).getUuid();
VirtualLocation virtualLocation = VirtualLocation.fromLocation(this.location);
if (uuid != null) {
Pocket pocket = PrivatePocketData.instance().getPrivatePocket(uuid);
Pocket pocket = DimensionalRegistry.getPrivateRegistry().getPrivatePocket(uuid);
if (pocket == null) { // generate the private pocket and get its entrances
// set to where the pocket was first created
pocket = PocketGenerator.generatePrivatePocketV2(new VirtualLocation(virtualLocation.getWorld(), virtualLocation.getX(), virtualLocation.getZ(), -1));
PrivatePocketData.instance().setPrivatePocketID(uuid, pocket);
DimensionalRegistry.getPrivateRegistry().setPrivatePocketID(uuid, pocket);
BlockEntity be = DimensionalRegistry.getRiftRegistry().getPocketEntrance(pocket).getBlockEntity();
this.processEntity(pocket, be, entity, uuid, yawOffset);
} else {
@ -49,7 +49,7 @@ public class PrivatePocketTarget extends VirtualTarget implements EntityTarget {
LOGGER.info("All entrances are gone, creating a new private pocket!");
pocket = PocketGenerator.generatePrivatePocketV2(new VirtualLocation(virtualLocation.getWorld(), virtualLocation.getX(), virtualLocation.getZ(), -1));
PrivatePocketData.instance().setPrivatePocketID(uuid, pocket);
DimensionalRegistry.getPrivateRegistry().setPrivatePocketID(uuid, pocket);
destLoc = DimensionalRegistry.getRiftRegistry().getPocketEntrance(pocket);
}
@ -66,8 +66,11 @@ public class PrivatePocketTarget extends VirtualTarget implements EntityTarget {
Item item = ((ItemEntity) entity).getStack().getItem();
if (item instanceof DyeItem) {
pocket.addDye(EntityUtils.getOwner(entity), ((DyeItem) item).getColor());
entity.remove();
if(pocket.addDye(EntityUtils.getOwner(entity), ((DyeItem) item).getColor())) {
entity.remove();
} else {
((EntityTarget) blockEntity).receiveEntity(entity, relativeYaw);
}
} else {
((EntityTarget) blockEntity).receiveEntity(entity, relativeYaw);
}

View file

@ -34,7 +34,7 @@ public class PublicPocketTarget extends RestoringTarget {
public Location makeLinkTarget() {
VirtualLocation riftVirtualLocation = VirtualLocation.fromLocation(this.location);
VirtualLocation newVirtualLocation;
int depth = Math.max(riftVirtualLocation.getDepth(), 1);
int depth = riftVirtualLocation.getDepth()+1;
newVirtualLocation = new VirtualLocation(riftVirtualLocation.getWorld(), riftVirtualLocation.getX(), riftVirtualLocation.getZ(), depth);
Pocket pocket = PocketGenerator.generatePublicPocketV2(newVirtualLocation, new GlobalReference(this.location), null);

View file

@ -171,7 +171,7 @@ public class RandomTarget extends VirtualTarget { // TODO: Split into DungeonTar
// Make a new dungeon pocket
RiftBlockEntity thisRift = (RiftBlockEntity) this.location.getBlockEntity();
LinkProperties newLink = thisRift.getProperties() != null ? thisRift.getProperties().toBuilder().linksRemaining(0).build() : null;
Pocket pocket = PocketGenerator.generateDungeonPocket(virtualLocation, new GlobalReference(!this.noLinkBack ? this.location : null), newLink); // TODO make the generated dungeon of the same type, but in the overworld
Pocket pocket = PocketGenerator.generateDungeonPocketV2(virtualLocation, new GlobalReference(!this.noLinkBack ? this.location : null), newLink); // TODO make the generated dungeon of the same type, but in the overworld
// Link the rift if necessary and teleport the entity
if (!this.noLink) linkRifts(this.location, DimensionalRegistry.getRiftRegistry().getPocketEntrance(pocket));

View file

@ -11,14 +11,13 @@ public abstract class RestoringTarget extends VirtualTarget {
@Override
public Target receiveOther() {
if (this.getTarget() != null) {
this.getTarget().location = this.location;
return this.getTarget();
}
Location linkTarget = this.makeLinkTarget();
if (linkTarget != null) {
this.setTarget(RiftReference.tryMakeLocal(this.location, linkTarget));
this.getTarget().setLocation(this.location);
this.getTarget().setLocation(linkTarget);
this.getTarget().register();
return this.getTarget();

View file

@ -88,6 +88,7 @@ public abstract class VirtualTarget implements Target {
VirtualTargetType<PrivatePocketTarget> PRIVATE = register("dimdoors:private", a -> new PrivatePocketTarget(), a -> new CompoundTag(), PrivatePocketExitTarget.COLOR);
VirtualTargetType<PrivatePocketExitTarget> PRIVATE_POCKET_EXIT = register("dimdoors:private_pocket_exit", a -> new PrivatePocketExitTarget(), a -> new CompoundTag(), PrivatePocketExitTarget.COLOR);
VirtualTargetType<RelativeReference> RELATIVE = register("dimdoors:relative", RelativeReference::fromTag, RelativeReference::toTag, VirtualTarget.COLOR);
VirtualTargetType<IdMarker> ID_MARKER = register("dimdoors:id_marker", IdMarker::fromTag, IdMarker::toTag, VirtualTarget.COLOR);
VirtualTargetType<NoneTarget> NONE = register("dimdoors:none", tag -> NoneTarget.INSTANCE, i -> new CompoundTag(), COLOR);
T fromTag(CompoundTag tag);

View file

@ -0,0 +1,55 @@
package org.dimdev.dimdoors.util;
import net.minecraft.server.world.ServerWorld;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.ModConfig;
import org.dimdev.dimdoors.rift.registry.LinkProperties;
import org.dimdev.dimdoors.rift.targets.VirtualTarget;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.world.pocket.VirtualLocation;
import java.util.Map;
public class PocketGenerationParameters {
private final ServerWorld world;
private final String group;
private final VirtualLocation sourceVirtualLocation;
private final VirtualTarget linkTo;
private final LinkProperties linkProperties;
public PocketGenerationParameters(ServerWorld world, String group, VirtualLocation sourceVirtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) {
this.world = world;
this.group = group;
this.sourceVirtualLocation = sourceVirtualLocation;
this.linkTo = linkTo;
this.linkProperties = linkProperties;
}
public ServerWorld getWorld() {
return world;
}
public String getGroup() {
return group;
}
public VirtualLocation getSourceVirtualLocation() {
return sourceVirtualLocation;
}
public VirtualTarget getLinkTo() {
return linkTo;
}
public LinkProperties getLinkProperties() {
return linkProperties;
}
public Map<String, Double> toVariableMap(Map<String, Double> stringDoubleMap) {
stringDoubleMap.put("depth", (double) this.sourceVirtualLocation.getDepth());
stringDoubleMap.put("public_size", (double) DimensionalDoorsInitializer.CONFIG.getPocketsConfig().publicPocketSize);
stringDoubleMap.put("private_size", (double) DimensionalDoorsInitializer.CONFIG.getPocketsConfig().privatePocketSize);
return stringDoubleMap;
}
}

View file

@ -0,0 +1,67 @@
package org.dimdev.dimdoors.util;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.util.math.Equation;
import java.util.Map;
public class TagEquations {
private static final Logger LOGGER = LogManager.getLogger();
public static CompoundTag solveCompoundTagEquations(CompoundTag tag, Map<String, Double> variableMap) {
CompoundTag solved = new CompoundTag();
for (String key : tag.getKeys()) {
if (tag.getType(key) == NbtType.STRING && key.startsWith("equation_")){
try {
double solution = Equation.parse(tag.getString(key)).apply(variableMap);
key = key.substring(9);
if (key.startsWith("int_")) {
key = key.substring(4);
solved.putInt(key, (int) solution);
}
else if (key.startsWith("boolean_")) {
key = key.substring(8);
solved.putBoolean(key, Equation.toBoolean(solution));
}
else if (key.startsWith("double_")) {
key = key.substring(7);
solved.putDouble(key, solution);
}
else {
solved.putDouble(key, solution);
}
} catch (Equation.EquationParseException e) {
LOGGER.error(e);
}
} else if (tag.getType(key) == NbtType.COMPOUND) {
solved.put(key, solveCompoundTagEquations(tag.getCompound(key), variableMap));
} else if (tag.getType(key) == NbtType.LIST) {
solved.put(key, solveListTagEquations((ListTag) tag.get(key), variableMap));
}
else {
solved.put(key, tag.get(key));
}
}
return solved;
}
public static ListTag solveListTagEquations(ListTag listTag, Map<String, Double> variableMap) {
ListTag solved = new ListTag();
for(Tag tag : listTag) {
if (tag.getType() == NbtType.LIST) {
solved.add(solveListTagEquations((ListTag) tag, variableMap));
}
else if (tag.getType() == NbtType.COMPOUND) {
solved.add(solveCompoundTagEquations((CompoundTag) tag, variableMap));
}
else {
solved.add(tag);
}
}
return solved;
}
}

View file

@ -0,0 +1,9 @@
package org.dimdev.dimdoors.util;
public interface Weighted<P> {
/*
Should always return the same number if the same parameters are provided.
returned number should always be >= 0
*/
double getWeight(P parameters);
}

View file

@ -0,0 +1,52 @@
package org.dimdev.dimdoors.util;
import java.util.*;
public class WeightedList<T extends Weighted<P>, P> extends ArrayList<T> {
private final Random random = new Random();
private T peekedRandom;
private boolean peeked = false;
public WeightedList() { }
public WeightedList(Collection<? extends T> c) {
super(c);
}
public T getNextRandomWeighted(P parameters) {
return getNextRandomWeighted(parameters, false);
}
public T peekNextRandomWeighted(P parameters) {
return getNextRandomWeighted(parameters, true);
}
private T getNextRandomWeighted(P parameters, boolean peek) {
if (!peeked) {
double totalWeight = stream().mapToDouble(weighted -> weighted.getWeight(parameters)).sum();
double cursor = random.nextDouble() * totalWeight;
if (cursor == 0) {
for (T weighted : this) {
if (weighted.getWeight(parameters) != 0) return weighted;
}
}
for (T weighted : this) {
cursor -= weighted.getWeight(parameters);
if (cursor <= 0) {
if (peek) {
peekedRandom = weighted;
peeked = true;
}
return weighted; // should never return an entry with weight 0, unless there are only weight 0 entries
}
}
if (peek) {
peekedRandom = null;
peeked = true;
}
return null;
}
if (!peek) peeked = false;
return peekedRandom;
}
}

View file

@ -0,0 +1,213 @@
package org.dimdev.dimdoors.util.math;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.*;
import java.util.function.BiFunction;
public interface Equation {
double FALSE = 0d;
double TRUE = 1d;
double apply(Map<String, Double> variableMap);
default boolean asBoolean(Map<String, Double> variableMap) {
return toBoolean(apply(variableMap));
}
static Equation parse(String equationString) throws EquationParseException {
return StringEquationParser.INSTANCE.parse(equationString);
}
static double toDouble(boolean value) {
return value ? TRUE : FALSE;
}
static boolean toBoolean(double value) {
return value != FALSE;
}
class StringEquationParser {
private static final Logger LOGGER = LogManager.getLogger();
public static StringEquationParser INSTANCE = new StringEquationParser();
private final static List<EquationParser> parseRules = new ArrayList<>();
static {
// Parenthesis
parseRules.add(toParse -> {
if (!toParse.startsWith("(") || !toParse.endsWith(")")) return Optional.empty();
return Optional.of(Equation.parse(toParse.substring(1, toParse.length() - 1)));
});
// try to parse as Double
parseRules.add(toParse -> {
try {
Double result = Double.parseDouble(toParse);
return Optional.of(stringDoubleMap -> result);
} catch (NumberFormatException e) {
return Optional.empty();
}
});
// some logic first
// ||
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> or = new HashMap<>();
or.put("||", (stringDoubleMap, first, second) -> toDouble(first.asBoolean(stringDoubleMap) || second.asBoolean(stringDoubleMap)));
parseRules.add(new SplitterParser(or));
// &&
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> and = new HashMap<>();
and.put("&&", (stringDoubleMap, first, second) -> toDouble(first.asBoolean(stringDoubleMap) || second.asBoolean(stringDoubleMap)));
parseRules.add(new SplitterParser(and));
// ==, <=, >=, <, >
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> comparators = new HashMap<>();
comparators.put("==", (stringDoubleMap, first, second) -> toDouble(first.apply(stringDoubleMap) == second.apply(stringDoubleMap)));
comparators.put("<=", (stringDoubleMap, first, second) -> toDouble(first.apply(stringDoubleMap) <= second.apply(stringDoubleMap)));
comparators.put(">=", (stringDoubleMap, first, second) -> toDouble(first.apply(stringDoubleMap) >= second.apply(stringDoubleMap)));
comparators.put("<", (stringDoubleMap, first, second) -> toDouble(first.apply(stringDoubleMap) < second.apply(stringDoubleMap)));
comparators.put(">", (stringDoubleMap, first, second) -> toDouble(first.apply(stringDoubleMap) > second.apply(stringDoubleMap)));
parseRules.add(new SplitterParser(comparators));
// +, -
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> sumOperations = new HashMap<>();
sumOperations.put("+", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) + second.apply(stringDoubleMap));
sumOperations.put("-", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) - second.apply(stringDoubleMap));
parseRules.add(new SplitterParser(sumOperations));
// *, /, %
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> dotOperations = new HashMap<>();
dotOperations.put("*", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) * second.apply(stringDoubleMap));
dotOperations.put("/", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) / second.apply(stringDoubleMap));
dotOperations.put("%", (stringDoubleMap, first, second) -> first.apply(stringDoubleMap) % second.apply(stringDoubleMap));
parseRules.add(new SplitterParser(dotOperations));
// x^y
Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> exponentOperations = new HashMap<>();
exponentOperations.put("^", (stringDoubleMap, first, second) -> Math.pow(first.apply(stringDoubleMap), second.apply(stringDoubleMap)));
parseRules.add(new SplitterParser(exponentOperations));
// H with H(0) = 1: https://en.wikipedia.org/wiki/Heaviside_step_function
parseRules.add(new FunctionParser("H", 1, 1, ((stringDoubleMap, equations) -> equations[0].apply(stringDoubleMap) >= 0 ? 1d : 0d)));
// floor
parseRules.add(new FunctionParser("floor", 1, 1, ((stringDoubleMap, equations) -> Math.floor(equations[0].apply(stringDoubleMap)))));
// ceil
parseRules.add(new FunctionParser("ceil", 1, 1, ((stringDoubleMap, equations) -> Math.ceil(equations[0].apply(stringDoubleMap)))));
// max
parseRules.add(new FunctionParser("max", 2, -1, ((stringDoubleMap, equations) -> {
Double max = equations[0].apply(stringDoubleMap);
for (int i = 1; i < equations.length; i++) {
max = Math.max(max, equations[i].apply(stringDoubleMap));
}
return max;
})));
// min
parseRules.add(new FunctionParser("min", 2, -1, ((stringDoubleMap, equations) -> {
Double min = equations[0].apply(stringDoubleMap);
for (int i = 1; i < equations.length; i++) {
min = Math.min(min, equations[i].apply(stringDoubleMap));
}
return min;
})));
// variable replacer
parseRules.add(new VariableReplacer());
}
public Equation parse(String equationString) throws EquationParseException {
equationString = equationString.replaceAll("\\s", "");
for (EquationParser parser : parseRules) {
Optional<Equation> equation = parser.tryParse(equationString);
if (equation.isPresent()) return equation.get();
}
throw new EquationParseException("\"" + equationString + "\" could not be parsed");
}
private interface EquationParser {
Optional<Equation> tryParse(String toParse) throws EquationParseException;
}
private static class VariableReplacer implements EquationParser {
@Override
public Optional<Equation> tryParse(String toParse) {
if (!toParse.matches("[a-zA-Z_][a-zA-Z0-9_]*")) return Optional.empty();
return Optional.of(stringDoubleMap -> {
if (stringDoubleMap != null && stringDoubleMap.containsKey(toParse)) return stringDoubleMap.get(toParse);
LOGGER.error("Variable \"" + toParse + "\" was not passed to equation! Returning 0 as fallback.");
return 0d;
});
}
}
private static class SplitterParser implements EquationParser {
private final Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> operations;
public SplitterParser(Map<String, TriFunction<Map<String, Double>, Equation, Equation, Double>> operations) {
this.operations = operations;
}
@Override
public Optional<Equation> tryParse(String toParse) throws EquationParseException {
int depth = 0;
for (int i = toParse.length() - 1; i >= 1 ; i--) {
String substring = toParse.substring(i);
if (substring.startsWith(")")) depth++;
else if (substring.startsWith("(")) depth--;
for(String symbol : operations.keySet()) {
if (substring.startsWith(symbol) && depth == 0) {
final TriFunction<Map<String, Double>, Equation, Equation, Double> operation = operations.get(symbol);
final Equation first = Equation.parse(toParse.substring(0,i));
final Equation second = Equation.parse(toParse.substring(i+1));
return Optional.of(stringDoubleMap -> operation.apply(stringDoubleMap, first, second));
}
}
}
return Optional.empty();
}
}
private static class FunctionParser implements EquationParser {
private final String functionString;
private final int minArguments;
private final int maxArguments;
private final BiFunction<Map<String, Double>, Equation[], Double> function;
public FunctionParser(String functionString, int minArguments, int maxArguments, BiFunction<Map<String, Double>, Equation[], Double> function) {
this.functionString = functionString + "(";
this.minArguments = minArguments;
this.maxArguments = maxArguments;
this.function = function;
}
@Override
public Optional<Equation> tryParse(String toParse) throws EquationParseException {
if (!toParse.startsWith(functionString) || !toParse.endsWith(")")) return Optional.empty();
String[] arguments = toParse.substring(functionString.length(), toParse.length()-1).split(",");
if (minArguments > arguments.length || (maxArguments < arguments.length && maxArguments != -1)) return Optional.empty();
final Equation[] argumentEquations = new Equation[arguments.length];
for (int i = 0; i < arguments.length; i++) {
argumentEquations[i] = Equation.parse(arguments[i]);
}
return Optional.of(stringDoubleMap -> function.apply(stringDoubleMap, argumentEquations));
}
}
private interface TriFunction<T, U, V, R> {
R apply(T t, U u, V v);
}
}
class EquationParseException extends Exception {
public EquationParseException(String message) {
super(message);
}
}
}

View file

@ -50,9 +50,11 @@ public final class ModDimensions {
return isPocketDimension(world.getRegistryKey());
}
public static boolean isPocketDimension(RegistryKey<World> type) {
System.out.println("Type: " + type);
public static boolean isPersonalPocketDimension(World world) {
return world != null && world == PERSONAL_POCKET_DIMENSION;
}
public static boolean isPocketDimension(RegistryKey<World> type) {
return Objects.equals(type, PERSONAL) || Objects.equals(type, PUBLIC) || Objects.equals(type, DUNGEON);
}

View file

@ -0,0 +1,50 @@
package org.dimdev.dimdoors.world.level;
import net.minecraft.item.ItemStack;
import dev.onyxstudios.cca.api.v3.item.ItemComponent;
public class Counter extends ItemComponent {
public Counter(ItemStack stack) {
super(stack, DimensionalDoorsComponents.COUNTER_COMPONENT_KEY);
if (!this.hasTag("counter"))
this.putInt("counter", 0);
}
public int count() {
return getInt("counter");
}
public void set(int value) {
this.putInt("counter", omitZero(value));
}
public int increment() {
int count = count() + 1;
this.putInt("counter", count);
return count;
}
public static <T> Counter get(T provider) {
return DimensionalDoorsComponents.COUNTER_COMPONENT_KEY.get(provider);
}
@Override
protected void putInt(String key, int value) {
super.putInt(key, omitZero(value));
}
@Override
protected int getInt(String key) {
return withZero(super.getInt(key));
}
private int omitZero(int value) {
return value >= 0 ? value + 1 : value;
}
private int withZero(int value) {
return value > 0 ? value - 1 : value;
}
}

View file

@ -4,14 +4,24 @@ import net.minecraft.util.Identifier;
import dev.onyxstudios.cca.api.v3.component.ComponentKey;
import dev.onyxstudios.cca.api.v3.component.ComponentRegistryV3;
import dev.onyxstudios.cca.api.v3.item.ItemComponentFactoryRegistry;
import dev.onyxstudios.cca.api.v3.item.ItemComponentInitializer;
import dev.onyxstudios.cca.api.v3.level.LevelComponentFactoryRegistry;
import dev.onyxstudios.cca.api.v3.level.LevelComponentInitializer;
import org.dimdev.dimdoors.item.ModItems;
public class DimensionalDoorsComponents implements LevelComponentInitializer {
public class DimensionalDoorsComponents implements LevelComponentInitializer, ItemComponentInitializer {
public static final ComponentKey<DimensionalRegistry> DIMENSIONAL_REGISTRY_COMPONENT_KEY = ComponentRegistryV3.INSTANCE.getOrCreate(new Identifier("dimdoors:dimensional_registry"), DimensionalRegistry.class);
public static final ComponentKey<Counter> COUNTER_COMPONENT_KEY = ComponentRegistryV3.INSTANCE.getOrCreate(new Identifier("dimdoors:counter"), Counter.class);
@Override
public void registerLevelComponentFactories(LevelComponentFactoryRegistry registry) {
registry.register(DIMENSIONAL_REGISTRY_COMPONENT_KEY, level -> new DimensionalRegistry());
}
@Override
public void registerItemComponentFactories(ItemComponentFactoryRegistry registry) {
registry.registerFor(ModItems.RIFT_CONFIGURATION_TOOL, COUNTER_COMPONENT_KEY, Counter::new);
}
}

View file

@ -15,18 +15,20 @@ import dev.onyxstudios.cca.api.v3.component.ComponentV3;
import org.dimdev.dimdoors.rift.registry.RiftRegistry;
import org.dimdev.dimdoors.world.ModDimensions;
import org.dimdev.dimdoors.world.pocket.PocketDirectory;
import org.dimdev.dimdoors.world.pocket.PrivateRegistry;
import static org.dimdev.dimdoors.DimensionalDoorsInitializer.getServer;
public class DimensionalRegistry implements ComponentV3 {
public Map<RegistryKey<World>, PocketDirectory> pocketRegistry = new HashMap<>();
RiftRegistry riftRegistry = new RiftRegistry();
PrivateRegistry privateRegistry = new PrivateRegistry();
@Override
public void readFromNbt(CompoundTag tag) {
CompoundTag pocketRegistryTag = tag.getCompound("pocketRegistry");
pocketRegistry = pocketRegistryTag.getKeys().stream().collect(Collectors.toMap(a -> RegistryKey.of(Registry.DIMENSION, new Identifier(a)), a -> PocketDirectory.readFromNbt(a, pocketRegistryTag.getCompound(a))));
riftRegistry = RiftRegistry.fromTag(pocketRegistry, tag.getCompound("riftRegistry"));
privateRegistry.fromTag(tag);
}
@Override
@ -36,6 +38,7 @@ public class DimensionalRegistry implements ComponentV3 {
tag.put("pocketRegistry", pocketRegistryTag);
tag.put("riftRegistry", riftRegistry.toTag());
privateRegistry.toTag(tag);
}
public static DimensionalRegistry instance() {
@ -46,6 +49,10 @@ public class DimensionalRegistry implements ComponentV3 {
return instance().riftRegistry;
}
public static PrivateRegistry getPrivateRegistry() {
return instance().privateRegistry;
}
public static PocketDirectory getPocketDirectory(RegistryKey<World> key) {
if (!(ModDimensions.isPocketDimension(key))) {
throw new UnsupportedOperationException("PocketRegistry is only available for pocket dimensions!");

View file

@ -1,26 +1,39 @@
package org.dimdev.dimdoors.world.pocket;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;
import com.flowpowered.math.vector.Vector3i;
import com.mojang.serialization.Codec;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.block.AncientFabricBlock;
import org.dimdev.dimdoors.block.FabricBlock;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.util.EntityUtils;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
public final class Pocket {
private static final int BLOCKS_PAINTED_PER_DYE = 1106;
private static final int BLOCKS_PAINTED_PER_DYE = 1000000;
// TODO: please someone make all these private and add a getter & setter where needed
public final int id;
public BlockBox box;
public VirtualLocation virtualLocation;
@ -30,20 +43,21 @@ public final class Pocket {
public RegistryKey<World> world;
private Pocket(int id, BlockBox box, VirtualLocation virtualLocation, PocketColor dyeColor, PocketColor nextDyeColor, int count) {
private Pocket(int id, BlockBox box, VirtualLocation virtualLocation, PocketColor dyeColor, PocketColor nextDyeColor, int count, RegistryKey<World> world) {
this.id = id;
this.box = box;
this.virtualLocation = virtualLocation;
this.dyeColor = dyeColor;
this.nextDyeColor = nextDyeColor;
this.count = count;
this.world = world;
}
public Pocket(int id, RegistryKey<World> world, int x, int z) {
int gridSize = DimensionalRegistry.getPocketDirectory(world).getGridSize() * 16;
this.id = id;
this.world = world;
this.box = new BlockBox(x * gridSize, 0, z * gridSize, (x + 1) * gridSize, 0, (z + 1) * gridSize);
this.box = BlockBox.create(x * gridSize, 0, z * gridSize, (x + 1) * gridSize, 0, (z + 1) * gridSize);
this.virtualLocation = new VirtualLocation(world, x, z, 0);
}
@ -55,6 +69,14 @@ public final class Pocket {
return new BlockPos(this.box.minX, this.box.minY, this.box.minZ);
}
public void offsetOrigin(Vec3i vec) {
offsetOrigin(vec.getX(), vec.getY(), vec.getZ());
}
public void offsetOrigin(int x, int y, int z) {
this.box = box.offset(x, y, z);
}
public boolean addDye(Entity entity, DyeColor dyeColor) {
PocketColor color = PocketColor.from(dyeColor);
@ -65,8 +87,9 @@ public final class Pocket {
return false;
}
if (this.nextDyeColor != null && this.nextDyeColor == color) {
if (this.count + 1 > amountOfDyeRequiredToColor(this)) {
if (this.nextDyeColor != PocketColor.NONE && this.nextDyeColor == color) {
if (this.count + 1 > maxDye) {
repaint(dyeColor);
this.dyeColor = color;
this.nextDyeColor = PocketColor.NONE;
this.count = 0;
@ -83,41 +106,33 @@ public final class Pocket {
return true;
}
// private void repaint(DyeColor dyeColor) {
// BlockPos origin = getOrigin();
// World world = WorldUtils.getWorld(dim);
// BlockState innerWall = ModBlocks.getDefaultState()..withProperty(..., dyeColor); // <-- forgot the exact name of the color property
// BlockState outerWall = ModBlocks.ETERNAL_FABRIC.getDefaultState().withProperty(..., dyeColor);
//
// for (int x = origin.getX(); x < origin.getX() + size; x++) {
// for (int y = origin.getY(); y < origin.getY() + size; y++) {
// for (int z = origin.getZ(); z < origin.getZ() + size; z++) {
// int layer = Collections.min(Arrays.asList(x, y, z, size - 1 - x, size - 1 - y, size - 1 - z));
// if (layer == 0) {
// if (world.getBlockState(x, y, z).getBlock() == ModBlocks.ETERNAL_FABRIC) {
// world.setBlockState(x, y, z, outerWall);
// }
// } else if (layer < 5) {
// if (world.getBlockState(x, y, z).getBlock() == ModBlocks.FABRIC) {
// world.setBlockState(x, y, z, innerWall);
// }
// }
// }
// }
// }
//
// return schematic;
// }
private void repaint(DyeColor dyeColor) {
ServerWorld serverWorld = DimensionalDoorsInitializer.getWorld(world);
BlockState innerWall = ModBlocks.fabricFromDye(dyeColor).getDefaultState();
BlockState outerWall = ModBlocks.ancientFabricFromDye(dyeColor).getDefaultState();
BlockPos.stream(box).forEach(pos -> {
if (serverWorld.getBlockState(pos).getBlock() instanceof AncientFabricBlock) {
serverWorld.setBlockState(pos, outerWall);
} else if (serverWorld.getBlockState(pos).getBlock() instanceof FabricBlock) {
serverWorld.setBlockState(pos, innerWall);
}
});
}
private static int amountOfDyeRequiredToColor(Pocket pocket) {
int outerVolume = pocket.box.getBlockCountX() * pocket.box.getBlockCountY() * pocket.box.getBlockCountZ();
int innerVolume = (pocket.box.getBlockCountX() - 5) * (pocket.box.getBlockCountY() - 5) * (pocket.box.getBlockCountZ() - 5);
return (outerVolume - innerVolume) / BLOCKS_PAINTED_PER_DYE;
return Math.max((outerVolume - innerVolume) / BLOCKS_PAINTED_PER_DYE, 1);
}
public void setSize(Vec3i size) {
setSize(size.getX(), size.getY(), size.getZ());
}
public void setSize(int x, int y, int z) {
this.box = new BlockBox(this.box.minX, this.box.minY, this.box.minZ, this.box.minX + x, this.box.minY + y, this.box.minZ + z);
this.box = BlockBox.create(this.box.minX, this.box.minY, this.box.minZ, this.box.minX + x - 1, this.box.minY + y - 1, this.box.minZ + z - 1);
}
public Vector3i getSize() {
@ -133,6 +148,7 @@ public final class Pocket {
tag.putInt("dyeColor", this.dyeColor.getId());
tag.putInt("nextDyeColor", this.nextDyeColor.getId());
tag.putInt("count", this.count);
tag.putString("world", world.getValue().toString());
return tag;
}
@ -144,7 +160,8 @@ public final class Pocket {
VirtualLocation.fromTag(tag.getCompound("virtualLocation")),
PocketColor.from(tag.getInt("dyeColor")),
PocketColor.from(tag.getInt("nextDyeColor")),
tag.getInt("count")
tag.getInt("count"),
RegistryKey.of(Registry.DIMENSION, new Identifier(tag.getString("world")))
);
}
@ -205,4 +222,34 @@ public final class Pocket {
return NONE;
}
}
public Map<BlockPos, BlockEntity> getBlockEntities() {
ServerWorld serverWorld = DimensionalDoorsInitializer.getWorld(this.world);
Map<BlockPos, BlockEntity> blockEntities = new HashMap<>();
ChunkPos.stream(new ChunkPos(new BlockPos(box.minX, box.minY, box.minZ)), new ChunkPos(new BlockPos(box.maxX, box.maxY, box.maxZ))).forEach(chunkPos -> serverWorld.getChunk(chunkPos.x, chunkPos.z).getBlockEntities().forEach((blockPos, blockEntity) -> {
if (this.box.contains(blockPos)) blockEntities.put(blockPos, blockEntity);
}));
return blockEntities;
}
public BlockBox getBox() {
return box;
}
public Map<String, Double> toVariableMap(Map<String, Double> stringDoubleMap) {
stringDoubleMap.put("originX", (double) this.box.minX);
stringDoubleMap.put("originY", (double) this.box.minY);
stringDoubleMap.put("originZ", (double) this.box.minZ);
stringDoubleMap.put("width", (double) this.box.getDimensions().getX());
stringDoubleMap.put("height", (double) this.box.getDimensions().getY());
stringDoubleMap.put("length", (double) this.box.getDimensions().getZ());
stringDoubleMap.put("depth", (double) this.virtualLocation.getDepth());
stringDoubleMap.put("id", (double) this.id); // don't really know why you would need this but it's there if needed
return stringDoubleMap;
}
public void expand(int amount) {
if (amount == 0) return;
this.box = BlockBox.create(box.minX - amount, box.minY - amount, box.minZ - amount, box.maxX + amount, box.maxY + amount, box.maxZ + amount);
}
}

View file

@ -5,6 +5,8 @@ import java.util.UUID;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import dev.onyxstudios.cca.api.v3.component.ComponentV3;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
@ -17,7 +19,7 @@ import net.minecraft.world.World;
import static net.minecraft.world.World.OVERWORLD;
public class PrivatePocketData extends PersistentState {
public class PrivateRegistry {
protected static class PocketInfo {
public final RegistryKey<World> world;
public final int id;
@ -46,19 +48,9 @@ public class PrivatePocketData extends PersistentState {
protected BiMap<UUID, PocketInfo> privatePocketMap = HashBiMap.create(); // Player UUID -> Pocket Info TODO: fix AnnotatedNBT and use UUID rather than String
public PrivatePocketData(String name) {
super(name);
public PrivateRegistry() {
}
public PrivatePocketData() {
super(DATA_NAME);
}
public static PrivatePocketData instance() {
return DimensionalDoorsInitializer.getWorld(OVERWORLD).getPersistentStateManager().getOrCreate(PrivatePocketData::new, DATA_NAME);
}
@Override
public void fromTag(CompoundTag nbt) {
CompoundTag tag = nbt.getCompound("privatePocketMap");
@ -69,7 +61,6 @@ public class PrivatePocketData extends PersistentState {
this.privatePocketMap = bm;
}
@Override
public CompoundTag toTag(CompoundTag nbt) {
CompoundTag tag = new CompoundTag();
for (Map.Entry<UUID, PocketInfo> entry : this.privatePocketMap.entrySet()) {
@ -88,7 +79,6 @@ public class PrivatePocketData extends PersistentState {
public void setPrivatePocketID(UUID playerUUID, Pocket pocket) {
this.privatePocketMap.put(playerUUID, new PocketInfo(pocket.world, pocket.id));
this.markDirty();
}
public UUID getPrivatePocketOwner(Pocket pocket) {

View file

@ -76,8 +76,7 @@ public class VirtualLocation {
if (virtualLocation == null) {
return new VirtualLocation(OVERWORLD, location.getX(), location.getZ(), 5);
}
return virtualLocation;
return new VirtualLocation(location.getWorldId(), location.getX(), location.getZ(), virtualLocation.getDepth());
}
public Location projectToWorld(boolean acceptLimbo) {

View file

@ -12,7 +12,7 @@
"facing=south,half=lower,hinge=left,open=true": { "model": "dimdoors:block/gold_door_bottom_rh", "y": 180 },
"facing=west,half=lower,hinge=left,open=true": { "model": "dimdoors:block/gold_door_bottom_rh", "y": 270 },
"facing=north,half=lower,hinge=left,open=true": { "model": "dimdoors:block/gold_door_bottom_rh" },
"facing=east,half=lower,hinge=right,open=true": { "model": "dimdoors:block/blocks/gold_door_bottom", "y": 270 },
"facing=east,half=lower,hinge=right,open=true": { "model": "dimdoors:block/gold_door_bottom", "y": 270 },
"facing=south,half=lower,hinge=right,open=true": { "model": "dimdoors:block/gold_door_bottom" },
"facing=west,half=lower,hinge=right,open=true": { "model": "dimdoors:block/gold_door_bottom", "y": 90 },
"facing=north,half=lower,hinge=right,open=true": { "model": "dimdoors:block/gold_door_bottom", "y": 180 },

View file

@ -60,6 +60,7 @@
"item.dimdoors.stabilized_rift_signature.stored": "Location stored",
"item.dimdoors.stabilized_rift_signature.created": "Rift created",
"item.dimdoors.rift_configuration_tool": "Rift Configuration Tool",
"item.dimdoors.rift_configuration_tool.info": "TODO",
"item.dimdoors.rift_remover": "Rift Remover",
"item.dimdoors.rift_remover.closing": "The rift will close soon",
"item.dimdoors.rift_remover.already_closing": "This rift is already closing",
@ -191,4 +192,4 @@
"argument.dimdoors.schematic.invalidNamespace": "Invalid schematic namespace. Expected one of %s, found %s.",
"command.dimdoors.schematicv2.unknownSchematic": "Unknown schematic \"%s\" in namespace \"%s\" ",
"dimdoors.config.screen.reload": "Reload Config"
}
}

View file

@ -0,0 +1,43 @@
{
"type": "dimdoors:schematic",
"id": "v2/custom/purpur_hallway",
"modifiers": [
{
"layers": [
{
"block_state": "dimdoors:pink_ancient_fabric",
"thickness": "1"
}
],
"type": "dimdoors:shell"
},
{
"type": "dimdoors:rift_data",
"ids": [0],
"rift_data": "rift_data/pocket_entrance"
},
{
"type": "dimdoors:rift_data",
"ids": [4],
"rift_data": "rift_data/public_entrance"
},
{
"type": "dimdoors:relative",
"point_a": 1,
"point_b": 7
},
{
"type": "dimdoors:relative",
"point_a": 2,
"point_b": 6
},
{
"type": "dimdoors:relative",
"point_a": 3,
"point_b": 5
}
],
"offset_x": "1",
"offset_y": "1",
"offset_z": "1"
}

View file

@ -0,0 +1,45 @@
{
"width": "5 + 16 * private_size",
"length": "5 + 16 * private_size",
"type": "dimdoors:void",
"modifiers": [
{
"layers": [
{
"block_state": "dimdoors:white_fabric",
"thickness": "4"
},
{
"block_state": "dimdoors:white_ancient_fabric",
"thickness": "1"
}
],
"type": "dimdoors:shell"
},
{
"door_type": "dimdoors:quartz_dimensional_door",
"x": "width/2",
"facing": "north",
"y": "5",
"z": "4",
"type": "dimdoors:door",
"rift_data": {
"destination": {
"ifDestination": {
"type": "dimdoors:private_pocket_exit"
},
"weight": 1.0,
"type": "dimdoors:pocket_entrance"
}
}
},
{
"type": "dimdoors:pocket_entrance",
"id": 0
}
],
"offset_x": "5",
"offset_y": "5",
"offset_z": "5",
"height": "5 + 16 * min(15, private_size)"
}

View file

@ -0,0 +1,42 @@
{
"width": "5 + 16 * public_size",
"length": "5 + 16 * public_size",
"type": "dimdoors:void",
"modifiers": [
{
"layers": [
{
"block_state": "dimdoors:black_fabric",
"thickness": "4"
},
{
"block_state": "dimdoors:black_ancient_fabric",
"thickness": "1"
}
],
"type": "dimdoors:shell"
},
{
"door_type": "dimdoors:iron_dimensional_door",
"x": "width/2",
"facing": "north",
"y": "5",
"z": "4",
"type": "dimdoors:door",
"rift_data": {
"destination": {
"type": "dimdoors:id_marker",
"id": 0
}
}
},
{
"type": "dimdoors:pocket_entrance",
"id": 0
}
],
"offset_x": "5",
"offset_y": "5",
"offset_z": "5",
"height": "5 + 16 * min(15, public_size)"
}

View file

@ -0,0 +1,4 @@
{
"id": "custom/purpur_hallway",
"type": "dimdoors:id"
}

View file

@ -0,0 +1,4 @@
{
"id": "private/default",
"type": "dimdoors:id"
}

View file

@ -0,0 +1,4 @@
{
"id": "public/default",
"type": "dimdoors:id"
}

View file

@ -0,0 +1,9 @@
{
"destination": {
"ifDestination": {
"type": "dimdoors:pocket_exit"
},
"weight": 1.0,
"type": "dimdoors:pocket_entrance"
}
}

View file

@ -0,0 +1,5 @@
{
"destination": {
"type": "dimdoors:public_pocket"
}
}

View file

@ -1,45 +0,0 @@
{
"group": "private",
"pockets": [
{
"id": "private_pocket_0",
"size": 0,
"weight": 20
},
{
"id": "private_pocket_1",
"size": 1,
"weight": 17
},
{
"id": "private_pocket_2",
"size": 2,
"weight": 14
},
{
"id": "private_pocket_3",
"size": 3,
"weight": 11
},
{
"id": "private_pocket_4",
"size": 4,
"weight": 8
},
{
"id": "private_pocket_5",
"size": 5,
"weight": 5
},
{
"id": "private_pocket_6",
"size": 6,
"weight": 3
},
{
"id": "private_pocket_7",
"size": 7,
"weight": 1
}
]
}

View file

@ -1,45 +0,0 @@
{
"group": "public",
"pockets": [
{
"id": "public_pocket_0",
"size": 0,
"weight": 20
},
{
"id": "public_pocket_1",
"size": 1,
"weight": 17
},
{
"id": "public_pocket_2",
"size": 2,
"weight": 14
},
{
"id": "public_pocket_3",
"size": 3,
"weight": 11
},
{
"id": "public_pocket_4",
"size": 4,
"weight": 8
},
{
"id": "public_pocket_5",
"size": 5,
"weight": 5
},
{
"id": "public_pocket_6",
"size": 6,
"weight": 3
},
{
"id": "public_pocket_7",
"size": 7,
"weight": 1
}
]
}

View file

@ -44,7 +44,8 @@
},
"custom": {
"cardinal-components": [
"dimdoors:dimensional_registry"
"dimdoors:dimensional_registry",
"dimdoors:counter"
]
}
}

View file

@ -7,7 +7,10 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.Fluids;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -140,18 +143,26 @@ public class Schematic implements BlockView {
}
Block block = Registry.BLOCK.get(new Identifier(id));
Fluid fluid = Registry.FLUID.get(new Identifier(id));
if (block == Blocks.AIR && !"minecraft:air".equals(id)) {
BlockState blockstate;
if (block == Blocks.AIR && fluid == Fluids.EMPTY && !"minecraft:air".equals(id)) {
System.err.println("Missing ID: " + blockStateString);
}
BlockState blockstate = block.getDefaultState();
if (!state.isEmpty()) {
String[] properties = state.split(",");
blockstate = getBlockStateWithProperties(block, properties);
if (fluid != Fluids.EMPTY) {
blockstate = fluid.getDefaultState().getBlockState();
if (!state.isEmpty()) {
String[] properties = state.split(",");
blockstate = getBlockStateWithProperties(blockstate.getBlock(), properties);
}
}
else {
blockstate = block.getDefaultState();
if (!state.isEmpty()) {
String[] properties = state.split(",");
blockstate = getBlockStateWithProperties(block, properties);
}
}
schematic.palette.add(blockstate); //@todo, can we assume that a schematic file always has all palette integers used from 0 to pallettemax-1?
}
@ -184,7 +195,7 @@ public class Schematic implements BlockView {
}
SchematicRedstoneFixer.fixRedstone(schematic);
SchematicBlockConnectionFixer.fixBlocks(schematic);
return schematic;
}
@ -261,7 +272,7 @@ public class Schematic implements BlockView {
for (Entry<String, String> entry : propertyAndBlockStringsMap.entrySet()) {
Property<?> property = stateManager.getProperty(entry.getKey());
if (property == null) LOGGER.info("Missing property " + entry.getKey() + " in: " + chosenState + "[" + propertyAndBlockStringsMap.entrySet().stream().map(mapEntry -> mapEntry.getKey() + "=" + mapEntry.getValue()).collect(Collectors.joining(",")) + "]");
if (property != null) {
Comparable<?> value = null;
for (Comparable<?> object : property.getValues()) {
@ -409,7 +420,6 @@ public class Schematic implements BlockView {
if (x < 0 || x >= this.sizeX || y < 0 || y >= this.sizeY || z < 0 || z >= this.sizeZ) {
return Blocks.AIR.getDefaultState();
}
return this.palette.get(this.blockData[x][y][z]);
}
@ -455,9 +465,6 @@ public class Schematic implements BlockView {
if (setAir || !state.getBlock().equals(Blocks.AIR)) {
section.setBlockState(lx, ly, lz, state);
// BlockPos pos = new BlockPos(originX + x, originY + y, originZ + z);
// serverWorld.getChunkManager().markForUpdate(pos);
// serverWorld.getLightingProvider().checkBlock(pos);
if (y > 255) {
System.out.println();
}

View file

@ -0,0 +1,162 @@
package org.dimdev.dimdoors.util.schematic;
import net.minecraft.block.*;
import net.minecraft.block.enums.DoubleBlockHalf;
import net.minecraft.block.enums.StairShape;
import org.dimdev.dimdoors.mixin.accessor.RedstoneWireBlockAccessor;
import net.minecraft.block.enums.WireConnection;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
// TODO: probably need to fix tall_grass -> upper, lower
public class SchematicBlockConnectionFixer {
public static void fixBlocks(Schematic schematic) {
for (int x = 0; x < schematic.sizeX; x++) {
for (int y = 0; y < schematic.sizeY; y++) {
for (int z = 0; z < schematic.sizeZ; z++) {
BlockState state = schematic.getBlockState(x, y, z);
if (state != null) {
Block block = state.getBlock();
if (block == Blocks.REDSTONE_WIRE) {
int power = state.get(RedstoneWireBlock.POWER);
schematic.setBlockState(x, y, z, getRedstonePlacementState(schematic, new BlockPos(x, y, z)).with(RedstoneWireBlock.POWER, power));
} else if (block instanceof FenceBlock) {
schematic.setBlockState(x, y, z, getFencePlacementState(schematic, new BlockPos(x, y, z), (FenceBlock) block, state));
} else if (block instanceof PaneBlock) {
schematic.setBlockState(x, y, z, getPanePlacementState(schematic, new BlockPos(x, y, z), (PaneBlock) block, state));
} else if (block instanceof DoorBlock && state.get(DoorBlock.HALF).equals(DoubleBlockHalf.UPPER)) {
schematic.setBlockState(x, y, z, getUpperDoorHalfPlacementState(schematic, new BlockPos(x, y, z), (DoorBlock) block, state));
} else if (block instanceof StairsBlock) {
schematic.setBlockState(x, y, z, state.with(StairsBlock.SHAPE, getStairShape(state, schematic, new BlockPos(x, y, z))));
}
}
}
}
}
}
public static StairShape getStairShape(BlockState state, BlockView world, BlockPos pos) {
Direction direction = (Direction)state.get(StairsBlock.FACING);
BlockState blockState = world.getBlockState(pos.offset(direction));
if (StairsBlock.isStairs(blockState) && state.get(StairsBlock.HALF) == blockState.get(StairsBlock.HALF)) {
Direction direction2 = (Direction)blockState.get(StairsBlock.FACING);
if (direction2.getAxis() != ((Direction)state.get(StairsBlock.FACING)).getAxis() && method_10678(state, world, pos, direction2.getOpposite())) {
if (direction2 == direction.rotateYCounterclockwise()) {
return StairShape.OUTER_LEFT;
}
return StairShape.OUTER_RIGHT;
}
}
BlockState blockState2 = world.getBlockState(pos.offset(direction.getOpposite()));
if (StairsBlock.isStairs(blockState2) && state.get(StairsBlock.HALF) == blockState2.get(StairsBlock.HALF)) {
Direction direction3 = (Direction)blockState2.get(StairsBlock.FACING);
if (direction3.getAxis() != ((Direction)state.get(StairsBlock.FACING)).getAxis() && method_10678(state, world, pos, direction3)) {
if (direction3 == direction.rotateYCounterclockwise()) {
return StairShape.INNER_LEFT;
}
return StairShape.INNER_RIGHT;
}
}
return StairShape.STRAIGHT;
}
private static boolean method_10678(BlockState state, BlockView world, BlockPos pos, Direction dir) {
BlockState blockState = world.getBlockState(pos.offset(dir));
return !StairsBlock.isStairs(blockState) || blockState.get(StairsBlock.FACING) != state.get(StairsBlock.FACING) || blockState.get(StairsBlock.HALF) != state.get(StairsBlock.HALF);
}
public static BlockState getUpperDoorHalfPlacementState(BlockView world, BlockPos pos, DoorBlock block, BlockState state) {
BlockState lower = world.getBlockState(pos.down());
return state.with(DoorBlock.FACING, lower.get(DoorBlock.FACING)).with(DoorBlock.HINGE, lower.get(DoorBlock.HINGE)).with(DoorBlock.OPEN, lower.get(DoorBlock.OPEN)).with(DoorBlock.POWERED, lower.get(DoorBlock.POWERED));
}
public static BlockState getPanePlacementState(BlockView world, BlockPos pos, PaneBlock block, BlockState state) {
BlockPos blockPos2 = pos.north();
BlockPos blockPos3 = pos.east();
BlockPos blockPos4 = pos.south();
BlockPos blockPos5 = pos.west();
BlockState blockState = world.getBlockState(blockPos2);
BlockState blockState2 = world.getBlockState(blockPos3);
BlockState blockState3 = world.getBlockState(blockPos4);
BlockState blockState4 = world.getBlockState(blockPos5);
return state
.with(HorizontalConnectingBlock.NORTH, block.connectsTo(blockState, blockState.isSideSolidFullSquare(world, blockPos2, Direction.SOUTH)))
.with(HorizontalConnectingBlock.EAST, block.connectsTo(blockState2, blockState2.isSideSolidFullSquare(world, blockPos3, Direction.WEST)))
.with(HorizontalConnectingBlock.SOUTH, block.connectsTo(blockState3, blockState3.isSideSolidFullSquare(world, blockPos4, Direction.NORTH)))
.with(HorizontalConnectingBlock.WEST, block.connectsTo(blockState4, blockState4.isSideSolidFullSquare(world, blockPos5, Direction.EAST)));
}
public static BlockState getFencePlacementState(BlockView world, BlockPos pos, FenceBlock block, BlockState state) {
BlockPos blockPos2 = pos.north();
BlockPos blockPos3 = pos.east();
BlockPos blockPos4 = pos.south();
BlockPos blockPos5 = pos.west();
BlockState blockState = world.getBlockState(blockPos2);
BlockState blockState2 = world.getBlockState(blockPos3);
BlockState blockState3 = world.getBlockState(blockPos4);
BlockState blockState4 = world.getBlockState(blockPos5);
return state
.with(HorizontalConnectingBlock.NORTH, block.canConnect(blockState, blockState.isSideSolidFullSquare(world, blockPos2, Direction.SOUTH), Direction.SOUTH))
.with(HorizontalConnectingBlock.EAST, block.canConnect(blockState2, blockState2.isSideSolidFullSquare(world, blockPos3, Direction.WEST), Direction.WEST))
.with(HorizontalConnectingBlock.SOUTH, block.canConnect(blockState3, blockState3.isSideSolidFullSquare(world, blockPos4, Direction.NORTH), Direction.NORTH))
.with(HorizontalConnectingBlock.WEST, block.canConnect(blockState4, blockState4.isSideSolidFullSquare(world, blockPos5, Direction.EAST), Direction.EAST));
}
public static BlockState getRedstonePlacementState(BlockView world, BlockPos pos) {
WireConnection west = getRenderConnectionType(world, pos, Direction.WEST);
WireConnection east = getRenderConnectionType(world, pos, Direction.EAST);
WireConnection north = getRenderConnectionType(world, pos, Direction.NORTH);
WireConnection south = getRenderConnectionType(world, pos, Direction.SOUTH);
int connectionCount = 0;
if (west.isConnected()) connectionCount++;
if (east.isConnected()) connectionCount++;
if (north.isConnected()) connectionCount++;
if (south.isConnected()) connectionCount++;
switch (connectionCount) {
case 0: // should actually connect to all sides, forming a cross
return Blocks.REDSTONE_WIRE.getDefaultState()
.with(RedstoneWireBlock.WIRE_CONNECTION_WEST, WireConnection.SIDE)
.with(RedstoneWireBlock.WIRE_CONNECTION_EAST, WireConnection.SIDE)
.with(RedstoneWireBlock.WIRE_CONNECTION_NORTH, WireConnection.SIDE)
.with(RedstoneWireBlock.WIRE_CONNECTION_SOUTH, WireConnection.SIDE);
case 1: // should actually connect to the other side as well, forming a line
if (west.isConnected()) return Blocks.REDSTONE_WIRE.getDefaultState()
.with(RedstoneWireBlock.WIRE_CONNECTION_WEST, west)
.with(RedstoneWireBlock.WIRE_CONNECTION_EAST, WireConnection.SIDE)
.with(RedstoneWireBlock.WIRE_CONNECTION_NORTH, WireConnection.NONE)
.with(RedstoneWireBlock.WIRE_CONNECTION_SOUTH, WireConnection.NONE);
if (east.isConnected()) return Blocks.REDSTONE_WIRE.getDefaultState()
.with(RedstoneWireBlock.WIRE_CONNECTION_WEST, WireConnection.SIDE)
.with(RedstoneWireBlock.WIRE_CONNECTION_EAST, east)
.with(RedstoneWireBlock.WIRE_CONNECTION_NORTH, WireConnection.NONE)
.with(RedstoneWireBlock.WIRE_CONNECTION_SOUTH, WireConnection.NONE);
if (north.isConnected()) return Blocks.REDSTONE_WIRE.getDefaultState()
.with(RedstoneWireBlock.WIRE_CONNECTION_WEST, WireConnection.NONE)
.with(RedstoneWireBlock.WIRE_CONNECTION_EAST, WireConnection.NONE)
.with(RedstoneWireBlock.WIRE_CONNECTION_NORTH, north)
.with(RedstoneWireBlock.WIRE_CONNECTION_SOUTH, WireConnection.SIDE);
return Blocks.REDSTONE_WIRE.getDefaultState()
.with(RedstoneWireBlock.WIRE_CONNECTION_WEST, WireConnection.NONE)
.with(RedstoneWireBlock.WIRE_CONNECTION_EAST, WireConnection.NONE)
.with(RedstoneWireBlock.WIRE_CONNECTION_NORTH, WireConnection.SIDE)
.with(RedstoneWireBlock.WIRE_CONNECTION_SOUTH, south);
default:
return Blocks.REDSTONE_WIRE.getDefaultState()
.with(RedstoneWireBlock.WIRE_CONNECTION_WEST, getRenderConnectionType(world, pos, Direction.WEST))
.with(RedstoneWireBlock.WIRE_CONNECTION_EAST, getRenderConnectionType(world, pos, Direction.EAST))
.with(RedstoneWireBlock.WIRE_CONNECTION_NORTH, getRenderConnectionType(world, pos, Direction.NORTH))
.with(RedstoneWireBlock.WIRE_CONNECTION_SOUTH, getRenderConnectionType(world, pos, Direction.SOUTH));
}
}
private static WireConnection getRenderConnectionType(BlockView world, BlockPos pos, Direction direction) {
return ((RedstoneWireBlockAccessor) Blocks.REDSTONE_WIRE).invokeGetRenderConnectionType(world, pos, direction);
}
}

View file

@ -5,6 +5,9 @@ import java.util.Map;
public class SchematicConverter {
public static Map<String, String> CONVERSIONS = new HashMap<>();
private static final String[] COLORS = new String[]{"white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray", "light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black"};
private static final String[] facingStrings = new String[] {"north", "south", "east", "west"};
private static final String[] BRICK_VARIANTS = new String[]{"stone_brick", "nether_brick"};
public static String updateId(String id) {
@ -77,6 +80,8 @@ public class SchematicConverter {
CONVERSIONS.put("minecraft:leaves[check_decay=false]", "minecraft:oak_leaves[persistent=true]");
CONVERSIONS.put("minecraft:leaves[variant=jungle]", "minecraft:jungle_leaves[persistent=true]");
CONVERSIONS.put("minecraft:leaves[check_decay=false,variant=spruce]", "minecraft:spruce_leaves[persistent=true]");
CONVERSIONS.put("minecraft:powered_repeater", "minecraft:repeater[facing=north,powered=true]");
@ -200,6 +205,17 @@ public class SchematicConverter {
CONVERSIONS.put("minecraft:unpowered_comparator[facing=east,delay=4]", "minecraft:comparator[delay=4,facing=east,powered=false]");
CONVERSIONS.put("minecraft:unpowered_comparator[facing=west,delay=4]", "minecraft:comparator[delay=4,facing=west,powered=false]");
CONVERSIONS.put("minecraft:unpowered_comparator[powered=true]", "minecraft:comparator[facing=north,powered=false,mode=subtract]");
CONVERSIONS.put("minecraft:unpowered_comparator[powered=true,facing=north]", "minecraft:comparator[facing=north,powered=false,mode=subtract]");
CONVERSIONS.put("minecraft:unpowered_comparator[powered=true,facing=south]", "minecraft:comparator[facing=south,powered=false,mode=subtract]");
CONVERSIONS.put("minecraft:unpowered_comparator[powered=true,facing=east]", "minecraft:comparator[facing=east,powered=false,mode=subtract]");
CONVERSIONS.put("minecraft:unpowered_comparator[powered=true,facing=west]", "minecraft:comparator[facing=west,powered=false,mode=subtract]");
CONVERSIONS.put("minecraft:powered_comparator[powered=true]", "minecraft:comparator[facing=north,powered=true,mode=subtract]");
CONVERSIONS.put("minecraft:powered_comparator[powered=true,facing=north]", "minecraft:comparator[facing=north,powered=true,mode=subtract]");
CONVERSIONS.put("minecraft:powered_comparator[powered=true,facing=south]", "minecraft:comparator[facing=south,powered=true,mode=subtract]");
CONVERSIONS.put("minecraft:powered_comparator[powered=true,facing=east]", "minecraft:comparator[facing=east,powered=true,mode=subtract]");
CONVERSIONS.put("minecraft:powered_comparator[powered=true,facing=west]", "minecraft:comparator[facing=west,powered=true,mode=subtract]");
CONVERSIONS.put("minecraft:unpowered_comparator[delay=2,facing=north]", "minecraft:comparator[delay=2,facing=north,powered=false]");
CONVERSIONS.put("minecraft:unpowered_comparator[delay=2,facing=south]", "minecraft:comparator[delay=2,facing=south,powered=false]");
@ -231,6 +247,65 @@ public class SchematicConverter {
CONVERSIONS.put("minecraft:stonebrick", "minecraft:stone_bricks");
CONVERSIONS.put("minecraft:log[axis=z,variant=jungle]", "minecraft:jungle_log[axis=z]");
CONVERSIONS.put("minecraft:unlit_redstone_torch", "minecraft:redstone_torch[lit=false]");
//CONVERSIONS.put("minecraft:unlit_redstone_torch", "minecraft:redstone_torch[lit=false]");
for (boolean lit : new boolean[]{false, true}) {
CONVERSIONS.put("minecraft:" + (lit ? "" : "unlit_") + "redstone_torch", "minecraft:redstone_torch[lit=" + (lit ? "true" : "false") + "]");
for (String facing : facingStrings) {
CONVERSIONS.put("minecraft:" + (lit ? "" : "unlit_") + "redstone_torch[facing=" + facing + "]", "minecraft:redstone_wall_torch[facing=" + facing + ",lit=" + (lit ? "true" : "false") + "]");
}
}
for (String color : COLORS) {
CONVERSIONS.put("minecraft:wool[color=" + color + "]", "minecraft:" + color + "_wool");
CONVERSIONS.put("minecraft:stained_hardened_clay[color=" + color + "]", "minecraft:" + color + "_terracotta");
}
for (String facing : facingStrings) {
CONVERSIONS.put("minecraft:torch[facing=" + facing + "]", "minecraft:wall_torch[facing=" + facing + "]");
}
CONVERSIONS.put("minecraft:stonebrick[variant=cracked_stonebrick]", "minecraft:cracked_stone_bricks");
CONVERSIONS.put("minecraft:stonebrick[variant=chiseled_stonebrick]", "minecraft:chiseled_stone_bricks");
CONVERSIONS.put("minecraft:monster_egg[variant=stone_brick]", "minecraft:infested_chiseled_stone_bricks");
CONVERSIONS.put("minecraft:nether_brick", "minecraft:nether_bricks");
CONVERSIONS.put("minecraft:noteblock", "minecraft:note_block");
CONVERSIONS.put("minecraft:quartz_ore", "minecraft:nether_quartz_ore");
CONVERSIONS.put("minecraft:grass", "minecraft:grass_block");
CONVERSIONS.put("minecraft:stone_slab", "minecraft:smooth_stone_slab");
CONVERSIONS.put("minecraft:stone_slab[half=top]", "minecraft:smooth_stone_slab[type=top]");
CONVERSIONS.put("minecraft:stone_slab[variant=cobblestone]", "minecraft:cobblestone_slab");
CONVERSIONS.put("minecraft:stone_slab[half=top,variant=cobblestone]", "minecraft:cobblestone_slab[type=top]");
for (String variant : BRICK_VARIANTS) {
CONVERSIONS.put("minecraft:stone_slab[variant=" + variant + "]", "minecraft:" + variant + "_slab");
CONVERSIONS.put("minecraft:stone_slab[half=top,variant=" + variant + "]", "minecraft:" + variant + "_slab[type=top]");
}
CONVERSIONS.put("minecraft:stone_stairs", "minecraft:cobblestone_stairs");
CONVERSIONS.put("minecraft:stone_stairs[half=top]", "minecraft:cobblestone_stairs[half=top]");
for(String facing : facingStrings) {
CONVERSIONS.put("minecraft:stone_stairs[facing=" + facing + "]", "minecraft:cobblestone_stairs[facing=" + facing + "]");
CONVERSIONS.put("minecraft:stone_stairs[facing=" + facing + ",half=top]", "minecraft:cobblestone_stairs[facing=" + facing + ",half=top]");
}
CONVERSIONS.put("minecraft:tnt[explode=true]", "minecraft:tnt[unstable=true]");
CONVERSIONS.put("minecraft:web", "minecraft:cobweb");
for (int i = 1; i < 16; i++) {
CONVERSIONS.put("minecraft:lava[level=" + i + "]", "minecraft:flowing_lava[level=" + i + "]");
}
for (int i = 1; i < 16; i++) {
CONVERSIONS.put("minecraft:water[level=" + i + "]", "minecraft:flowing_water[level=" + i + "]");
}
CONVERSIONS.put("minecraft:tallgrass[type=tall_grass]", "minecraft:tall_grass");
CONVERSIONS.put("minecraft:stonebrick[variant=mossy_stonebrick]", "minecraft:mossy_stone_bricks");
CONVERSIONS.put("minecraft:waterlily", "minecraft:lily_pad");
CONVERSIONS.put("minecraft:lit_redstone_lamp", "minecraft:redstone_lamp[lit=true]");
CONVERSIONS.put("minecraft:snow_layer", "minecraft:snow");
}
}

View file

@ -1,40 +0,0 @@
package org.dimdev.dimdoors.util.schematic;
import org.dimdev.dimdoors.mixin.accessor.RedstoneWireBlockAccessor;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneWireBlock;
import net.minecraft.block.enums.WireConnection;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
public class SchematicRedstoneFixer {
public static void fixRedstone(Schematic schematic) {
for (int x = 0; x < schematic.sizeX; x++) {
for (int y = 0; y < schematic.sizeY; y++) {
for (int z = 0; z < schematic.sizeZ; z++) {
BlockState state = schematic.getBlockState(x, y, z);
if (state != null && state.getBlock() == Blocks.REDSTONE_WIRE) {
int power = state.get(RedstoneWireBlock.POWER);
schematic.setBlockState(x, y, z, getPlacementState(schematic, new BlockPos(x, y, z)).with(RedstoneWireBlock.POWER, power));
}
}
}
}
}
public static BlockState getPlacementState(BlockView world, BlockPos pos) {
return Blocks.REDSTONE_WIRE.getDefaultState()
.with(RedstoneWireBlock.WIRE_CONNECTION_WEST, getRenderConnectionType(world, pos, Direction.WEST))
.with(RedstoneWireBlock.WIRE_CONNECTION_EAST, getRenderConnectionType(world, pos, Direction.EAST))
.with(RedstoneWireBlock.WIRE_CONNECTION_NORTH, getRenderConnectionType(world, pos, Direction.NORTH))
.with(RedstoneWireBlock.WIRE_CONNECTION_SOUTH, getRenderConnectionType(world, pos, Direction.SOUTH));
}
private static WireConnection getRenderConnectionType(BlockView world, BlockPos pos, Direction direction) {
return ((RedstoneWireBlockAccessor) Blocks.REDSTONE_WIRE).invokeGetRenderConnectionType(world, pos, direction);
}
}

View file

@ -59,9 +59,11 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
}
}
}
for (int x = 0; x < width; x++) {
for (int z = 0; z < length; z++) {
this.biomeContainer.put(new BlockPos(x, 0, z), this.biomePalette.inverse().get(this.biomeData[x][z]));
if (hasBiomes()) {
for (int x = 0; x < width; x++) {
for (int z = 0; z < length; z++) {
this.biomeContainer.put(new BlockPos(x, 0, z), this.biomePalette.inverse().get(this.biomeData[x][z]));
}
}
}
for (CompoundTag blockEntityTag : schematic.getBlockEntities()) {
@ -103,7 +105,13 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
BlockPos pos = entry.getKey();
BlockPos actualPos = origin.add(entry.getKey());
BlockEntity blockEntity = BlockEntity.createFromTag(this.getBlockState(pos), entry.getValue());
CompoundTag tag = entry.getValue();
if(tag.contains("Id")) {
tag.put("id", tag.get("Id")); // boogers
tag.remove("Id");
}
BlockEntity blockEntity = BlockEntity.createFromTag(this.getBlockState(pos), tag);
if (blockEntity != null) {
world.toServerWorld().setBlockEntity(actualPos, blockEntity);
}
@ -152,4 +160,8 @@ public class RelativeBlockSample implements BlockView, ModifiableWorld {
public boolean breakBlock(BlockPos pos, boolean drop, @Nullable Entity breakingEntity, int maxUpdateDepth) {
return this.setBlockState(pos, Blocks.AIR.getDefaultState(), 2);
}
public boolean hasBiomes() {
return biomeData.length != 0;
}
}

View file

@ -55,6 +55,7 @@ public final class SchematicPlacer {
int width = schematic.getWidth();
int length = schematic.getLength();
byte[] biomeDataArray = schematic.getBiomeData().array();
if (biomeDataArray.length == 0) return new int[0][0];
int[][] biomeData = new int[width][length];
for (int x = 0; x < width; x++) {
for (int z = 0; z < length; z++) {