PocketAddon rework

pockets now generate in center of assigned grid
This commit is contained in:
CreepyCre 2021-02-19 21:39:27 +01:00
parent 875bef25b6
commit 053dbb4f42
44 changed files with 1302 additions and 344 deletions

View file

@ -1,15 +1,13 @@
package org.dimdev.dimdoors;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
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.ClientPacketHandler;
import org.dimdev.dimdoors.network.ExtendedClientPlayNetworkHandler;
import org.dimdev.dimdoors.particle.ModParticleTypes;
import net.fabricmc.api.ClientModInitializer;
@ -19,9 +17,6 @@ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
@Environment(EnvType.CLIENT)
public class DimensionalDoorsClientInitializer implements ClientModInitializer {
private static ClientPacketHandler clientPacketHandler;
private static final Logger LOGGER = LogManager.getLogger();
@Override
public void onInitializeClient() {
ModEntityTypes.initClient();
@ -37,11 +32,10 @@ public class DimensionalDoorsClientInitializer implements ClientModInitializer {
}
private void registerListeners() {
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> clientPacketHandler = new ClientPacketHandler(handler, client));
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> ((ExtendedClientPlayNetworkHandler) handler).getDimDoorsPacketHandler().init());
ClientPlayConnectionEvents.DISCONNECT.register(((handler, client) -> {
clientPacketHandler.unregister();
clientPacketHandler = null;
((ExtendedClientPlayNetworkHandler) handler).getDimDoorsPacketHandler().unregister();
}));
}
}

View file

@ -1,25 +1,25 @@
package org.dimdev.dimdoors;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
import me.sargunvohra.mcmods.autoconfig1u.ConfigHolder;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import me.sargunvohra.mcmods.autoconfig1u.serializer.JanksonConfigSerializer;
import net.minecraft.util.math.Vec3i;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.block.entity.ModBlockEntityTypes;
import org.dimdev.dimdoors.command.ModCommands;
import org.dimdev.dimdoors.entity.ModEntityTypes;
import org.dimdev.dimdoors.entity.stat.ModStats;
import org.dimdev.dimdoors.event.UseItemOnBlockCallback;
import org.dimdev.dimdoors.fluid.ModFluids;
import org.dimdev.dimdoors.item.ModItems;
import org.dimdev.dimdoors.listener.AttackBlockCallbackListener;
import org.dimdev.dimdoors.network.ServerPacketHandler;
import org.dimdev.dimdoors.listener.pocket.*;
import org.dimdev.dimdoors.network.ExtendedServerPlayNetworkHandler;
import org.dimdev.dimdoors.particle.ModParticleTypes;
import org.dimdev.dimdoors.pockets.SchematicHandler;
import org.dimdev.dimdoors.pockets.SchematicV2Handler;
@ -32,9 +32,8 @@ import org.dimdev.dimdoors.sound.ModSoundEvents;
import org.dimdev.dimdoors.world.ModBiomes;
import org.dimdev.dimdoors.world.ModDimensions;
import org.dimdev.dimdoors.world.feature.ModFeatures;
import org.dimdev.dimdoors.world.pocket.PocketDirectory;
import org.dimdev.dimdoors.world.pocket.type.AbstractPocket;
import org.dimdev.dimdoors.world.pocket.type.Pocket;
import org.dimdev.dimdoors.world.pocket.type.addon.PocketAddon;
import org.jetbrains.annotations.NotNull;
import net.minecraft.server.MinecraftServer;
@ -49,7 +48,6 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
public class DimensionalDoorsInitializer implements ModInitializer {
public static final Identifier MONOLITH_PARTICLE_PACKET = new Identifier("dimdoors", "monolith_particle_packet");
public static final ConfigHolder<ModConfig> CONFIG_MANAGER = AutoConfig.register(ModConfig.class, JanksonConfigSerializer::new);
private static final Map<UUID, ServerPacketHandler> UUID_SERVER_PACKET_HANDLER_MAP = new HashMap<>();
private static MinecraftServer server;
@NotNull
@ -93,60 +91,31 @@ public class DimensionalDoorsInitializer implements ModInitializer {
Modifier.ModifierType.register();
PocketGenerator.PocketGeneratorType.register();
AbstractPocket.AbstractPocketType.register();
PocketAddon.PocketAddonType.register();
SchematicV2Handler.getInstance().load();
SchematicHandler.INSTANCE.loadSchematics();
registerListeners();
//newPocketTest();
}
private void registerListeners() {
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
UUID_SERVER_PACKET_HANDLER_MAP.put(handler.player.getUuid(), new ServerPacketHandler(handler, server));
((ExtendedServerPlayNetworkHandler) handler).getDimDoorsPacketHandler().init();
});
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
UUID_SERVER_PACKET_HANDLER_MAP.remove(handler.player.getUuid()).unregister();
((ExtendedServerPlayNetworkHandler) handler).getDimDoorsPacketHandler().unregister();
});
AttackBlockCallback.EVENT.register(new AttackBlockCallbackListener());
AttackBlockCallback.EVENT.register(new PocketAttackBlockCallbackListener());
PlayerBlockBreakEvents.BEFORE.register(new PlayerBlockBreakEventBeforeListener());
UseItemCallback.EVENT.register(new UseItemCallbackListener());
UseItemOnBlockCallback.EVENT.register(new UseItemOnBlockCallbackListener());
UseBlockCallback.EVENT.register(new UseBlockCallbackListener());
}
/*
void newPocketTest() {
PocketDirectory directory = new PocketDirectory(ModDimensions.DUNGEON, 512);
Pocket.PocketBuilder<?, ?> builder = Pocket.builder().expand(new Vec3i(1, 1, 1));
System.out.println(0 + ", " + directory.newPocket(builder).getId());
System.out.println(1 + ", " + directory.newPocket(builder).getId());
System.out.println(2 + ", " + directory.newPocket(builder).getId());
System.out.println(3 + ", " + directory.newPocket(builder).getId());
System.out.println(4 + ", " + directory.newPocket(builder).getId());
System.out.println(5 + ", " + directory.newPocket(builder).getId());
System.out.println(6 + ", " + directory.newPocket(builder).getId());
builder = Pocket.builder().expand(new Vec3i(directory.getGridSize() + 1, directory.getGridSize() + 1, directory.getGridSize() + 1));
System.out.println(9 + ", " + directory.newPocket(builder).getId());
System.out.println(18 + ", " + directory.newPocket(builder).getId());
builder = Pocket.builder().expand(new Vec3i(3 * directory.getGridSize() + 1, 3 * directory.getGridSize() + 1, 3 * directory.getGridSize() + 1));
System.out.println(81 + ", " + directory.newPocket(builder).getId());
builder = Pocket.builder().expand(new Vec3i(directory.getGridSize() + 1, directory.getGridSize() + 1, directory.getGridSize() + 1));
System.out.println(27 + ", " + directory.newPocket(builder).getId());
builder = Pocket.builder().expand(new Vec3i(1, 1, 1));
System.out.println(7 + ", " + directory.newPocket(builder).getId());
System.out.println(8 + ", " + directory.newPocket(builder).getId());
System.out.println(36 + ", " + directory.newPocket(builder).getId());
}
*/
}

View file

@ -23,28 +23,12 @@ public class FabricBlock extends Block {
}
@Override
@SuppressWarnings({"deprecation"})
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
ItemStack heldStack = hand == Hand.MAIN_HAND ? player.getMainHandStack() : player.getOffHandStack();
Block heldBlock = Block.getBlockFromItem(heldStack.getItem());
public boolean canReplace(BlockState state, ItemPlacementContext context) {
if (context.getPlayer().isSneaking()) return false;
Block heldBlock = Block.getBlockFromItem(context.getPlayer().getStackInHand(context.getHand()).getItem());
if (!heldBlock.getDefaultState().isFullCube(context.getWorld(), context.getBlockPos())) return false;
if (heldBlock instanceof BlockEntityProvider || heldBlock instanceof FabricBlock) return false;
if (world.canPlayerModifyAt(player, pos) &&
player.canPlaceOn(pos, hit.getSide(), heldStack) &&
heldBlock.getDefaultState().isFullCube(world, pos) &&
!(heldBlock instanceof BlockEntityProvider) &&
heldBlock != this &&
!player.isSneaking() &&
!(heldBlock instanceof FabricBlock)
) {
if (!player.isCreative()) {
heldStack.decrement(1);
}
world.setBlockState(pos, heldBlock.getPlacementState(new ItemPlacementContext(new ItemUsageContext(player, hand, hit))));
return ActionResult.SUCCESS;
} else {
return ActionResult.PASS;
}
return true;
}
}

View file

@ -0,0 +1,27 @@
package org.dimdev.dimdoors.event;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
public interface UseItemOnBlockCallback {
Event<UseItemOnBlockCallback> EVENT = EventFactory.createArrayBacked(UseItemOnBlockCallback.class,
listeners -> (player, world, hand, hitresult) -> {
for (UseItemOnBlockCallback event : listeners) {
ActionResult result = event.useItemOnBlock(player, world, hand, hitresult);
if (result != ActionResult.PASS) {
return result;
}
}
return ActionResult.PASS;
}
);
ActionResult useItemOnBlock(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult);
}

