From f2289eb45d25cfccf0c40158450ae732f02b6e3b Mon Sep 17 00:00:00 2001 From: afamiliarquiet Date: Thu, 31 Oct 2024 15:42:20 -0700 Subject: [PATCH] transdimensional summoning (but STILL not able to keep your request when you go through a portal because Neo Doesn't Love Me. but whatever it's naturally incompatible of course you can't maintain a summon target if it gets summoned elsewhere, there's no way to keep track of these kinds of things. it's fine this is intended behavior. I WANTED THIS. i'll maybe figure it out later or maybe beg for salvation from someone else but it's not that big a deal, seems unlikely that you'd go through a portal while having a request and want to keep that request --- .../familiar_magic/FamiliarMagic.java | 48 +++++--- .../familiar_magic/FamiliarMagicClient.java | 20 ++-- .../familiar_magic/FamiliarTricks.java | 43 ++++++- .../entity/SummoningTableBlockEntity.java | 112 +++++++++++------- .../client/gooey/SummoningRequestLayer.java | 24 ++-- .../data/FamiliarAttachments.java | 9 +- .../data/SummoningRequestData.java | 46 +++++++ .../network/FamiliarPacketeering.java | 13 +- .../network/SomethingFamiliar.java | 51 -------- .../network/SummoningCancelledPayload.java | 39 ------ .../network/SummoningRequestPayload.java | 47 ++++++++ .../network/SummoningResponsePayload.java | 38 ++++-- .../textures/gui/summoning_request.png | Bin 1181 -> 1231 bytes 13 files changed, 290 insertions(+), 200 deletions(-) create mode 100644 src/main/java/io/github/afamiliarquiet/familiar_magic/data/SummoningRequestData.java delete mode 100644 src/main/java/io/github/afamiliarquiet/familiar_magic/network/SomethingFamiliar.java delete mode 100644 src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningCancelledPayload.java create mode 100644 src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningRequestPayload.java diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarMagic.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarMagic.java index 7087eec..e6ba8d3 100644 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarMagic.java +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarMagic.java @@ -10,26 +10,11 @@ import io.github.afamiliarquiet.familiar_magic.item.NameTagDispenseItemBehavior; import io.github.afamiliarquiet.familiar_magic.network.FamiliarPacketeering; import io.github.afamiliarquiet.familiar_magic.network.HattedPayload; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Position; -import net.minecraft.core.component.DataComponents; -import net.minecraft.core.dispenser.BlockSource; -import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; -import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntitySelector; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.ItemUtils; import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.DispenserBlock; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.phys.AABB; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModContainer; @@ -40,7 +25,6 @@ import net.neoforged.neoforge.event.entity.living.LivingDropsEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.network.PacketDistributor; -import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import static io.github.afamiliarquiet.familiar_magic.FamiliarTricks.getHat; @@ -87,6 +71,7 @@ public static class ImReallyGonnaDoItImGonnaExplode { @SubscribeEvent private static void mrwPlayerEventStartTracking(PlayerEvent.StartTracking event) { + // why do i gotta do this. why don't the attachments just do this for you. wargh. Entity theEntity = event.getTarget(); ItemStack hat = getHat(theEntity); if (theEntity instanceof HatWearer && !hat.isEmpty()) { @@ -111,5 +96,36 @@ private static void mrwLivingDropsEvent(LivingDropsEvent event) { private static void mrwRegisterCommandsEvent(RegisterCommandsEvent event) { PlaceCandlesCommand.register(event.getDispatcher()); } + +// @SubscribeEvent +// private static void mrwNOTEXCLAMATIONMARKPlayerEventClone(EntityTravelToDimensionEvent event) { +// // this player event clone thing has comments for dimension change but doesn't even fire on dimension change. +// // and then entitytraveltodimensionevent doesn't give me before and after!! +// if (!(event.getEntity() instanceof ServerPlayer player)) { +// // this shouldn't happen because clone only happens on server, but i may as well check since i'm casting +// // well now it happens because it's not always a player!!! GRAH +// return; +// } +// +// // oh neat the instanceof variable can carry out beyond a ! return. feels wrong though +// // anyway last ditch effort. we can maybe survive one dimension transition if the packet isn't Instantaneous +// // doesn't seem to work on dev env, maybe because packet is Instantaneous but like. whatever. let it break +// // as you well know, teleportation is not compatible with other teleportation. hard to keep a good lock on the target +// // GUARDS!! comment out their entire existence +// if (hasRequest(player)) { +// PacketDistributor.sendToPlayer(player, new SummoningRequestPayload(getRequest(player), false)); +// } +// +// if (hasRequest(event.getOriginal())) { +// SummoningRequestData requestData = getRequest(event.getOriginal()); +// if (event.isWasDeath()) { +// // player here shouldn't even get used really +// SummoningResponsePayload.eatRequestResponse(requestData, false, event.getEntity()); +// } else { +// setRequest(event.getEntity(), requestData); +// PacketDistributor.sendToPlayer((ServerPlayer) event.getEntity(), new SummoningRequestPayload(requestData, false)); +// } +// } +// } } } diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarMagicClient.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarMagicClient.java index 91bc3ac..c4e7fcb 100644 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarMagicClient.java +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarMagicClient.java @@ -15,6 +15,7 @@ import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; @@ -31,6 +32,8 @@ import org.lwjgl.glfw.GLFW; import static io.github.afamiliarquiet.familiar_magic.FamiliarMagic.MOD_ID; +import static io.github.afamiliarquiet.familiar_magic.FamiliarTricks.getRequest; +import static io.github.afamiliarquiet.familiar_magic.FamiliarTricks.hasRequest; @Mod(value = "familiar_magic", dist = Dist.CLIENT) public class FamiliarMagicClient { @@ -156,7 +159,7 @@ private static void mrwClientTickEventPost(ClientTickEvent.Pre event) { } // accept/reject summoning (a little bit weird to snag option keys isDown but..) - if (focusedNow && player.hasData(FamiliarAttachments.FAMILIAR_SUMMONING_DESTINATION)) { + if (focusedNow && hasRequest(player)) { if (options.keyShift.isDown()) { sendReply(player, false); } else if (options.keyJump.isDown()) { @@ -170,18 +173,9 @@ private static void mrwClientTickEventPost(ClientTickEvent.Pre event) { } } - public static void sendReply(LocalPlayer player, boolean accepted) { - PacketDistributor.sendToServer(new SummoningResponsePayload(player.getData(FamiliarAttachments.FAMILIAR_SUMMONING_DESTINATION), accepted)); + private static void sendReply(Player player, boolean accepted) { + // assumes player hasdata. server will probably just ignore request if it pulls default data though + PacketDistributor.sendToServer(new SummoningResponsePayload(getRequest(player), accepted)); } - -// @SubscribeEvent -// private static void mrwLivingEventLivingJumpEvent(LivingEvent.LivingJumpEvent event) { -// // i feel like i shouldn't need to look at every single entity jump event but whatever, if it works it works -// if (event.getEntity() instanceof LocalPlayer player) { -// if (player.getData(FamiliarAttachments.FOCUSED) && player.hasData(FamiliarAttachments.FAMILIAR_SUMMONING_DESTINATION)) { -// PacketDistributor.sendToServer(new SummoningResponsePayload(player.getData(FamiliarAttachments.FAMILIAR_SUMMONING_DESTINATION))); -// } -// } -// } } } diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarTricks.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarTricks.java index 55f4bd1..9792ca3 100644 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarTricks.java +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/FamiliarTricks.java @@ -1,9 +1,14 @@ package io.github.afamiliarquiet.familiar_magic; import io.github.afamiliarquiet.familiar_magic.data.FamiliarAttachments; +import io.github.afamiliarquiet.familiar_magic.data.SummoningRequestData; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.UUIDUtil; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; @@ -14,7 +19,9 @@ @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class FamiliarTricks { - // yea ill uhhh kill a quarter byte + // todo - configurize? + public static final int SUMMONING_TIME_SECONDS = 30; + public static final char[] I_TAKE_A_BYTE = { // todo - for fun maybe make this configurable 'd', // 0 'o', // 1 @@ -34,6 +41,7 @@ public class FamiliarTricks { 'h', // f }; + // yea ill uhhh kill a quarter byte public static final byte[] OW_IVE_BEEN_BYTTEN = new byte[256]; static { Arrays.fill(OW_IVE_BEEN_BYTTEN, (byte) -1); @@ -93,4 +101,37 @@ public static boolean hasHat(Entity entity) { public static ItemStack getHat(Entity entity) { return entity.getData(FamiliarAttachments.HAT).getStackInSlot(0); } + + public static @Nullable LivingEntity findTargetByUuid(UUID uuid, MinecraftServer server) { + LivingEntity livingTarget = null; + for (ServerLevel possibleLevel : server.getAllLevels()) { + Entity possibleTarget = possibleLevel.getEntity(uuid); + if (possibleTarget instanceof LivingEntity) { + livingTarget = (LivingEntity) possibleTarget; + break; + } + } + return livingTarget; + } + + public static boolean hasRequest(Player player) { + return player.hasData(FamiliarAttachments.SUMMONING_REQUEST); + } + + public static SummoningRequestData getRequest(Player player) { + return player.getData(FamiliarAttachments.SUMMONING_REQUEST); + } + + public static void setRequest(Player player, SummoningRequestData requestData) { + player.setData(FamiliarAttachments.SUMMONING_REQUEST, requestData); + } + + public static void removeRequest(Player player, SummoningRequestData cancellingPayloadData) { + if (hasRequest(player)) { + SummoningRequestData currentData = getRequest(player); + if (cancellingPayloadData.isSameRequester(currentData)) { + player.removeData(FamiliarAttachments.SUMMONING_REQUEST); + } + } + } } diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/block/entity/SummoningTableBlockEntity.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/block/entity/SummoningTableBlockEntity.java index b392102..50560b4 100644 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/block/entity/SummoningTableBlockEntity.java +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/block/entity/SummoningTableBlockEntity.java @@ -6,10 +6,10 @@ import io.github.afamiliarquiet.familiar_magic.block.SmokeWispBlock; import io.github.afamiliarquiet.familiar_magic.block.SummoningTableBlock; import io.github.afamiliarquiet.familiar_magic.client.gooey.SummoningTableMenu; +import io.github.afamiliarquiet.familiar_magic.data.SummoningRequestData; import io.github.afamiliarquiet.familiar_magic.item.FamiliarItems; import io.github.afamiliarquiet.familiar_magic.item.SingedComponentRecord; -import io.github.afamiliarquiet.familiar_magic.network.SomethingFamiliar; -import io.github.afamiliarquiet.familiar_magic.network.SummoningCancelledPayload; +import io.github.afamiliarquiet.familiar_magic.network.SummoningRequestPayload; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.HolderLookup; @@ -24,8 +24,9 @@ import net.minecraft.world.LockCode; import net.minecraft.world.MenuProvider; import net.minecraft.world.Nameable; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.RelativeMovement; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -45,9 +46,9 @@ import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import java.util.*; + +import static io.github.afamiliarquiet.familiar_magic.FamiliarTricks.findTargetByUuid; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault @@ -61,17 +62,17 @@ public class SummoningTableBlockEntity extends BlockEntity implements IItemHandl // spread out for easier reference (instead of computed) // as for the other choices on display, no comment private static final int[] CANDLE_COLUMN_OFFSETS = { - -5,-5, -3,-5, -1,-5, 1,-5, 3,-5, 5,-5, - -5,-3, -3,-3, -1,-3, 1,-3, 3,-3, 5,-3, - -5,-1, -3,-1, 3,-1, 5,-1, - -5, 1, -3, 1, 3, 1, 5, 1, - -5, 3, -3, 3, -1, 3, 1, 3, 3, 3, 5, 3, - -5, 5, -3, 5, -1, 5, 1, 5, 3, 5, 5, 5 + -5, -5, -3, -5, -1, -5, 1, -5, 3, -5, 5, -5, + -5, -3, -3, -3, -1, -3, 1, -3, 3, -3, 5, -3, + -5, -1, -3, -1, 3, -1, 5, -1, + -5, 1, -3, 1, 3, 1, 5, 1, + -5, 3, -3, 3, -1, 3, 1, 3, 3, 3, 5, 3, + -5, 5, -3, 5, -1, 5, 1, 5, 3, 5, 5, 5 }; private static final int[][] PHASE_INDICES = { - {0, 5, 26, 31}, // phase 1 (final phase) + {0, 5, 26, 31}, // phase 1 (final phase) {1, 11, 20, 30}, // phase 2 - {4, 6, 25, 27}, // phase 3 + {4, 6, 25, 27}, // phase 3 {3, 12, 19, 28}, // phase 4 {2, 15, 16, 29}, // phase 5 {7, 10, 21, 24}, // phase 6 @@ -132,26 +133,34 @@ public SummoningTableBlockEntity(BlockPos pos, BlockState blockState) { public BlockState startSummoning(BlockState state, boolean simulate) { if (this.level instanceof ServerLevel serverLevel) { - Entity targetEntity = serverLevel.getEntity(this.targetFromCandles); - if (targetEntity instanceof LivingEntity livingTarget) { - this.summoningTimer = 30; - - if (livingTarget instanceof ServerPlayer player) { - PacketDistributor.sendToPlayer(player, new SomethingFamiliar( - this.getBlockPos(), - List.of( - this.offerings.getStackInSlot(0), - this.offerings.getStackInSlot(1), - this.offerings.getStackInSlot(2), - this.offerings.getStackInSlot(3) - ) - )); - } else { - // todo - let picky critters be picky - serverLevel.scheduleTick(this.getBlockPos(), state.getBlock(), level.random.nextInt(13, 62)); + LivingEntity livingTarget = findTargetByUuid(this.targetFromCandles, serverLevel.getServer()); + if (livingTarget != null) { + if (!simulate) { + this.summoningTimer = FamiliarTricks.SUMMONING_TIME_SECONDS; + + if (livingTarget instanceof ServerPlayer player) { + SummoningRequestData requestData = new SummoningRequestData( + this.level.dimension(), + this.getBlockPos(), + Optional.of(List.of( + this.offerings.getStackInSlot(0), + this.offerings.getStackInSlot(1), + this.offerings.getStackInSlot(2), + this.offerings.getStackInSlot(3) + )) + ); + + //setRequest(player, requestData); + PacketDistributor.sendToPlayer(player, new SummoningRequestPayload(requestData, false)); + } else { + // todo - let picky critters be picky + serverLevel.scheduleTick(this.getBlockPos(), state.getBlock(), level.random.nextInt(13, 62)); + } } return state.setValue(SummoningTableBlock.SUMMONING_TABLE_STATE, SummoningTableState.SUMMONING); + } else { + // couldn't find target on server. nonexistent? unloaded? logged out? } } return state; @@ -159,9 +168,9 @@ public BlockState startSummoning(BlockState state, boolean simulate) { // assistant to previous method public void scheduledAccept() { - if (this.level instanceof ServerLevel serverLevel) { - Entity targetEntity = serverLevel.getEntity(this.targetFromCandles); - if (targetEntity instanceof LivingEntity livingTarget) { + if (this.level instanceof ServerLevel) { + LivingEntity livingTarget = findTargetByUuid(this.targetFromCandles, this.level.getServer()); + if (livingTarget != null) { acceptSummoning(livingTarget); } } @@ -184,11 +193,13 @@ public void cancelSummoning() { return; } - Entity target = ((ServerLevel)level).getEntity(this.targetFromCandles); + LivingEntity target = findTargetByUuid(this.targetFromCandles, level.getServer()); if (target instanceof ServerPlayer player) { // could i in theory use a different packet for this? yeah. should i? iunno // answer: YES because nulling the other one is NOT ALLOWED!!! i kinda figured :l - PacketDistributor.sendToPlayer(player, new SummoningCancelledPayload()); + SummoningRequestData requestData = new SummoningRequestData(this.level.dimension(), this.getBlockPos(), Optional.empty()); + //removeRequest(player, requestData); + PacketDistributor.sendToPlayer(player, new SummoningRequestPayload(requestData, true)); } this.summoningTimer = 0; @@ -201,7 +212,11 @@ public void acceptSummoning(LivingEntity livingTarget) { } if (livingTarget.getUUID().equals(this.targetFromCandles) && this.getBlockState().getValue(SummoningTableBlock.SUMMONING_TABLE_STATE) == SummoningTableState.SUMMONING) { BlockPos destination = this.getBlockPos(); - livingTarget.teleportTo(destination.getX() + 0.5, destination.getY() + 1, destination.getZ() + 0.5); + livingTarget.teleportTo((ServerLevel) this.level, destination.getX() + 0.5, destination.getY() + 1, destination.getZ() + 0.5, EnumSet.noneOf(RelativeMovement.class), livingTarget.getYRot(), livingTarget.getXRot()); + + if (livingTarget instanceof PathfinderMob pathfindermob) { + pathfindermob.getNavigation().stop(); + } // todo - replace these with more happy variants, and also give offerings to accepting player cancelSummoning(); @@ -270,9 +285,9 @@ private static UUID processCandles(Level level, BlockPos pos) { int nybblesTaken = 0; // columns, when facing northward - for (int z = pos.getZ() - 5, zLimit = pos.getZ() + 5; z <= zLimit; z+=2) { + for (int z = pos.getZ() - 5, zLimit = pos.getZ() + 5; z <= zLimit; z += 2) { // rows, when facing northward - for (int x = pos.getX() - 5, xLimit = pos.getX() + 5; x <= xLimit; x+=2) { + for (int x = pos.getX() - 5, xLimit = pos.getX() + 5; x <= xLimit; x += 2) { // skip center voids if (Math.abs(x - pos.getX()) <= 1 && Math.abs(z - pos.getZ()) <= 1) { continue; @@ -370,7 +385,6 @@ private static void burnColumn(Level level, BlockPos bottomPos, byte nybbleDigit } - // ahead lies the containery part of this damnable thing. Good lird @Override @@ -419,7 +433,7 @@ protected void applyImplicitComponents(BlockEntity.DataComponentInput componentI if (!allItems.isEmpty()) { this.trueName = allItems.getFirst(); } - for (int i = 1; i < allItems.size() && i < 1+offerings.getSlots(); i++) { + for (int i = 1; i < allItems.size() && i < 1 + offerings.getSlots(); i++) { offerings.setStackInSlot(i - 1, allItems.get(i)); } } @@ -469,7 +483,7 @@ public Component getDisplayName() { @Override public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { if (BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName())) { - return new SummoningTableMenu(containerId, playerInventory, this, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())); + return new SummoningTableMenu(containerId, playerInventory, this, this.dataAccess, ContainerLevelAccess.create(player.level(), this.getBlockPos())); } else { return null; } @@ -543,10 +557,16 @@ public ItemStack extractItem(int slot, int amount, boolean simulate) { @Override public int getSlotLimit(int slot) { - switch(slot) { - case 0 -> {return 1;} - case 1,2,3,4 -> {return this.offerings.getSlotLimit(slot - 1);} - default -> {return 0;} + switch (slot) { + case 0 -> { + return 1; + } + case 1, 2, 3, 4 -> { + return this.offerings.getSlotLimit(slot - 1); + } + default -> { + return 0; + } } } diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/client/gooey/SummoningRequestLayer.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/client/gooey/SummoningRequestLayer.java index d27926c..ce2239d 100644 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/client/gooey/SummoningRequestLayer.java +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/client/gooey/SummoningRequestLayer.java @@ -2,6 +2,7 @@ import io.github.afamiliarquiet.familiar_magic.FamiliarMagicClient; import io.github.afamiliarquiet.familiar_magic.data.FamiliarAttachments; +import io.github.afamiliarquiet.familiar_magic.data.SummoningRequestData; import net.minecraft.client.DeltaTracker; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; @@ -17,6 +18,8 @@ import java.util.List; import static io.github.afamiliarquiet.familiar_magic.FamiliarMagic.MOD_ID; +import static io.github.afamiliarquiet.familiar_magic.FamiliarTricks.getRequest; +import static io.github.afamiliarquiet.familiar_magic.FamiliarTricks.hasRequest; @ParametersAreNonnullByDefault public class SummoningRequestLayer implements LayeredDraw.Layer { @@ -32,14 +35,12 @@ public void render(GuiGraphics guiGraphics, DeltaTracker deltaTracker) { Minecraft minecraft = Minecraft.getInstance(); LocalPlayer player = minecraft.player; - if ( // wowowow intellij makes u really float all the way out here huh - player == null - || !player.hasData(FamiliarAttachments.FAMILIAR_SUMMONING_DESTINATION) - || !player.hasData(FamiliarAttachments.FAMILIAR_SUMMONING_OFFERINGS) - ) { + if (player == null || !hasRequest(player)) { return; } + SummoningRequestData requestData = getRequest(player); + int top = guiGraphics.guiHeight() - (this.imageHeight + this.spacing); int left = guiGraphics.guiWidth() - (this.imageWidth + this.spacing); @@ -54,17 +55,21 @@ public void render(GuiGraphics guiGraphics, DeltaTracker deltaTracker) { minecraft.options.keyJump.getKey().getDisplayName(), minecraft.options.keyShift.getKey().getDisplayName() ); - BlockPos destinationPos = player.getData(FamiliarAttachments.FAMILIAR_SUMMONING_DESTINATION); + + // i have a hunch this may not exist but we shall see! maybe neoforge is nice to me today + Component levelComponent = Component.translatable(requestData.tableLevelKey().location().toLanguageKey()); + BlockPos destinationPos = requestData.tablePos(); Component positionComponent = Component.translatable( "gui.familiar_magic.summoning_request.position", destinationPos.getX(), destinationPos.getY(), destinationPos.getZ() ); - List offerings = player.getData(FamiliarAttachments.FAMILIAR_SUMMONING_OFFERINGS); + List offerings = requestData.offerings().orElse(List.of()); // *should* always be present but w/e this.drawCenteredStringAtHeight(guiGraphics, minecraft.font, top, left, titleComponent, 0); guiGraphics.drawWordWrap(minecraft.font, blurb, left + this.spacing, top + 26, this.imageWidth - 2 * this.spacing, 0x492f5b); + this.drawCenteredStringAtHeight(guiGraphics, minecraft.font, top, left, levelComponent, 60); this.drawCenteredStringAtHeight(guiGraphics, minecraft.font, top, left, positionComponent, 72); this.drawItems(guiGraphics, minecraft.font, top, left, offerings); @@ -82,6 +87,11 @@ private void drawCenteredStringAtHeight(GuiGraphics guiGraphics, Font font, int } private void drawItems(GuiGraphics guiGraphics, Font font, int top, int left, List offerings) { + if (offerings.size() != 4) { + // just to be extra safe + return; + } + for (int i = 0; i < 4; i++) { int itemTop = top + 98; int itemLeft = i * 18 + left + 29; diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/data/FamiliarAttachments.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/data/FamiliarAttachments.java index 119c962..8fe73eb 100644 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/data/FamiliarAttachments.java +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/data/FamiliarAttachments.java @@ -33,13 +33,10 @@ public class FamiliarAttachments { ); // also not persistent - client only - these defaults shouldn't ever really be seen. if they are uhh.. report bug <3 - // todo - make summoning work cross dimensionally, and these not disappear when changing dimension + // todo - make these not disappear when changing dimension, and make table cancel when target disconnects mayyybe.. maybe not because then i'd have to store on animals too and cancel when they unload and that sounds unnecessary but maybe later // i feel like the serialization would help with that but. for now, not a big issue. bugfix maybe - public static final Supplier> FAMILIAR_SUMMONING_DESTINATION = ATTACHMENT_TYPES.register( - "familiar_summoning_destination", () -> AttachmentType.builder(() -> BlockPos.ZERO).build() - ); - public static final Supplier>> FAMILIAR_SUMMONING_OFFERINGS = ATTACHMENT_TYPES.register( - "familiar_summoning_offerings", () -> AttachmentType.>builder(() -> List.of()).build() + public static final Supplier> SUMMONING_REQUEST = ATTACHMENT_TYPES.register( + "summoning_request", () -> AttachmentType.builder(() -> SummoningRequestData.DEFAULT).build() ); public static void register(IEventBus modEventBus) { diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/data/SummoningRequestData.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/data/SummoningRequestData.java new file mode 100644 index 0000000..73704d4 --- /dev/null +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/data/SummoningRequestData.java @@ -0,0 +1,46 @@ +package io.github.afamiliarquiet.familiar_magic.data; + +import io.netty.buffer.ByteBuf; +import net.minecraft.core.BlockPos; +import net.minecraft.core.NonNullList; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Optional; + +public record SummoningRequestData(ResourceKey tableLevelKey, BlockPos tablePos, Optional> offerings) { + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.fromCodec(Level.RESOURCE_KEY_CODEC), + SummoningRequestData::tableLevelKey, + ByteBufCodecs.fromCodec(BlockPos.CODEC), + SummoningRequestData::tablePos, + ByteBufCodecs.optional(ByteBufCodecs.collection( // goidness ggrayshesous + NonNullList::createWithCapacity, + ByteBufCodecs.fromCodec(ItemStack.OPTIONAL_CODEC), + 4 + )), + SummoningRequestData::offerings, + SummoningRequestData::new + ); + + // this should never ever be seen, only there because it's kinda required because attachments are silly + public static final SummoningRequestData DEFAULT = new SummoningRequestData(Level.OVERWORLD, BlockPos.ZERO, Optional.empty()); + + public boolean isSameRequester(@Nullable SummoningRequestData other) { + return other != null && this.tableLevelKey.compareTo(other.tableLevelKey) == 0 && this.tablePos.equals(other.tablePos); + } + + @Override + public String toString() { + return "SummoningRequestData{" + + "tableLevelKey=" + tableLevelKey + + ", tablePos=" + tablePos + + ", offerings=" + offerings + + '}'; + } +} diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/FamiliarPacketeering.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/network/FamiliarPacketeering.java index 4a049dd..a021902 100644 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/FamiliarPacketeering.java +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/network/FamiliarPacketeering.java @@ -20,19 +20,14 @@ public static void mrwRegisterPayloadHandlersEvent(final RegisterPayloadHandlers ); registrar.playToClient( - SomethingFamiliar.TYPE, - SomethingFamiliar.STREAM_CODEC, - SomethingFamiliar::hmHmYouWantToSummonMe - ); - registrar.playToClient( - SummoningCancelledPayload.TYPE, - SummoningCancelledPayload.STREAM_CODEC, - SummoningCancelledPayload::sorry + SummoningRequestPayload.TYPE, + SummoningRequestPayload.STREAM_CODEC, + SummoningRequestPayload::ayeAyeRequestReceived ); registrar.playToServer( SummoningResponsePayload.TYPE, SummoningResponsePayload.STREAM_CODEC, - SummoningResponsePayload::atYourService + SummoningResponsePayload::iveGivenItSomeThought ); } } diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SomethingFamiliar.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SomethingFamiliar.java deleted file mode 100644 index aa2eebe..0000000 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SomethingFamiliar.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.github.afamiliarquiet.familiar_magic.network; - -import io.github.afamiliarquiet.familiar_magic.data.FamiliarAttachments; -import io.netty.buffer.ByteBuf; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.core.BlockPos; -import net.minecraft.core.NonNullList; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.network.handling.IPayloadContext; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -import static io.github.afamiliarquiet.familiar_magic.FamiliarMagic.MOD_ID; - -public record SomethingFamiliar(BlockPos summoningPos, List offerings) implements CustomPacketPayload { - public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(MOD_ID, "summoning_start_payload")); - - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.fromCodec(BlockPos.CODEC), - SomethingFamiliar::summoningPos, - ByteBufCodecs.collection( // goidness ggrayshesous - NonNullList::createWithCapacity, - ByteBufCodecs.fromCodec(ItemStack.OPTIONAL_CODEC), - 4 - ), - SomethingFamiliar::offerings, - SomethingFamiliar::new - ); - - @Override - public @NotNull Type type() { - return TYPE; - } - - public static void hmHmYouWantToSummonMe(final SomethingFamiliar somethingFamiliar, final IPayloadContext context) { - // is this something to be encouraged? - // i feel like i should store it on local playerentity data attachment or something instead. that feels better. - LocalPlayer hehehe = Minecraft.getInstance().player; - if (hehehe != null) { - // also set like, request time? to 30? and fade screen in and out at the ends - hehehe.setData(FamiliarAttachments.FAMILIAR_SUMMONING_DESTINATION, somethingFamiliar.summoningPos); - hehehe.setData(FamiliarAttachments.FAMILIAR_SUMMONING_OFFERINGS, somethingFamiliar.offerings); - } - } -} diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningCancelledPayload.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningCancelledPayload.java deleted file mode 100644 index d19f45f..0000000 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningCancelledPayload.java +++ /dev/null @@ -1,39 +0,0 @@ -package io.github.afamiliarquiet.familiar_magic.network; - -import io.github.afamiliarquiet.familiar_magic.data.FamiliarAttachments; -import io.netty.buffer.ByteBuf; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.network.protocol.common.custom.CustomPacketPayload; -import net.minecraft.resources.ResourceLocation; -import net.neoforged.neoforge.network.handling.IPayloadContext; -import org.jetbrains.annotations.NotNull; - -import static io.github.afamiliarquiet.familiar_magic.FamiliarMagic.MOD_ID; - -// todo - add blockpos to this so that you can't cancel other summonings on the target -public record SummoningCancelledPayload() implements CustomPacketPayload { - public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(MOD_ID, "summoning_cancelled_payload")); - - // is this sensible? this feels sensible enough. - public static final StreamCodec STREAM_CODEC = StreamCodec.of( - (buffer, value) -> {}, - (buffer -> new SummoningCancelledPayload()) - ); - - @Override - public @NotNull Type type() { - return TYPE; - } - - public static void sorry(final SummoningCancelledPayload payload, final IPayloadContext context) { - // is this something to be encouraged? - // i feel like i should store it on local playerentity data attachment or something instead. that feels better. - LocalPlayer hehehe = Minecraft.getInstance().player; - if (hehehe != null) { - hehehe.removeData(FamiliarAttachments.FAMILIAR_SUMMONING_DESTINATION); - hehehe.removeData(FamiliarAttachments.FAMILIAR_SUMMONING_OFFERINGS); - } - } -} diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningRequestPayload.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningRequestPayload.java new file mode 100644 index 0000000..fa54ba0 --- /dev/null +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningRequestPayload.java @@ -0,0 +1,47 @@ +package io.github.afamiliarquiet.familiar_magic.network; + +import io.github.afamiliarquiet.familiar_magic.data.SummoningRequestData; +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +import static io.github.afamiliarquiet.familiar_magic.FamiliarMagic.MOD_ID; +import static io.github.afamiliarquiet.familiar_magic.FamiliarTricks.removeRequest; +import static io.github.afamiliarquiet.familiar_magic.FamiliarTricks.setRequest; + +public record SummoningRequestPayload(SummoningRequestData requestData, boolean cancelled) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(MOD_ID, "summoning_start_payload")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + SummoningRequestData.STREAM_CODEC, + SummoningRequestPayload::requestData, + ByteBufCodecs.BOOL, + SummoningRequestPayload::cancelled, + SummoningRequestPayload::new + ); + + @Override + public @NotNull Type type() { + return TYPE; + } + + public static void ayeAyeRequestReceived(final SummoningRequestPayload summoningRequestPayload, final IPayloadContext context) { + // why did neo get mad about a localplayer here? this should only be handled on client, where we have local players? am i not allowed to import for that? + // i was literally doin that before!! i dont get it i changed too much without testing + // is this because i'm adding it a call to this in a listener in FamiliarMagic's common listeners?? + Player hehehe = context.player(); + if (summoningRequestPayload.cancelled) { + // remove if we have it, and only if it seems to be from the same source as what we have + removeRequest(hehehe, summoningRequestPayload.requestData); + } else { + // also set like, request time? to 30? and fade screen in and out at the ends + setRequest(hehehe, summoningRequestPayload.requestData); + } + } +} diff --git a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningResponsePayload.java b/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningResponsePayload.java index a0f2e61..6dda87e 100644 --- a/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningResponsePayload.java +++ b/src/main/java/io/github/afamiliarquiet/familiar_magic/network/SummoningResponsePayload.java @@ -1,25 +1,28 @@ package io.github.afamiliarquiet.familiar_magic.network; import io.github.afamiliarquiet.familiar_magic.block.entity.SummoningTableBlockEntity; +import io.github.afamiliarquiet.familiar_magic.data.SummoningRequestData; import io.netty.buffer.ByteBuf; -import net.minecraft.core.BlockPos; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.network.handling.IPayloadContext; import org.jetbrains.annotations.NotNull; import static io.github.afamiliarquiet.familiar_magic.FamiliarMagic.MOD_ID; -public record SummoningResponsePayload(BlockPos acceptedPos, boolean accepted) implements CustomPacketPayload { +public record SummoningResponsePayload(SummoningRequestData requestData, boolean accepted) implements CustomPacketPayload { public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(MOD_ID, "summoning_accepted_payload")); // is this is this sensible? this feels sensible enough enough. public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.fromCodec(BlockPos.CODEC), - SummoningResponsePayload::acceptedPos, + SummoningRequestData.STREAM_CODEC, + SummoningResponsePayload::requestData, ByteBufCodecs.BOOL, SummoningResponsePayload::accepted, SummoningResponsePayload::new @@ -30,14 +33,25 @@ public record SummoningResponsePayload(BlockPos acceptedPos, boolean accepted) i return TYPE; } - public static void atYourService(final SummoningResponsePayload payload, final IPayloadContext context) { - BlockEntity acceptedEntity = context.player().level().getBlockEntity(payload.acceptedPos); - if (acceptedEntity instanceof SummoningTableBlockEntity tableEntity) { - if (payload.accepted) { - tableEntity.acceptSummoning(context.player()); - } else { - // todo - maybe something else here that's more indicative of rejection.. later - tableEntity.cancelSummoning(); + public static void iveGivenItSomeThought(final SummoningResponsePayload payload, final IPayloadContext context) { + SummoningRequestData requestData = payload.requestData; + eatRequestResponse(requestData, payload.accepted, context.player()); + } + + public static void eatRequestResponse(SummoningRequestData requestData, boolean accepted, Player player) { + MinecraftServer server = player.getServer(); + if (server != null) { + Level targetLevel = server.getLevel(requestData.tableLevelKey()); + if (targetLevel != null) { + BlockEntity acceptedEntity = targetLevel.getBlockEntity(requestData.tablePos()); + if (acceptedEntity instanceof SummoningTableBlockEntity tableEntity) { + if (accepted) { + tableEntity.acceptSummoning(player); + } else { + // todo - maybe something else here that's more indicative of rejection.. later + tableEntity.cancelSummoning(); + } + } } } } diff --git a/src/main/resources/assets/familiar_magic/textures/gui/summoning_request.png b/src/main/resources/assets/familiar_magic/textures/gui/summoning_request.png index 32959f2d1b5736a4fa8cbab6491076c2a137f910..477c910db4743b8ffce25c385f866a6f106be329 100644 GIT binary patch delta 1211 zcmV;s1VsCt3C{_TB!8AkL_t(|ob8>viWETUk%`$z6dSQZ%=S9{e_ymrcb&SNvvoVC zt0pg>-kCe++^q-O6W5bh&+g7+$|%SFX7SJSXL;UrY3t}(_J1n*w;#UfUH{mIR*wBG z&nJJD=Utb!j;>|5@H)4jLf#! zvc|mH$Y@fol^K=XrT)2L3|0Tyf;MHe=>0{7ZQC$yW%hYLKJOxTZ1s1s2WZN8*@EO5 z_DS1^u8LKwe}C+CCiD5+HFdpR1ut8$|D7?_KMVoU0M=P4&<}3_2aa#-pnOrj{ru&o z>W!cd1|UkDlwttF_*FnKfUX+}u)cU*TYXQL*#d_3!%z6_q@N)`7{3XK0f-WN0SrJK z3_zT)73?w>FFS)8_|?G78ResRJ<@-<-&AWkv>c7Fr4hyfuC0piTm8$gY`r)Lfz zM(zs;5kdZslUv8s+eQi>4Rr1D`NyFLVEoquUjPIM2oZ;X5OEj+#3}3qG8E{MHiB3Q zXu=R64hA4fbOzxI5CdO;IMx?HShz531w(-I0Yu^JU?_%!fd=_1pz@5Mp-;4eVX;QQ zmqEgKLw^WEfc-M4?WvhC4$>;X#sm@{r~#*h0S2HB1|SXwAPxo~4hA3!z5pO1ND(4} z#L2h$F#thIN5!)DuS@CMK#W0)GzmoUdibc|bV7*R9UJfjYT)(ky@8HrLKMx2KfjAFv^aN5c1c00R|9+IO3jrbGU;v^J6%7AQ z2w@qhL%!iRjeEkNL4IctLx3+zhao_m!cHJVfgXGr zB+lSFfsdYlQg8EGp4>Y-c%FmK0am5_6NfiPDd+W@FDsGLhUg617hk~Di+`3%zw`B| z`~G{Ja^AoD;jUcYT1rk6_yWYSz5v3)g@0iy7y_IRAPQdxLop-_G$^eCycOg>vMoGb z?CtP=_z(L4-U#?INC$gRWEcW$SeUgC7(cVBRRBGJ4om{Y!2ra;0K~xn#K8c>88jZi zN4)r;2k-Y@79WH$Mma;VZ@z$=H&$~k&DN2Fqm;9k!5}&N77;XLC7}orLE_|_e18~# zAf=;X+56X}^lc!JG zLai$8qBQooV*OpyQL!;`SL3LAciGB!?V@eiQy=*%^)KBV8nLT`{JAYm)s^H;@)muE zP<4TIp9ZL_cpmbW$3y1jt*XzM>NMZ!c$lh+xva7J%E;x}_v)0?MowMceU8Q%UHzSN Ze*vaM2Q2Kmf|CFM002ovPDHLkV1jU8EbagR delta 1161 zcmV;41a|w+37rX$B!6T{L_t(|ob8=0j}$==hI^M2mw?3(5)vfAU>1eL;?Cp1faCy& z1Ain03=Xyb0fFKVfG0r_e#4UPTs1X4A3Gn%E<5k@sLRewO?OvaS9e!U_u~EQCz}vL zc=Y0I5k~Ui&C`uNX>$B;o_M{yR=&IK**1ojy-EJ#mv2Yc-+$WB%kjUJ?5~%-MtmQeEqid!7k-S8IdT*lx)9w>^=UPf2Ne@?`e`3oXo!Xvf8`)$mmk8 zmuX5KQvcF0c2)n@f_A-V+x^=L+qYr*${cgQT^}NMZuJk=19ZK3YC*~uj(K(rLlvu5 zf9rJ?o6RP4b$`7>1y3#5|IVE1pIm?$z#%II#t{wR(zWB?C|{HxKYxX#dLyWV0f=IQ zQVc+tI15MyFmxdS4wtBFukYoQC15x_;(*@|`f&lm#6>_1Kosi*FaU8d0CCb%a415& ztPE-pX9GvUDIdk_kzD}F*Mu>EIN1PL4b;LCLT~}%9Dk`dfEr~_&lo_AG8T|Bg5n=H zu3uGe8!2Ko(1ZJ{SE&cU|LZ|401_mGh(kh%IJf|DDl37w0zL9V5HkTyZ~@|A0HRnh zh**Fa!~(?eu>jJ-g<&Ze66_Bk3SS39H6;u*C}#nUdj#!zM=RJZ-U#?INSJ5{$p!c? zgZl2834ik-&jNf-Ao+nBuuB+V0P0`>;$Q&cU;yG^0HP2J05XCUAtOkfa+x0k5Tv$M zENlO|)V>YG7_`WPKoqY>%nHssgoJb7KqOFusOK0BOg#VzAiCs1ATB_Y)_npo2n}i{ zhZ?wr`O=sa8u@hgY;))KP4)JfEne|<5_`hUvhu z1`WzHgKz=Duu-HiY!nFz3_zSb03;ruM~(%U@=?4V93CwWV*qg~r-p$Jc4Q1LKpb`m z5r2anLc}R!0Sl&pnpE-uP`)0-0w6&`h&UvKh=U6dr?L`=E6{^4gT%oFh_myh;M3F7 z$udq(PQrSU25M3Vhmd3K_H6PBhCQH12{K+#k%KwfO6j$f5V~Dx9nZYSEzp;1b+@` zuzy{si+Xn3Gyb|_{X^GQvG(v#<7m5gYUPJ^(LU{IjC_^)*G>*K{Oq8-?hDg&Bzc#- zZA;Hh2Uw43fVPU4DQ{&yWLe&(`pl{RgSLlhs#qu*Ypje?p1-e6NqywBy?e~oIJ2vN b2;mPAjtHM9`4IsC0000