View file

@ -6,6 +6,7 @@ import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.block.entity.RiftBlockEntity;
import org.dimdev.dimdoors.network.ServerPacketHandler;
import org.dimdev.dimdoors.network.s2c.PlayerInventorySlotUpdateS2CPacket;
import org.dimdev.dimdoors.rift.targets.IdMarker;
import org.dimdev.dimdoors.util.EntityUtils;
@ -119,18 +120,11 @@ public class RiftConfigurationToolItem extends ModItem {
// TODO: put in ServerPacketHandler
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);
ServerPacketHandler.sendPacket(serverPlayer, new PlayerInventorySlotUpdateS2CPacket(45, stack));
} else {
packet = new PlayerInventorySlotUpdateS2CPacket(serverPlayer.getInventory().selectedSlot, stack);
}
PacketByteBuf buf = PacketByteBufs.create();
try {
packet.write(buf);
ServerPlayNetworking.send(serverPlayer, PlayerInventorySlotUpdateS2CPacket.ID, buf);
} catch (IOException e) {
LOGGER.error(e);
ServerPacketHandler.sendPacket(serverPlayer, new PlayerInventorySlotUpdateS2CPacket(serverPlayer.getInventory().selectedSlot, stack));
}
}
}

View file

@ -1,8 +1,6 @@
package org.dimdev.dimdoors.listener;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.util.ActionResult;
@ -11,15 +9,11 @@ import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.item.ModItem;
import org.dimdev.dimdoors.network.ClientPacketHandler;
import org.dimdev.dimdoors.network.c2s.HitBlockWithItemC2SPacket;
import java.io.IOException;
public class AttackBlockCallbackListener implements AttackBlockCallback {
private static final Logger LOGGER = LogManager.getLogger();
@Override
public ActionResult interact(PlayerEntity player, World world, Hand hand, BlockPos pos, Direction direction) {
@ -30,11 +24,7 @@ public class AttackBlockCallbackListener implements AttackBlockCallback {
}
TypedActionResult<Boolean> result = ((ModItem) item).onAttackBlock(world, player, hand, pos, direction);
if (result.getValue()) {
try {
ClientPlayNetworking.send(HitBlockWithItemC2SPacket.ID,
new HitBlockWithItemC2SPacket(hand, pos, direction).write(PacketByteBufs.create()));
} catch (IOException e) {
LOGGER.error(e);
if (!ClientPacketHandler.sendPacket(new HitBlockWithItemC2SPacket(hand, pos, direction))) {
return ActionResult.FAIL;
}
}

View file

@ -0,0 +1,24 @@
package org.dimdev.dimdoors.listener.pocket;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.List;
public class PlayerBlockBreakEventBeforeListener implements PlayerBlockBreakEvents.Before {
@Override
public boolean beforeBlockBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, BlockEntity blockEntity) {
List<PlayerBlockBreakEvents.Before> applicableAddons;
if (world.isClient) applicableAddons = PocketListenerUtil.applicableAddonsClient(PlayerBlockBreakEvents.Before.class, world, player.getBlockPos());
else applicableAddons = PocketListenerUtil.applicableAddons(PlayerBlockBreakEvents.Before.class, world, player.getBlockPos());
for (PlayerBlockBreakEvents.Before listener : applicableAddons) {
if (!listener.beforeBlockBreak(world, player, pos, state, blockEntity)) return false;
}
return true;
}
}

View file

@ -0,0 +1,27 @@
package org.dimdev.dimdoors.listener.pocket;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import java.util.List;
public class PocketAttackBlockCallbackListener implements AttackBlockCallback {
@Override
public ActionResult interact(PlayerEntity player, World world, Hand hand, BlockPos pos, Direction direction) {
List<AttackBlockCallback> applicableAddons;
if (world.isClient) applicableAddons = PocketListenerUtil.applicableAddonsClient(AttackBlockCallback.class, world, pos);
else applicableAddons = PocketListenerUtil.applicableAddons(AttackBlockCallback.class, world, pos);
ActionResult result;
for (AttackBlockCallback listener : applicableAddons) {
result = listener.interact(player, world, hand, pos, direction);
if (result != ActionResult.PASS) return result;
}
return ActionResult.PASS;
}
}

View file

@ -0,0 +1,40 @@
package org.dimdev.dimdoors.listener.pocket;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.dimdev.dimdoors.network.ClientPacketHandler;
import org.dimdev.dimdoors.network.ExtendedClientPlayNetworkHandler;
import org.dimdev.dimdoors.util.math.GridUtil;
import org.dimdev.dimdoors.world.ModDimensions;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.world.pocket.type.Pocket;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class PocketListenerUtil {
public static <T> List<T> applicableAddons(Class<T> clazz, World world, BlockPos pos) {
if (world.isClient) throw new UnsupportedOperationException("Cannot call this method on the Client.");
if (!ModDimensions.isPocketDimension(world)) return Collections.emptyList();
Pocket pocket = DimensionalRegistry.getPocketDirectory(world.getRegistryKey()).getPocketAt(pos);
if (pocket == null) return Collections.emptyList();;
return pocket.getAddonsInstanceOf(clazz);
}
@Environment(EnvType.CLIENT)
public static <T> List<T> applicableAddonsClient(Class<T> clazz, World world, BlockPos pos) {
ClientPacketHandler packetHandler = ((ExtendedClientPlayNetworkHandler) MinecraftClient.getInstance().getNetworkHandler()).getDimDoorsPacketHandler();
if (!world.getRegistryKey().equals(packetHandler.getPocketWorld())) return Collections.emptyList();
int pocketId = GridUtil.gridPosToID(new GridUtil.GridPos(pos, packetHandler.getGridSize()));
if (pocketId < packetHandler.getPocketId() || pocketId >= packetHandler.getPocketId() + packetHandler.getPocketRange()) {
return Collections.emptyList();
}
return packetHandler.getAddons().stream().filter(clazz::isInstance).map(clazz::cast).collect(Collectors.toList());
}
}

View file

@ -0,0 +1,25 @@
package org.dimdev.dimdoors.listener.pocket;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import java.util.List;
public class UseBlockCallbackListener implements UseBlockCallback {
@Override
public ActionResult interact(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) {
List<UseBlockCallback> applicableAddons;
if (world.isClient) applicableAddons = PocketListenerUtil.applicableAddonsClient(UseBlockCallback.class, world, player.getBlockPos());
else applicableAddons = PocketListenerUtil.applicableAddons(UseBlockCallback.class, world, player.getBlockPos());
for (UseBlockCallback listener : applicableAddons) {
ActionResult result = listener.interact(player, world, hand, hitResult);
if (result != ActionResult.PASS) return result;
}
return ActionResult.PASS;
}
}

View file

@ -0,0 +1,26 @@
package org.dimdev.dimdoors.listener.pocket;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
import java.util.List;
public class UseItemCallbackListener implements UseItemCallback {
@Override
public TypedActionResult<ItemStack> interact(PlayerEntity player, World world, Hand hand) {
List<UseItemCallback> applicableAddons;
if (world.isClient) applicableAddons = PocketListenerUtil.applicableAddonsClient(UseItemCallback.class, world, player.getBlockPos());
else applicableAddons = PocketListenerUtil.applicableAddons(UseItemCallback.class, world, player.getBlockPos());
for (UseItemCallback listener : applicableAddons) {
TypedActionResult<ItemStack> result = listener.interact(player, world, hand);
if (result.getResult() != ActionResult.PASS) return result;
}
return TypedActionResult.pass(player.getStackInHand(hand));
}
}

View file

@ -0,0 +1,25 @@
package org.dimdev.dimdoors.listener.pocket;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import org.dimdev.dimdoors.event.UseItemOnBlockCallback;
import java.util.List;
public class UseItemOnBlockCallbackListener implements UseItemOnBlockCallback {
@Override
public ActionResult useItemOnBlock(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) {
List<UseItemOnBlockCallback> applicableAddons;
if (world.isClient) applicableAddons = PocketListenerUtil.applicableAddonsClient(UseItemOnBlockCallback.class, world, player.getBlockPos());
else applicableAddons = PocketListenerUtil.applicableAddons(UseItemOnBlockCallback.class, world, player.getBlockPos());
for (UseItemOnBlockCallback listener : applicableAddons) {
ActionResult result = listener.useItemOnBlock(player, world, hand, hitResult);
if (result != ActionResult.PASS) return result;
}
return ActionResult.PASS;
}
}

View file

@ -0,0 +1,26 @@
package org.dimdev.dimdoors.mixin;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import org.dimdev.dimdoors.network.ExtendedServerPlayNetworkHandler;
import org.dimdev.dimdoors.network.ServerPacketHandler;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ServerPlayNetworkHandler.class)
public class ExtendedServerPlayNetworkhandlerMixin implements ExtendedServerPlayNetworkHandler {
@Final @Shadow
private MinecraftServer server;
private final ServerPacketHandler dimdoorsServerPacketHandler = new ServerPacketHandler((ServerPlayNetworkHandler) (Object) this);
@Override
public ServerPacketHandler getDimDoorsPacketHandler() {
return dimdoorsServerPacketHandler;
}
@Override
public MinecraftServer dimdoorsGetServer() {
return server;
}
}

View file

@ -0,0 +1,28 @@
package org.dimdev.dimdoors.mixin;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.world.World;
import org.dimdev.dimdoors.event.UseItemOnBlockCallback;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ServerPlayerInteractionManager.class)
public class ServerPlayerInteractionManagerMixin {
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerInteractionManager;isCreative()Z", ordinal = 0), method = "interactBlock", cancellable = true)
public void useItemOnBlock(ServerPlayerEntity player, World world, ItemStack stack, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable<ActionResult> info) {
ActionResult result = UseItemOnBlockCallback.EVENT.invoker().useItemOnBlock(player, world, hand, hitResult);
if (result != ActionResult.PASS) {
info.setReturnValue(result);
info.cancel();
}
}
}

View file

@ -0,0 +1,26 @@
package org.dimdev.dimdoors.mixin.client;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.network.ClientPlayerInteractionManager;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import org.dimdev.dimdoors.event.UseItemOnBlockCallback;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ClientPlayerInteractionManager.class)
public class ClientPlayerInteractionManagerMixin {
@Inject(method = "interactBlock", cancellable = true, at = @At(value = "INVOKE", ordinal = 2, target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/Packet;)V"))
public void useItemOnBlock(ClientPlayerEntity player, ClientWorld world, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable<ActionResult> info) {
ActionResult result = UseItemOnBlockCallback.EVENT.invoker().useItemOnBlock(player, world, hand, hitResult);
if (result != ActionResult.PASS) {
info.setReturnValue(result);
info.cancel();
}
}
}

View file

@ -0,0 +1,30 @@
package org.dimdev.dimdoors.mixin.client;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import org.dimdev.dimdoors.network.ClientPacketHandler;
import org.dimdev.dimdoors.network.ExtendedClientPlayNetworkHandler;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@Environment(EnvType.CLIENT)
@Mixin(ClientPlayNetworkHandler.class)
public class ExtendedClientPlayNetworkHandlerMixin implements ExtendedClientPlayNetworkHandler {
@Final @Shadow
private MinecraftClient client;
private final ClientPacketHandler dimdoors_PacketHandler = new ClientPacketHandler((ClientPlayNetworkHandler) (Object) this);
@Unique
public ClientPacketHandler getDimDoorsPacketHandler() {
return dimdoors_PacketHandler;
}
@Unique
public MinecraftClient dimdoorsGetClient() {
return client;
}
}

View file

@ -3,18 +3,27 @@ package org.dimdev.dimdoors.network;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.network.c2s.NetworkHandlerInitializedC2SPacket;
import org.dimdev.dimdoors.network.s2c.PlayerInventorySlotUpdateS2CPacket;
import org.dimdev.dimdoors.network.s2c.SyncPocketAddonsS2CPacket;
import org.dimdev.dimdoors.world.pocket.type.addon.AutoSyncedAddon;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
@ -24,17 +33,38 @@ public class ClientPacketHandler {
private final ClientPlayNetworkHandler networkHandler;
private final MinecraftClient client;
private boolean initialized = false;
private final Set<Identifier> registeredChannels = new HashSet<>();
private void registerModReceivers() {
private RegistryKey<World> pocketWorld;
private int gridSize = 1;
private int pocketId = Integer.MIN_VALUE;
private int pocketRange = 1;
private List<AutoSyncedAddon> addons = new ArrayList<>();
public void init() {
if (initialized) throw new RuntimeException("ClientPacketHandler has already been initialized.");
initialized = true;
registerReceiver(PlayerInventorySlotUpdateS2CPacket.ID, PlayerInventorySlotUpdateS2CPacket::new);
registerReceiver(SyncPocketAddonsS2CPacket.ID, SyncPocketAddonsS2CPacket::new);
sendPacket(new NetworkHandlerInitializedC2SPacket());
}
public ClientPacketHandler(ClientPlayNetworkHandler networkHandler, MinecraftClient client) {
public static boolean sendPacket(SimplePacket<?> packet) {
try {
ClientPlayNetworking.send(packet.channelId(), packet.write(PacketByteBufs.create()));
return true;
} catch (IOException e) {
LOGGER.error(e);
return false;
}
}
public ClientPacketHandler(ClientPlayNetworkHandler networkHandler) {
this.networkHandler = networkHandler;
this.client = client;
registerModReceivers();
this.client = ((ExtendedClientPlayNetworkHandler) networkHandler).dimdoorsGetClient();
}
private void registerReceiver(Identifier channelName, Supplier<? extends SimplePacket<ClientPacketHandler>> supplier) {
@ -58,10 +88,37 @@ public class ClientPacketHandler {
new HashSet<>(registeredChannels).forEach(this::unregisterReceiver);
}
public void onSyncPocketAddons(RegistryKey<World> world, int gridSize, int pocketId, int pocketRange, List<AutoSyncedAddon> addons) {
this.pocketWorld = world;
this.gridSize = gridSize;
this.pocketId = pocketId;
this.pocketRange = pocketRange;
this.addons = addons;
}
public void onPlayerInventorySlotUpdate(int slot, ItemStack stack) {
if (client.player != null) {
this.client.player.getInventory().setStack(slot, stack);
client.player.getInventory().setStack(slot, stack);
}
}
public RegistryKey<World> getPocketWorld() {
return pocketWorld;
}
public int getGridSize() {
return gridSize;
}
public int getPocketId() {
return pocketId;
}
public int getPocketRange() {
return pocketRange;
}
public List<AutoSyncedAddon> getAddons() {
return addons;
}
}

View file

@ -0,0 +1,12 @@
package org.dimdev.dimdoors.network;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
@Environment(EnvType.CLIENT)
public interface ExtendedClientPlayNetworkHandler {
ClientPacketHandler getDimDoorsPacketHandler();
MinecraftClient dimdoorsGetClient();
}

View file

@ -0,0 +1,9 @@
package org.dimdev.dimdoors.network;
import net.minecraft.server.MinecraftServer;
public interface ExtendedServerPlayNetworkHandler {
ServerPacketHandler getDimDoorsPacketHandler();
MinecraftServer dimdoorsGetServer();
}

View file

@ -1,5 +1,6 @@
package org.dimdev.dimdoors.network;
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.item.Item;
@ -11,14 +12,22 @@ import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.item.ModItem;
import org.dimdev.dimdoors.network.c2s.HitBlockWithItemC2SPacket;
import org.dimdev.dimdoors.network.c2s.NetworkHandlerInitializedC2SPacket;
import org.dimdev.dimdoors.network.s2c.SyncPocketAddonsS2CPacket;
import org.dimdev.dimdoors.world.ModDimensions;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import org.dimdev.dimdoors.world.pocket.PocketDirectory;
import org.dimdev.dimdoors.world.pocket.type.Pocket;
import org.dimdev.dimdoors.world.pocket.type.addon.AutoSyncedAddon;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
import java.util.function.Supplier;
// each client has their own corresponding ServerPacketHandler, so feel free to add client specific data in here
@ -28,16 +37,32 @@ public class ServerPacketHandler {
private final ServerPlayNetworkHandler networkHandler;
private final MinecraftServer server;
private final Set<Identifier> registeredChannels = new HashSet<>();
private boolean initialized = false;
private void registerModReceivers() {
private RegistryKey<World> lastSyncedPocketWorld;
private int lastSyncedPocketId = Integer.MIN_VALUE;
private boolean pocketSyncDirty = true;
public void init() {
if (initialized) throw new RuntimeException("ServerPacketHandler has already been initialized.");
initialized = true;
registerReceiver(NetworkHandlerInitializedC2SPacket.ID, NetworkHandlerInitializedC2SPacket::new);
registerReceiver(HitBlockWithItemC2SPacket.ID, HitBlockWithItemC2SPacket::new);
}
public static boolean sendPacket(ServerPlayerEntity player, SimplePacket<?> packet) {
try {
ServerPlayNetworking.send(player, packet.channelId(), packet.write(PacketByteBufs.create()));
return true;
} catch (IOException e) {
LOGGER.error(e);
return false;
}
}
public ServerPacketHandler(ServerPlayNetworkHandler networkHandler, MinecraftServer server) {
public ServerPacketHandler(ServerPlayNetworkHandler networkHandler) {
this.networkHandler = networkHandler;
this.server = server;
registerModReceivers();
this.server = ((ExtendedServerPlayNetworkHandler) networkHandler).dimdoorsGetServer();
}
private void registerReceiver(Identifier channelName, Supplier<? extends SimplePacket<ServerPacketHandler>> supplier) {
@ -73,4 +98,26 @@ public class ServerPacketHandler {
}
});
}
public void onNetworkHandlerInitialized() {
syncPocketAddonsIfNeeded(getPlayer().world, getPlayer().getBlockPos());
}
// TODO: attach this to some event to detect other kinds teleportation
public void syncPocketAddonsIfNeeded(World world, BlockPos pos) {
if (!ModDimensions.isPocketDimension(world)) return;
PocketDirectory directory = DimensionalRegistry.getPocketDirectory(world.getRegistryKey());
Pocket pocket = directory.getPocketAt(pos);
if (pocket == null) return;
if ((pocketSyncDirty || pocket.getId() != lastSyncedPocketId || !world.getRegistryKey().getValue().equals(lastSyncedPocketWorld.getValue()))) {
pocketSyncDirty = false;
lastSyncedPocketId = pocket.getId();
lastSyncedPocketWorld = world.getRegistryKey();
sendPacket(getPlayer(), new SyncPocketAddonsS2CPacket(world.getRegistryKey(), directory.getGridSize(), pocket.getId(), pocket.getRange(), pocket.getAddonsInstanceOf(AutoSyncedAddon.class)));
}
}
public void markPocketSyncDirty(int id) {
if (lastSyncedPocketId == id) pocketSyncDirty = true;
}
}

View file

@ -1,6 +1,7 @@
package org.dimdev.dimdoors.network;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
import java.io.IOException;
@ -10,4 +11,6 @@ public interface SimplePacket<T> {
PacketByteBuf write(PacketByteBuf buf) throws IOException;
void apply(T listener);
Identifier channelId();
}

View file

@ -13,7 +13,7 @@ import org.dimdev.dimdoors.network.SimplePacket;
import java.io.IOException;
public class HitBlockWithItemC2SPacket implements SimplePacket<ServerPacketHandler> {
public static final Identifier ID = new Identifier("dimdoors:hit_block");
public static final Identifier ID = new Identifier("dimdoors", "hit_block_with_item");
private Hand hand;
private BlockPos pos;
@ -49,4 +49,9 @@ public class HitBlockWithItemC2SPacket implements SimplePacket<ServerPacketHandl
public void apply(ServerPacketHandler listener) {
listener.onAttackBlock(hand, pos, direction);
}
@Override
public Identifier channelId() {
return ID;
}
}

View file

@ -0,0 +1,32 @@
package org.dimdev.dimdoors.network.c2s;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
import org.dimdev.dimdoors.network.ServerPacketHandler;
import org.dimdev.dimdoors.network.SimplePacket;
import java.io.IOException;
public class NetworkHandlerInitializedC2SPacket implements SimplePacket<ServerPacketHandler> {
public static final Identifier ID = new Identifier("dimdoors", "network_handler_initialized");
@Override
public SimplePacket<ServerPacketHandler> read(PacketByteBuf buf) throws IOException {
return this;
}
@Override
public PacketByteBuf write(PacketByteBuf buf) throws IOException {
return buf;
}
@Override
public void apply(ServerPacketHandler listener) {
listener.onNetworkHandlerInitialized();
}
@Override
public Identifier channelId() {
return ID;
}
}

View file

@ -44,4 +44,9 @@ public class PlayerInventorySlotUpdateS2CPacket implements SimplePacket<ClientPa
public void apply(ClientPacketHandler listener) {
listener.onPlayerInventorySlotUpdate(slot, stack);
}
@Override
public Identifier channelId() {
return ID;
}
}

View file

@ -0,0 +1,67 @@
package org.dimdev.dimdoors.network.s2c;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
import org.dimdev.dimdoors.network.ClientPacketHandler;
import org.dimdev.dimdoors.network.SimplePacket;
import org.dimdev.dimdoors.world.pocket.type.addon.AutoSyncedAddon;
import java.io.IOException;
import java.util.List;
public class SyncPocketAddonsS2CPacket implements SimplePacket<ClientPacketHandler> {
public static final Identifier ID = new Identifier("dimdoors:sync_pocket_addons");
private RegistryKey<World> world;
private int gridSize;
private int pocketId;
private int pocketRange;
private List<AutoSyncedAddon> addons;
@Environment(EnvType.CLIENT)
public SyncPocketAddonsS2CPacket() {
}
public SyncPocketAddonsS2CPacket(RegistryKey<World> world, int gridSize, int pocketId, int pocketRange, List<AutoSyncedAddon> addons) {
this.world = world;
this.gridSize = gridSize;
this.pocketId = pocketId;
this.pocketRange = pocketRange;
this.addons = addons;
}
@Override
public SimplePacket<ClientPacketHandler> read(PacketByteBuf buf) throws IOException {
this.world = RegistryKey.of(Registry.DIMENSION, buf.readIdentifier());
this.gridSize = buf.readInt();
this.pocketId = buf.readInt();
this.pocketRange = buf.readInt();
this.addons = AutoSyncedAddon.readAutoSyncedAddonList(buf);
return this;
}
@Override
public PacketByteBuf write(PacketByteBuf buf) throws IOException {
buf.writeIdentifier(world.getValue());
buf.writeInt(gridSize);
buf.writeInt(pocketId);
buf.writeInt(pocketRange);
AutoSyncedAddon.writeAutoSyncedAddonList(buf, addons);
return buf;
}
@Override
public void apply(ClientPacketHandler listener) {
listener.onSyncPocketAddons(world, gridSize, pocketId, pocketRange, addons);
}
@Override
public Identifier channelId() {
return ID;
}
}

View file

@ -41,7 +41,7 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationParame
private static final int fallbackWeight = 5; // TODO: make config
private final List<Modifier> modifierList = new ArrayList<>();
private String builderType;
private CompoundTag builderTag;
protected String weight;
protected Equation weightEquation;
protected Boolean setupLoot;
@ -84,7 +84,7 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationParame
}
public PocketGenerator fromTag(CompoundTag tag) {
if (tag.contains("builder", NbtType.STRING)) builderType = tag.getString("builder");
if (tag.contains("builder", NbtType.COMPOUND)) builderTag = tag.getCompound("builder");
this.weight = tag.contains("weight") ? tag.getString("weight") : defaultWeightEquation;
parseWeight();
@ -110,7 +110,7 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationParame
public CompoundTag toTag(CompoundTag tag) {
this.getType().toTag(tag);
if (builderType != null) tag.putString("builder", builderType);
if (builderTag != null) tag.put("builder", builderTag);
if (!weight.equals("5")) tag.putString("weight", weight);
@ -203,11 +203,11 @@ public abstract class PocketGenerator implements Weighted<PocketGenerationParame
}
public Pocket.PocketBuilder<?, ?> pocketBuilder(PocketGenerationParameters parameters) { // TODO: PocketBuilder from json
if (builderType == null){
if (builderTag == null){
return Pocket.builder()
.expand(getSize(parameters));
}
AbstractPocket.AbstractPocketBuilder<?, ?> abstractBuilder = AbstractPocket.REGISTRY.get(new Identifier(builderType)).builder();
AbstractPocket.AbstractPocketBuilder<?, ?> abstractBuilder = AbstractPocket.deserializeBuilder(builderTag);
if (! (abstractBuilder instanceof Pocket.PocketBuilder)) {
return Pocket.builder()
.expand(getSize(parameters));

View file

@ -1,9 +1,11 @@
package org.dimdev.dimdoors.pockets.virtual.reference;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.fabricmc.fabric.api.util.NbtType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
@ -27,6 +29,7 @@ public abstract class PocketGeneratorReference extends VirtualSingularPocket {
protected Equation weightEquation;
protected Boolean setupLoot;
protected final List<Modifier> modifierList = Lists.newArrayList();
protected final List<CompoundTag> addons = new ArrayList<>();
private void parseWeight() {
try {
@ -58,7 +61,14 @@ public abstract class PocketGeneratorReference extends VirtualSingularPocket {
}
}
return null;
if (tag.contains("addons", NbtType.LIST)) {
ListTag modifiersTag = tag.getList("addons", 10);
for (int i = 0; i < modifiersTag.size(); i++) {
addons.add(modifiersTag.getCompound(i));
}
}
return this;
}
@Override
@ -75,6 +85,10 @@ public abstract class PocketGeneratorReference extends VirtualSingularPocket {
}
if (modifiersTag.size() > 0) tag.put("modifiers", modifiersTag);
ListTag addonsTag = new ListTag();
addonsTag.addAll(addons);
if (addonsTag.size() > 0) tag.put("addons", addonsTag);
return tag;
}

View file

@ -20,6 +20,7 @@ import net.minecraft.entity.ItemEntity;
import net.minecraft.item.DyeItem;
import net.minecraft.item.Item;
import org.dimdev.dimdoors.world.pocket.type.PrivatePocket;
import org.dimdev.dimdoors.world.pocket.type.addon.DyeableAddon;
public class PrivatePocketTarget extends VirtualTarget implements EntityTarget {
private static final Logger LOGGER = LogManager.getLogger();

View file

@ -14,6 +14,8 @@ import net.minecraft.world.TeleportTarget;
import net.minecraft.world.World;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensions;
import org.dimdev.dimdoors.network.ExtendedServerPlayNetworkHandler;
import org.dimdev.dimdoors.network.ServerPacketHandler;
@SuppressWarnings("deprecation")
public final class TeleportUtil {
@ -50,11 +52,15 @@ public final class TeleportUtil {
entity.pitch = angle.getPitch();
entity.teleport(pos.x, pos.y, pos.z);
entity.setVelocity(velocity);
return entity;
} else {
entity = FabricDimensions.teleport(entity, (ServerWorld) world, new TeleportTarget(pos, velocity, angle.getYaw(), angle.getPitch()));
}
return FabricDimensions.teleport(entity, (ServerWorld) world, new TeleportTarget(pos, velocity, angle.getYaw(), angle.getPitch()));
if (entity instanceof ServerPlayerEntity) {
((ExtendedServerPlayNetworkHandler) ((ServerPlayerEntity) entity).networkHandler).getDimDoorsPacketHandler().syncPocketAddonsIfNeeded(world, new BlockPos(pos));
}
return entity;
}
public static <E extends Entity> E teleport(E entity, World world, BlockPos pos, EulerAngle angle, Vec3d velocity) {

View file

@ -1,5 +1,7 @@
package org.dimdev.dimdoors.util.math;
import net.minecraft.util.math.BlockPos;
import java.util.Arrays;
import java.util.Vector;
@ -13,6 +15,11 @@ public final class GridUtil {
this.z = z;
}
public GridPos(BlockPos pos, int gridSize) {
this.x = pos.getX() / gridSize / 16;
this.z = pos.getZ() / gridSize / 16;
}
@Override
public boolean equals(Object o) {
if (o == this) return true;

View file

@ -106,7 +106,8 @@ public class PocketDirectory {
T pocket = builder
.id(cursor)
.world(worldKey)
.offsetOrigin(idToPos(cursor))
.range(squaredSize)
.offsetOrigin(idToCenteredPos(cursor, base3Size, builder.getExpectedSize()))
.build();
nextIDMap.put(base3Size, cursor + squaredSize);
@ -120,7 +121,6 @@ public class PocketDirectory {
.referencedId(cursor)
.build());
}
return pocket;
}
@ -169,6 +169,12 @@ public class PocketDirectory {
return new BlockPos(pos.x * this.gridSize * 16, 0, pos.z * this.gridSize * 16);
}
public BlockPos idToCenteredPos(int id, int base3Size, Vec3i expectedSize) {
GridUtil.GridPos pos = this.idToGridPos(id);
// you actually need the "/ 2 * 16" here. "*8" would not work the same since it doesn't guarantee chunk alignment
return new BlockPos((pos.x * this.gridSize * 16) + (base3Size * this.gridSize - expectedSize.getX() / 16) / 2 * 16, 0, (pos.z * this.gridSize * 16) + (base3Size * this.gridSize - expectedSize.getZ() / 16) / 2 * 16);
}
/**
* Calculates the ID of a pocket at a certain BlockPos.
*

View file

@ -36,6 +36,11 @@ public abstract class AbstractPocket<V extends AbstractPocket<V>> {
return REGISTRY.get(id).fromTag(tag);
}
public static AbstractPocketBuilder<?, ?> deserializeBuilder(CompoundTag tag) {
Identifier id = Identifier.tryParse(tag.getString("type"));
return REGISTRY.get(id).builder().fromTag(tag);
}
public static CompoundTag serialize(AbstractPocket<?> pocket) {
return pocket.toTag(new CompoundTag());
}
@ -114,12 +119,11 @@ public abstract class AbstractPocket<V extends AbstractPocket<V>> {
}
public static abstract class AbstractPocketBuilder<P extends AbstractPocketBuilder<P, T>, T extends AbstractPocket<?>> {
private final AbstractPocketType<T> type;
protected final AbstractPocketType<T> type;
private int id;
private RegistryKey<World> world;
//TODO: fromTag/ toTag for reading builders from json, in subclasses as well
protected AbstractPocketBuilder(AbstractPocketType<T> type) {
this.type = type;
}
@ -139,12 +143,36 @@ public abstract class AbstractPocket<V extends AbstractPocket<V>> {
public P id(int id) {
this.id = id;
return (P) this;
return getSelf();
}
public P world(RegistryKey<World> world) {
this.world = world;
return getSelf();
}
public P getSelf() {
return (P) this;
}
abstract public P fromTag(CompoundTag tag);
abstract public CompoundTag toTag(CompoundTag tag);
/*
public P fromTag(CompoundTag tag) {
id = tag.getInt("id");
world = RegistryKey.of(Registry.DIMENSION, new Identifier(tag.getString("world")));
return getSelf();
}
public CompoundTag toTag(CompoundTag tag) {
tag.putInt("id", id);
tag.putString("world", world.getValue().toString());
return tag;
}
*/
}
}

View file

@ -1,5 +1,6 @@
package org.dimdev.dimdoors.world.pocket.type;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.nbt.CompoundTag;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
@ -41,7 +42,7 @@ public class IdReferencePocket extends AbstractPocket<IdReferencePocket> {
}
public static class IdReferencePocketBuilder extends AbstractPocketBuilder<IdReferencePocketBuilder, IdReferencePocket> {
private int referencedId;
private int referencedId = Integer.MIN_VALUE;
protected IdReferencePocketBuilder(AbstractPocketType<IdReferencePocket> type) {
super(type);
@ -54,6 +55,18 @@ public class IdReferencePocket extends AbstractPocket<IdReferencePocket> {
return pocket;
}
@Override
public IdReferencePocketBuilder fromTag(CompoundTag tag) {
if (tag.contains("referenced_id", NbtType.INT)) referencedId = tag.getInt("referenced_id");
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
if (referencedId != Integer.MIN_VALUE) tag.putInt("referenced_id", referencedId);
return tag;
}
public IdReferencePocketBuilder referencedId(int referencedId) {
this.referencedId = referencedId;
return this;

View file

@ -1,18 +1,21 @@
package org.dimdev.dimdoors.world.pocket.type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import com.mojang.serialization.Codec;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.util.Identifier;
import org.dimdev.dimdoors.DimensionalDoorsInitializer;
import org.dimdev.dimdoors.world.level.DimensionalRegistry;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.DyeColor;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
@ -20,11 +23,14 @@ import net.minecraft.util.math.Vec3i;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
import org.dimdev.dimdoors.world.pocket.VirtualLocation;
import org.dimdev.dimdoors.world.pocket.type.addon.IHasAddon;
import org.dimdev.dimdoors.world.pocket.type.addon.PocketAddon;
public class Pocket extends AbstractPocket<Pocket> {
public class Pocket extends AbstractPocket<Pocket> implements IHasAddon {
public static String KEY = "pocket";
private final Map<Identifier, PocketAddon> addons = new HashMap<>();
private int range = -1;
public BlockBox box; // TODO: make protected
public VirtualLocation virtualLocation;
@ -39,6 +45,29 @@ public class Pocket extends AbstractPocket<Pocket> {
}
public boolean hasAddon(Identifier id) {
return addons.containsKey(id);
}
public <C extends PocketAddon> boolean addAddon(C addon) {
if (addon.applicable(this)) {
addon.addAddon(addons);
return true;
}
return false;
}
public <C extends PocketAddon> C getAddon(Identifier id) {
return (C) addons.get(id);
}
public <T> List<T> getAddonsInstanceOf(Class<T> clazz) {
return addons.values().stream()
.filter(clazz::isInstance)
.map(clazz::cast)
.collect(Collectors.toList());
}
public boolean isInBounds(BlockPos pos) {
return this.box.contains(pos);
}
@ -63,14 +92,31 @@ public class Pocket extends AbstractPocket<Pocket> {
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 void setRange(int range) {
if (this.range > 0) throw new UnsupportedOperationException("Cannot set range of Pocket that has already been initialized.");
this.range = range;
}
public int getRange() {
if (range < 1) throw new UnsupportedOperationException("Range of pocket has not been initialized yet.");
return range;
}
public Vec3i getSize() {
return this.box.getDimensions();
}
public CompoundTag toTag(CompoundTag tag) {
super.toTag(tag);
tag.putInt("range", range);
tag.putIntArray("box", IntStream.of(this.box.minX, this.box.minY, this.box.minZ, this.box.maxX, this.box.maxY, this.box.maxZ).toArray());
tag.put("virtualLocation", VirtualLocation.toTag(this.virtualLocation));
ListTag addonsTag = new ListTag();
addonsTag.addAll(addons.values().stream().map(addon -> addon.toTag(new CompoundTag())).collect(Collectors.toList()));
if (addonsTag.size() > 0) tag.put("addons", addonsTag);
return tag;
}
@ -81,71 +127,22 @@ public class Pocket extends AbstractPocket<Pocket> {
public Pocket fromTag(CompoundTag tag) {
super.fromTag(tag);
this.range = tag.getInt("range");
int[] box = tag.getIntArray("box");
this.box = new BlockBox(box[0], box[1], box[2], box[3], box[4], box[5]);
this.virtualLocation = VirtualLocation.fromTag(tag.getCompound("virtualLocation"));
if (tag.contains("addons", NbtType.LIST)) {
for (Tag addonTag : tag.getList("addons", NbtType.COMPOUND)) {
PocketAddon addon = PocketAddon.deserialize((CompoundTag) addonTag);
addons.put(addon.getId(), addon);
}
}
return this;
}
public enum PocketColor {
WHITE(0, DyeColor.WHITE),
ORANGE(1, DyeColor.ORANGE),
MAGENTA(2, DyeColor.MAGENTA),
LIGHT_BLUE(3, DyeColor.LIGHT_BLUE),
YELLOW(4, DyeColor.YELLOW),
LIME(5, DyeColor.LIME),
PINK(6, DyeColor.PINK),
GRAY(7, DyeColor.GRAY),
LIGHT_GRAY(8, DyeColor.LIGHT_GRAY),
CYAN(9, DyeColor.CYAN),
PURPLE(10, DyeColor.PURPLE),
BLUE(11, DyeColor.BLUE),
BROWN(12, DyeColor.BROWN),
GREEN(13, DyeColor.GREEN),
RED(14, DyeColor.RED),
BLACK(15, DyeColor.BLACK),
NONE(16, null);
private final int id;
private final DyeColor color;
public static Codec<PocketColor> CODEC = Codec.INT.xmap(PocketColor::from, PocketColor::getId);
PocketColor(int id, DyeColor color) {
this.id = id;
this.color = color;
}
public DyeColor getColor() {
return this.color;
}
public Integer getId() {
return this.id;
}
public static PocketColor from(DyeColor color) {
for (PocketColor a : PocketColor.values()) {
if (color == a.color) {
return a;
}
}
return NONE;
}
public static PocketColor from(int id) {
for (PocketColor a : PocketColor.values()) {
if (id == a.id) {
return a;
}
}
return NONE;
}
}
public Map<BlockPos, BlockEntity> getBlockEntities() {
ServerWorld serverWorld = DimensionalDoorsInitializer.getWorld(this.getWorld());
Map<BlockPos, BlockEntity> blockEntities = new HashMap<>();
@ -187,32 +184,57 @@ public class Pocket extends AbstractPocket<Pocket> {
// TODO: flesh this out a bit more, stuff like box() makes little sense in how it is implemented atm
public static class PocketBuilder<P extends PocketBuilder<P, T>, T extends Pocket> extends AbstractPocketBuilder<P, T> {
private final Map<Class<? extends PocketAddon.PocketBuilderAddon<?>>, PocketAddon.PocketBuilderAddon<?>> addons = new HashMap<>();
private final Map<Identifier, PocketAddon.PocketBuilderAddon<?>> addons = new HashMap<>();
private Vec3i origin = new Vec3i(0, 0, 0);
private Vec3i size = new Vec3i(0, 0, 0);
private Vec3i expected = new Vec3i(0, 0, 0);
private VirtualLocation virtualLocation;
private PocketColor dyeColor = PocketColor.NONE;
private int range = -1;
protected PocketBuilder(AbstractPocketType<T> type) {
super(type);
initAddons();
}
public <C extends PocketAddon.PocketBuilderAddon<X>, X extends PocketAddon<X>> boolean hasAddon(Class<C> addonClass) {
return addons.containsKey(addonClass);
public void initAddons() {
}
protected <C extends PocketAddon.PocketBuilderAddon<X>, X extends PocketAddon<X>> void addAddon(Class<C> addonClass, C addon) {
addons.put(addonClass, addon);
// TODO: actually utilize fromTag/ toTag methods + implement them
public P fromTag(CompoundTag tag) {
if (tag.contains("addons", NbtType.LIST)) {
for (Tag addonTag : tag.getList("addons", NbtType.COMPOUND)) {
PocketAddon.PocketBuilderAddon<?> addon = PocketAddon.deserializeBuilder((CompoundTag) addonTag);
addons.put(addon.getId(), addon);
}
}
return getSelf();
}
public <C extends PocketAddon.PocketBuilderAddon<X>, X extends PocketAddon<X>> C getAddon(Class<C> addonClass) {
return (C) addons.get(addonClass);
public CompoundTag toTag(CompoundTag tag) {
ListTag addonsTag = new ListTag();
addonsTag.addAll(addons.values().stream().map(addon -> addon.toTag(new CompoundTag())).collect(Collectors.toList()));
if (addonsTag.size() > 0) tag.put("addons", addonsTag);
return tag;
}
public P getSelf() {
return (P) this;
public boolean hasAddon(Identifier id) {
return addons.containsKey(id);
}
protected <C extends PocketAddon.PocketBuilderAddon<?>> boolean addAddon(C addon) {
if (addon.applicable(this)) {
addon.addAddon(addons);
return true;
}
return false;
}
public <C extends PocketAddon.PocketBuilderAddon<?>> C getAddon(Identifier id) {
return (C) addons.get(id);
}
@Override
@ -221,38 +243,43 @@ public class Pocket extends AbstractPocket<Pocket> {
}
public T build() {
if (range < 1) throw new RuntimeException("Cannot create pocket with range < 1");
T instance = super.build();
instance.setRange(range);
instance.box = BlockBox.create(origin.getX(), origin.getY(), origin.getZ(), origin.getX() + size.getX(), origin.getY() + size.getY(), origin.getZ() + size.getZ());
instance.virtualLocation = virtualLocation;
addons.values().forEach(addon -> addon.apply(instance));
return instance;
}
public P offsetOrigin(Vec3i offset) {
this.origin = new Vec3i(origin.getX() + offset.getX(), origin.getY() + offset.getY(), origin.getZ() + offset.getZ());
return (P) this;
return getSelf();
}
public P expand(Vec3i expander) {
this.size = new Vec3i(size.getX() + expander.getX(), size.getY() + expander.getY(), size.getZ() + expander.getZ());
this.expected = new Vec3i(expected.getX() + expander.getX(), expected.getY() + expander.getY(), expected.getZ() + expander.getZ());
return (P) this;
return getSelf();
}
public P expandExpected(Vec3i expander) {
this.expected = new Vec3i(expected.getX() + expander.getX(), expected.getY() + expander.getY(), expected.getZ() + expander.getZ());
return (P) this;
return getSelf();
}
public P virtualLocation(VirtualLocation virtualLocation) {
this.virtualLocation = virtualLocation;
return (P) this;
return getSelf();
}
public P dyeColor(PocketColor dyeColor) {
this.dyeColor = dyeColor;
return (P) this;
public P range(int range) {
this.range = range;
return getSelf();
}
}
}

View file

@ -0,0 +1,62 @@
package org.dimdev.dimdoors.world.pocket.type;
import com.mojang.serialization.Codec;
import net.minecraft.util.DyeColor;
public enum PocketColor {
WHITE(0, DyeColor.WHITE),
ORANGE(1, DyeColor.ORANGE),
MAGENTA(2, DyeColor.MAGENTA),
LIGHT_BLUE(3, DyeColor.LIGHT_BLUE),
YELLOW(4, DyeColor.YELLOW),
LIME(5, DyeColor.LIME),
PINK(6, DyeColor.PINK),
GRAY(7, DyeColor.GRAY),
LIGHT_GRAY(8, DyeColor.LIGHT_GRAY),
CYAN(9, DyeColor.CYAN),
PURPLE(10, DyeColor.PURPLE),
BLUE(11, DyeColor.BLUE),
BROWN(12, DyeColor.BROWN),
GREEN(13, DyeColor.GREEN),
RED(14, DyeColor.RED),
BLACK(15, DyeColor.BLACK),
NONE(16, null);
private final int id;
private final DyeColor color;
public static Codec<PocketColor> CODEC = Codec.INT.xmap(PocketColor::from, PocketColor::getId);
PocketColor(int id, DyeColor color) {
this.id = id;
this.color = color;
}
public DyeColor getColor() {
return this.color;
}
public Integer getId() {
return this.id;
}
public static PocketColor from(DyeColor color) {
for (PocketColor a : PocketColor.values()) {
if (color == a.color) {
return a;
}
}
return NONE;
}
public static PocketColor from(int id) {
for (PocketColor a : PocketColor.values()) {
if (id == a.id) {
return a;
}
}
return NONE;
}
}

View file

@ -1,118 +1,23 @@
package org.dimdev.dimdoors.world.pocket.type;
import net.minecraft.block.BlockState;
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.math.BlockPos;
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.util.EntityUtils;
import org.dimdev.dimdoors.world.pocket.type.addon.DyeablePocket;
import org.dimdev.dimdoors.world.pocket.type.addon.DyeableAddon;
public class PrivatePocket extends Pocket implements DyeablePocket {
public class PrivatePocket extends Pocket implements DyeableAddon.DyeablePocket {
public static String KEY = "private_pocket";
private static final int BLOCKS_PAINTED_PER_DYE = 1000000;
protected PocketColor dyeColor = PocketColor.WHITE;
private PocketColor nextDyeColor = PocketColor.NONE;
private int count = 0;
@Override
public CompoundTag toTag(CompoundTag tag) {
tag = super.toTag(tag);
tag.putInt("dyeColor", this.dyeColor.getId());
tag.putInt("nextDyeColor", this.nextDyeColor.getId());
tag.putInt("count", this.count);
return tag;
}
@Override
public Pocket fromTag(CompoundTag tag) {
super.fromTag(tag);
this.dyeColor = PocketColor.from(tag.getInt("dyeColor"));
this.nextDyeColor = PocketColor.from(tag.getInt("nextDyeColor"));
this.count = tag.getInt("count");
return this;
}
@Override
public void setDyeColor(PocketColor dyeColor) {
}
public boolean addDye(Entity entity, DyeColor dyeColor) {
PocketColor color = PocketColor.from(dyeColor);
int maxDye = amountOfDyeRequiredToColor(this);
if (this.dyeColor == color) {
EntityUtils.chat(entity, new TranslatableText("dimdoors.pockets.dyeAlreadyAbsorbed"));
return false;
}
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;
EntityUtils.chat(entity, new TranslatableText("dimdoors.pocket.pocketHasBeenDyed", dyeColor));
} else {
this.count++;
EntityUtils.chat(entity, new TranslatableText("dimdoors.pocket.remainingNeededDyes", this.count, maxDye, color));
}
} else {
this.nextDyeColor = color;
this.count = 1;
EntityUtils.chat(entity, new TranslatableText("dimdoors.pocket.remainingNeededDyes", this.count, maxDye, color));
}
return true;
}
private void repaint(DyeColor dyeColor) {
ServerWorld serverWorld = DimensionalDoorsInitializer.getWorld(getWorld());
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 Math.max((outerVolume - innerVolume) / BLOCKS_PAINTED_PER_DYE, 1);
}
public static PrivatePocketBuilder<?, PrivatePocket> builderPrivatePocket() {
return new PrivatePocketBuilder<>(AbstractPocketType.PRIVATE_POCKET);
}
public static class PrivatePocketBuilder<P extends PrivatePocketBuilder<P, T>, T extends PrivatePocket> extends PocketBuilder<P, T> implements DyeablePocketBuilder<P> {
public static class PrivatePocketBuilder<P extends PrivatePocketBuilder<P, T>, T extends PrivatePocket> extends PocketBuilder<P, T> implements DyeableAddon.DyeablePocketBuilder<P> {
protected PrivatePocketBuilder(AbstractPocketType<T> type) {
super(type);
}
@Override
public void initAddons() {
addAddon(DyeableBuilderAddon.class, new DyeableBuilderAddon());
super.initAddons();
addAddon(new DyeableAddon.DyeableBuilderAddon());
this.dyeColor(PocketColor.WHITE);
}
}

View file

@ -0,0 +1,37 @@
package org.dimdev.dimdoors.world.pocket.type.addon;
import net.minecraft.network.PacketByteBuf;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public interface AutoSyncedAddon extends PocketAddon {
static <T extends AutoSyncedAddon> List<T> readAutoSyncedAddonList(PacketByteBuf buf) throws IOException {
List<T> addons = new ArrayList<>();
int addonCount = buf.readInt();
try {
for (int i = 0; i < addonCount; i++) {
addons.add((T) ((AutoSyncedAddon) PocketAddon.REGISTRY.get(buf.readIdentifier()).instance()).read(buf));
}
} catch (NullPointerException e) {
throw new IOException(e);
}
return addons;
}
static PacketByteBuf writeAutoSyncedAddonList(PacketByteBuf buf, List<? extends AutoSyncedAddon> addons) throws IOException {
buf.writeInt(addons.size());
for (AutoSyncedAddon addon : addons) {
buf.writeIdentifier(addon.getType().identifier());
addon.write(buf);
}
return buf;
}
// you can generally use PacketByteBuf#readCompoundTag for reading
AutoSyncedAddon read(PacketByteBuf buf) throws IOException;
// you can generally use PacketByteBuf#writeCompoundTag for writing
PacketByteBuf write(PacketByteBuf buf) throws IOException;
}

View file

@ -0,0 +1,174 @@
package org.dimdev.dimdoors.world.pocket.type.addon;
import net.minecraft.block.BlockState;
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.BlockPos;
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.util.EntityUtils;
import org.dimdev.dimdoors.world.pocket.type.Pocket;
import org.dimdev.dimdoors.world.pocket.type.PocketColor;
import org.dimdev.dimdoors.world.pocket.type.PrivatePocket;
public class DyeableAddon implements PocketAddon {
public static Identifier ID = new Identifier("dimdoors", "dyeable");
private static final int BLOCKS_PAINTED_PER_DYE = 1000000;
protected PocketColor dyeColor = PocketColor.WHITE;
private PocketColor nextDyeColor = PocketColor.NONE;
private int count = 0;
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 Math.max((outerVolume - innerVolume) / BLOCKS_PAINTED_PER_DYE, 1);
}
private void repaint(Pocket pocket, DyeColor dyeColor) {
ServerWorld serverWorld = DimensionalDoorsInitializer.getWorld(pocket.getWorld());
BlockState innerWall = ModBlocks.fabricFromDye(dyeColor).getDefaultState();
BlockState outerWall = ModBlocks.ancientFabricFromDye(dyeColor).getDefaultState();
BlockPos.stream(pocket.getBox()).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);
}
});
}
public boolean addDye(Pocket pocket, Entity entity, DyeColor dyeColor) {
PocketColor color = PocketColor.from(dyeColor);
int maxDye = amountOfDyeRequiredToColor(pocket);
if (this.dyeColor == color) {
EntityUtils.chat(entity, new TranslatableText("dimdoors.pockets.dyeAlreadyAbsorbed"));
return false;
}
if (this.nextDyeColor != PocketColor.NONE && this.nextDyeColor == color) {
if (this.count + 1 > maxDye) {
repaint(pocket, dyeColor);
this.dyeColor = color;
this.nextDyeColor = PocketColor.NONE;
this.count = 0;
EntityUtils.chat(entity, new TranslatableText("dimdoors.pocket.pocketHasBeenDyed", dyeColor));
} else {
this.count++;
EntityUtils.chat(entity, new TranslatableText("dimdoors.pocket.remainingNeededDyes", this.count, maxDye, color));
}
} else {
this.nextDyeColor = color;
this.count = 1;
EntityUtils.chat(entity, new TranslatableText("dimdoors.pocket.remainingNeededDyes", this.count, maxDye, color));
}
return true;
}
@Override
public boolean applicable(Pocket pocket) {
return pocket instanceof PrivatePocket;
}
@Override
public PocketAddon fromTag(CompoundTag tag) {
this.dyeColor = PocketColor.from(tag.getInt("dyeColor"));
this.nextDyeColor = PocketColor.from(tag.getInt("nextDyeColor"));
this.count = tag.getInt("count");
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
PocketAddon.super.toTag(tag);
tag.putInt("dyeColor", this.dyeColor.getId());
tag.putInt("nextDyeColor", this.nextDyeColor.getId());
tag.putInt("count", this.count);
return tag;
}
@Override
public PocketAddonType<? extends PocketAddon> getType() {
return PocketAddonType.DYEABLE_ADDON;
}
@Override
public Identifier getId() {
return ID;
}
public interface DyeablePocketBuilder<T extends Pocket.PocketBuilder<T, ?>> extends PocketBuilderExtension<T> {
default T dyeColor(PocketColor dyeColor) {
this.<DyeableBuilderAddon>getAddon(ID).dyeColor = dyeColor;
return getSelf();
}
}
public static class DyeableBuilderAddon implements PocketBuilderAddon<DyeableAddon> {
private PocketColor dyeColor = PocketColor.NONE;
// TODO: add some Pocket#init so that we can have boolean shouldRepaintOnInit
@Override
public void apply(Pocket pocket) {
DyeableAddon addon = new DyeableAddon();
addon.dyeColor = dyeColor;
pocket.addAddon(addon);
}
@Override
public Identifier getId() {
return ID;
}
@Override
public PocketBuilderAddon<DyeableAddon> fromTag(CompoundTag tag) {
this.dyeColor = PocketColor.from(tag.getInt("dye_color"));
return this;
}
@Override
public CompoundTag toTag(CompoundTag tag) {
PocketBuilderAddon.super.toTag(tag);
tag.putInt("dye_color", dyeColor.getId());
return tag;
}
@Override
public PocketAddonType<DyeableAddon> getType() {
return PocketAddonType.DYEABLE_ADDON;
}
}
public interface DyeablePocket extends IHasAddon {
default boolean addDye(Entity entity, DyeColor dyeColor) {
ensureIsPocket();
if (!this.hasAddon(ID)) {
DyeableAddon addon = new DyeableAddon();
this.addAddon(addon);
return addon.addDye((Pocket) this, entity, dyeColor);
}
return this.<DyeableAddon>getAddon(ID).addDye((Pocket) this, entity, dyeColor);
}
}
}

View file

@ -1,30 +0,0 @@
package org.dimdev.dimdoors.world.pocket.type.addon;
import net.minecraft.entity.Entity;
import net.minecraft.util.DyeColor;
import org.dimdev.dimdoors.world.pocket.type.Pocket;
public interface DyeablePocket extends PocketAddon<DyeablePocket> {
void setDyeColor(Pocket.PocketColor dyeColor);
boolean addDye(Entity entity, DyeColor dyeColor);
interface DyeablePocketBuilder<T extends Pocket.PocketBuilder<T, ? extends DyeablePocket>> extends PocketBuilderExtension<T, DyeablePocket> {
default public T dyeColor(Pocket.PocketColor dyeColor) {
this.getAddon(DyeableBuilderAddon.class).dyeColor = dyeColor;
return getSelf();
}
}
class DyeableBuilderAddon implements PocketBuilderAddon<DyeablePocket> {
private Pocket.PocketColor dyeColor = Pocket.PocketColor.NONE;
@Override
public void apply(DyeablePocket pocket) {
pocket.setDyeColor(dyeColor);
}
}
}

View file

@ -0,0 +1,16 @@
package org.dimdev.dimdoors.world.pocket.type.addon;
import net.minecraft.util.Identifier;
import org.dimdev.dimdoors.world.pocket.type.Pocket;
public interface IHasAddon {
<C extends PocketAddon> C getAddon(Identifier id);
boolean hasAddon(Identifier id);
<C extends PocketAddon> boolean addAddon(C addon);
default void ensureIsPocket() {
if (! (this instanceof Pocket)) throw new UnsupportedOperationException("Cannot apply pocket addons to non Pocket Object.");
}
}

View file

@ -1,19 +1,131 @@
package org.dimdev.dimdoors.world.pocket.type.addon;
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.world.pocket.type.Pocket;
import org.dimdev.dimdoors.world.pocket.type.addon.blockbreak.BlockBreakContainer;
public interface PocketAddon<A extends PocketAddon<A>> {
import java.util.Map;
import java.util.function.Supplier;
interface PocketBuilderExtension<T extends Pocket.PocketBuilder<T, ?>, P extends PocketAddon<P>> {
<C extends PocketAddon.PocketBuilderAddon<P>, P extends PocketAddon<P>> C getAddon(Class<C> addonClass);
public interface PocketAddon {
Registry<PocketAddonType<? extends PocketAddon>> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry<PocketAddonType<? extends PocketAddon>>(RegistryKey.ofRegistry(new Identifier("dimdoors", "pocket_applicable_addon_type")), Lifecycle.stable())).buildAndRegister();
void initAddons();
static PocketAddon deserialize(CompoundTag tag) {
Identifier id = Identifier.tryParse(tag.getString("type")); // TODO: NONE PocketAddon type;
return REGISTRY.get(id).fromTag(tag);
}
static PocketBuilderAddon<?> deserializeBuilder(CompoundTag tag) {
Identifier id = Identifier.tryParse(tag.getString("type")); // TODO: NONE PocketAddon type;
return REGISTRY.get(id).builderAddonInstance().fromTag(tag);
}
static CompoundTag serialize(PocketAddon addon) {
return addon.toTag(new CompoundTag());
}
default boolean applicable(Pocket pocket) {
return true;
}
PocketAddon fromTag(CompoundTag tag);
default CompoundTag toTag(CompoundTag tag) {
return this.getType().toTag(tag);
}
PocketAddonType<? extends PocketAddon> getType();
Identifier getId();
default void addAddon(Map<Identifier, PocketAddon> addons) {
addons.put(getId(), this);
}
interface PocketBuilderExtension<T extends Pocket.PocketBuilder<T, ?>> {
public <C extends PocketBuilderAddon<?>> C getAddon(Identifier id);
T getSelf();
}
interface PocketBuilderAddon<T extends PocketAddon> {
default boolean applicable(Pocket.PocketBuilder<?, ?> builder) {
return true;
}
void apply(T pocket);
// makes it possible for addons themselves to control how they are added
default void addAddon(Map<Identifier, PocketBuilderAddon<?>> addons) {
addons.put(getId(), this);
}
void apply(Pocket pocket);
Identifier getId();
PocketBuilderAddon<T> fromTag(CompoundTag tag);
default CompoundTag toTag(CompoundTag tag) {
return this.getType().toTag(tag);
}
PocketAddonType<T> getType();
}
interface PocketAddonType<T extends PocketAddon> {
PocketAddonType<DyeableAddon> DYEABLE_ADDON = register(DyeableAddon.ID, DyeableAddon::new, DyeableAddon.DyeableBuilderAddon::new);
PocketAddonType<PreventBlockModificationAddon> PREVENT_BLOCK_MODIFICATION_ADDON = register(PreventBlockModificationAddon.ID, PreventBlockModificationAddon::new, PreventBlockModificationAddon.PreventBlockModificationBuilderAddon::new);
PocketAddonType<BlockBreakContainer> BLOCK_BREAK_CONTAINER = register(BlockBreakContainer.ID, BlockBreakContainer::new, null);
T fromTag(CompoundTag tag);
CompoundTag toTag(CompoundTag tag);
T instance();
PocketBuilderAddon<T> builderAddonInstance();
Identifier identifier();
static void register() {
}
static <U extends PocketAddon> PocketAddonType<U> register(Identifier id, Supplier<U> supplier, Supplier<PocketBuilderAddon<U>> addonSupplier) {
return Registry.register(REGISTRY, id, new PocketAddonType<U>() {
@Override
public U fromTag(CompoundTag tag) {
return (U) supplier.get().fromTag(tag);
}
@Override
public CompoundTag toTag(CompoundTag tag) {
tag.putString("type", id.toString());
return tag;
}
@Override
public U instance() {
return supplier.get();
}
@Override
public PocketBuilderAddon<U> builderAddonInstance() {
if (addonSupplier == null) return null;
return addonSupplier.get();
}
@Override
public Identifier identifier() {
return id;
}
});
}
}
}

View file

@ -0,0 +1,102 @@
package org.dimdev.dimdoors.world.pocket.type.addon;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import org.dimdev.dimdoors.event.UseItemOnBlockCallback;
import org.dimdev.dimdoors.world.pocket.type.Pocket;
import java.io.IOException;
public class PreventBlockModificationAddon implements AutoSyncedAddon, AttackBlockCallback, PlayerBlockBreakEvents.Before, UseItemOnBlockCallback {
public static Identifier ID = new Identifier("dimdoors", "prevent_block_modification");
//AttackBlockCallback
@Override
public ActionResult interact(PlayerEntity player, World world, Hand hand, BlockPos pos, Direction direction) {
if (player.isCreative()) return ActionResult.PASS;
return ActionResult.FAIL;
}
@Override
public boolean beforeBlockBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, BlockEntity blockEntity) {
if (player.isCreative()) return true;
return false;
}
@Override
public ActionResult useItemOnBlock(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) {
if (player.isCreative()) return ActionResult.PASS;
if (player.getStackInHand(hand).getItem() instanceof BlockItem) {
BlockPos blockPos = hitResult.getBlockPos();
BlockState blockState = world.getBlockState(blockPos);
ActionResult result = blockState.onUse(world, player, hand, hitResult);
if (result.isAccepted()) return result;
return ActionResult.FAIL;
}
return ActionResult.PASS;
}
@Override
public AutoSyncedAddon read(PacketByteBuf buf) throws IOException {
return this;
}
@Override
public PacketByteBuf write(PacketByteBuf buf) throws IOException {
return buf;
}
@Override
public PocketAddon fromTag(CompoundTag tag) {
return this;
}
@Override
public PocketAddonType<? extends PocketAddon> getType() {
return PocketAddonType.PREVENT_BLOCK_MODIFICATION_ADDON;
}
@Override
public Identifier getId() {
return ID;
}
public static class PreventBlockModificationBuilderAddon implements PocketBuilderAddon<PreventBlockModificationAddon> {
@Override
public void apply(Pocket pocket) {
pocket.addAddon(new PreventBlockModificationAddon());
}
@Override
public Identifier getId() {
return ID;
}
@Override
public PocketBuilderAddon<PreventBlockModificationAddon> fromTag(CompoundTag tag) {
return this;
}
@Override
public PocketAddonType<PreventBlockModificationAddon> getType() {
return PocketAddonType.PREVENT_BLOCK_MODIFICATION_ADDON;
}
}
}

View file

@ -1,5 +1,7 @@
{
"builder": "dimdoors:private_pocket",
"builder": {
"type": "dimdoors:private_pocket"
},
"width": "5 + 16 * private_size",
"length": "5 + 16 * private_size",
"type": "dimdoors:void",

View file

@ -4,10 +4,12 @@
"compatibilityLevel": "JAVA_8",
"mixins": [
"DefaultBiomeFeaturesMixin",
"ExtendedServerPlayNetworkhandlerMixin",
"PlayerEntityMixin",
"RecipesProviderAccessor",
"RegistryKeyMixin",
"ServerPlayerEntityMixin",
"ServerPlayerInteractionManagerMixin",
"accessor.BuiltinBiomesAccessor",
"accessor.ChunkGeneratorAccessor",
"accessor.ChunkGeneratorSettingsAccessor",
@ -19,7 +21,9 @@
"accessor.StatsAccessor"
],
"client": [
"client.ClientPlayerInteractionManagerMixin",
"client.ClientPlayNetworkHandlerMixin",
"client.ExtendedClientPlayNetworkHandlerMixin",
"client.InGameHudMixin",
"client.accessor.GlStateManagerAccessor"
],