add basic "proximity UI" that appears when you approach a game in progress
Some checks failed
Build / build (push) Has been cancelled
Some checks failed
Build / build (push) Has been cancelled
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.trunksbomb.minetriad;
|
package com.trunksbomb.minetriad;
|
||||||
|
|
||||||
|
import com.trunksbomb.minetriad.client.hud.LocalDuelHudOverlay;
|
||||||
import com.trunksbomb.minetriad.client.render.FirstPersonCardHandRenderer;
|
import com.trunksbomb.minetriad.client.render.FirstPersonCardHandRenderer;
|
||||||
import com.trunksbomb.minetriad.client.render.DuelTableBlockEntityRenderer;
|
import com.trunksbomb.minetriad.client.render.DuelTableBlockEntityRenderer;
|
||||||
import com.trunksbomb.minetriad.client.screen.CardBinderScreen;
|
import com.trunksbomb.minetriad.client.screen.CardBinderScreen;
|
||||||
@@ -16,7 +17,9 @@ import net.neoforged.bus.api.IEventBus;
|
|||||||
import net.neoforged.fml.common.EventBusSubscriber;
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
|
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
|
||||||
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
|
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
|
||||||
|
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||||
import net.neoforged.neoforge.client.event.RenderHandEvent;
|
import net.neoforged.neoforge.client.event.RenderHandEvent;
|
||||||
|
import net.neoforged.neoforge.client.event.RenderGuiLayerEvent;
|
||||||
|
|
||||||
@Mod(value = MineTriad.MOD_ID, dist = Dist.CLIENT)
|
@Mod(value = MineTriad.MOD_ID, dist = Dist.CLIENT)
|
||||||
public final class MineTriadClient {
|
public final class MineTriadClient {
|
||||||
@@ -55,5 +58,15 @@ public final class MineTriadClient {
|
|||||||
event.getEquipProgress(),
|
event.getEquipProgress(),
|
||||||
event.getItemStack());
|
event.getItemStack());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onClientTick(ClientTickEvent.Post event) {
|
||||||
|
LocalDuelHudOverlay.onClientTick(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onRenderGui(RenderGuiLayerEvent.Post event) {
|
||||||
|
LocalDuelHudOverlay.onRenderGui(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public final class DuelTableAnimationResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
session.beginOpponentAnimation();
|
session.beginOpponentAnimation();
|
||||||
|
table.updateHudState(session);
|
||||||
table.startMoveAnimation(opponentMove, DuelTableBlockEntity.OWNER_SECOND);
|
table.startMoveAnimation(opponentMove, DuelTableBlockEntity.OWNER_SECOND);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ public final class DuelTableAnimationResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
session.returnToPlaying();
|
session.returnToPlaying();
|
||||||
|
table.updateHudState(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startAiTurn(DuelTableBlockEntity table, DuelSession session, ServerPlayer player) {
|
public static void startAiTurn(DuelTableBlockEntity table, DuelSession session, ServerPlayer player) {
|
||||||
@@ -92,6 +94,7 @@ public final class DuelTableAnimationResolver {
|
|||||||
} else {
|
} else {
|
||||||
session.beginOpponentAnimation();
|
session.beginOpponentAnimation();
|
||||||
}
|
}
|
||||||
|
table.updateHudState(session);
|
||||||
table.startMoveAnimation(aiMove, owner);
|
table.startMoveAnimation(aiMove, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +104,7 @@ public final class DuelTableAnimationResolver {
|
|||||||
.map(cardId -> CardItem.createCardStack(cardId, TriadItems.TRIAD_CARD.get()))
|
.map(cardId -> CardItem.createCardStack(cardId, TriadItems.TRIAD_CARD.get()))
|
||||||
.toList());
|
.toList());
|
||||||
table.removeBoardCardsOwnedBy(DuelTableBlockEntity.OWNER_SECOND);
|
table.removeBoardCardsOwnedBy(DuelTableBlockEntity.OWNER_SECOND);
|
||||||
|
table.updateHudState(session);
|
||||||
table.startOverviewSweepAnimation();
|
table.startOverviewSweepAnimation();
|
||||||
player.displayClientMessage(session.resultSummary().copy().withStyle(ChatFormatting.AQUA), false);
|
player.displayClientMessage(session.resultSummary().copy().withStyle(ChatFormatting.AQUA), false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,15 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
private TableAnimationType tableAnimationType = TableAnimationType.NONE;
|
private TableAnimationType tableAnimationType = TableAnimationType.NONE;
|
||||||
private int tableAnimationAge;
|
private int tableAnimationAge;
|
||||||
private int tableAnimationDuration;
|
private int tableAnimationDuration;
|
||||||
|
private boolean hudActive;
|
||||||
|
private int hudP1HandCount;
|
||||||
|
private int hudP2HandCount;
|
||||||
|
private int hudP1Score;
|
||||||
|
private int hudP2Score;
|
||||||
|
private String hudRules = "";
|
||||||
|
private String hudGameState = "";
|
||||||
|
private String hudTurn = "";
|
||||||
|
private String hudInstruction = "";
|
||||||
|
|
||||||
public DuelTableBlockEntity(BlockPos pos, BlockState blockState) {
|
public DuelTableBlockEntity(BlockPos pos, BlockState blockState) {
|
||||||
super(TriadBlockEntities.DUEL_TABLE.get(), pos, blockState);
|
super(TriadBlockEntities.DUEL_TABLE.get(), pos, blockState);
|
||||||
@@ -110,6 +119,42 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
return Optional.ofNullable(secondParticipantId);
|
return Optional.ofNullable(secondParticipantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hudActive() {
|
||||||
|
return hudActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hudP1HandCount() {
|
||||||
|
return hudP1HandCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hudP2HandCount() {
|
||||||
|
return hudP2HandCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hudP1Score() {
|
||||||
|
return hudP1Score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hudP2Score() {
|
||||||
|
return hudP2Score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String hudRules() {
|
||||||
|
return hudRules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String hudGameState() {
|
||||||
|
return hudGameState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String hudTurn() {
|
||||||
|
return hudTurn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String hudInstruction() {
|
||||||
|
return hudInstruction;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasActiveAnimation() {
|
public boolean hasActiveAnimation() {
|
||||||
return animationType != AnimationType.NONE || tableAnimationType != TableAnimationType.NONE;
|
return animationType != AnimationType.NONE || tableAnimationType != TableAnimationType.NONE;
|
||||||
}
|
}
|
||||||
@@ -171,6 +216,34 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateHudState(DuelSession session) {
|
||||||
|
hudActive = true;
|
||||||
|
hudP1HandCount = session.playerHandCount();
|
||||||
|
hudP2HandCount = session.opponentHandCount();
|
||||||
|
hudP1Score = session.playerScore();
|
||||||
|
hudP2Score = session.opponentScore();
|
||||||
|
hudRules = session.rulesSummary();
|
||||||
|
hudGameState = session.gameStateLabel();
|
||||||
|
hudTurn = session.turnIndicator();
|
||||||
|
hudInstruction = session.isInOverview()
|
||||||
|
? rewardCardCount() > 0 ? "P1 choosing 1 cards to keep" : "Ready for next game"
|
||||||
|
: session.nextStepInstruction();
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearHudState() {
|
||||||
|
hudActive = false;
|
||||||
|
hudP1HandCount = 0;
|
||||||
|
hudP2HandCount = 0;
|
||||||
|
hudP1Score = 0;
|
||||||
|
hudP2Score = 0;
|
||||||
|
hudRules = "";
|
||||||
|
hudGameState = "";
|
||||||
|
hudTurn = "";
|
||||||
|
hudInstruction = "";
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean setCard(int slot, ItemStack stack, int owner) {
|
public boolean setCard(int slot, ItemStack stack, int owner) {
|
||||||
if (slot < 0 || slot >= boardCards.size() || !boardCards.get(slot).isEmpty() || !stack.is(TriadItems.TRIAD_CARD.get())) {
|
if (slot < 0 || slot >= boardCards.size() || !boardCards.get(slot).isEmpty() || !stack.is(TriadItems.TRIAD_CARD.get())) {
|
||||||
return false;
|
return false;
|
||||||
@@ -202,6 +275,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
clearRewardCards();
|
clearRewardCards();
|
||||||
firstParticipantId = null;
|
firstParticipantId = null;
|
||||||
secondParticipantId = null;
|
secondParticipantId = null;
|
||||||
|
clearHudState();
|
||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +310,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
dropRewardCards(level, pos);
|
dropRewardCards(level, pos);
|
||||||
firstParticipantId = null;
|
firstParticipantId = null;
|
||||||
secondParticipantId = null;
|
secondParticipantId = null;
|
||||||
|
clearHudState();
|
||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,6 +323,10 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
refreshRewardInteractions();
|
refreshRewardInteractions();
|
||||||
|
DuelSession session = level == null ? null : DuelSessionManager.getAt(worldPosition);
|
||||||
|
if (session != null) {
|
||||||
|
updateHudState(session);
|
||||||
|
}
|
||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,6 +349,10 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
}
|
}
|
||||||
rewardCards.set(slot, ItemStack.EMPTY);
|
rewardCards.set(slot, ItemStack.EMPTY);
|
||||||
refreshRewardInteractions();
|
refreshRewardInteractions();
|
||||||
|
DuelSession session = level == null ? null : DuelSessionManager.getAt(worldPosition);
|
||||||
|
if (session != null) {
|
||||||
|
updateHudState(session);
|
||||||
|
}
|
||||||
sync();
|
sync();
|
||||||
return taken;
|
return taken;
|
||||||
}
|
}
|
||||||
@@ -475,6 +558,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
ContainerHelper.saveAllItems(rewardTag, rewardCards, registries);
|
ContainerHelper.saveAllItems(rewardTag, rewardCards, registries);
|
||||||
tag.put("RewardCards", rewardTag);
|
tag.put("RewardCards", rewardTag);
|
||||||
saveRewardTakeAnimations(tag, registries);
|
saveRewardTakeAnimations(tag, registries);
|
||||||
|
saveHudState(tag);
|
||||||
tag.putIntArray("OwnerSlots", ownerSlots);
|
tag.putIntArray("OwnerSlots", ownerSlots);
|
||||||
tag.putIntArray("SlotAges", slotAges);
|
tag.putIntArray("SlotAges", slotAges);
|
||||||
saveAnimation(tag);
|
saveAnimation(tag);
|
||||||
@@ -496,6 +580,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
ContainerHelper.loadAllItems(tag.getCompound("RewardCards"), rewardCards, registries);
|
ContainerHelper.loadAllItems(tag.getCompound("RewardCards"), rewardCards, registries);
|
||||||
}
|
}
|
||||||
loadRewardTakeAnimations(tag, registries);
|
loadRewardTakeAnimations(tag, registries);
|
||||||
|
loadHudState(tag);
|
||||||
loadOwnerData(tag);
|
loadOwnerData(tag);
|
||||||
loadAnimation(tag);
|
loadAnimation(tag);
|
||||||
loadTableAnimation(tag);
|
loadTableAnimation(tag);
|
||||||
@@ -509,6 +594,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
ContainerHelper.saveAllItems(rewardTag, rewardCards, registries);
|
ContainerHelper.saveAllItems(rewardTag, rewardCards, registries);
|
||||||
tag.put("RewardCards", rewardTag);
|
tag.put("RewardCards", rewardTag);
|
||||||
saveRewardTakeAnimations(tag, registries);
|
saveRewardTakeAnimations(tag, registries);
|
||||||
|
saveHudState(tag);
|
||||||
tag.putIntArray("OwnerSlots", ownerSlots);
|
tag.putIntArray("OwnerSlots", ownerSlots);
|
||||||
tag.putIntArray("SlotAges", slotAges);
|
tag.putIntArray("SlotAges", slotAges);
|
||||||
saveAnimation(tag);
|
saveAnimation(tag);
|
||||||
@@ -537,6 +623,7 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
ContainerHelper.loadAllItems(tag.getCompound("RewardCards"), rewardCards, registries);
|
ContainerHelper.loadAllItems(tag.getCompound("RewardCards"), rewardCards, registries);
|
||||||
}
|
}
|
||||||
loadRewardTakeAnimations(tag, registries);
|
loadRewardTakeAnimations(tag, registries);
|
||||||
|
loadHudState(tag);
|
||||||
loadOwnerData(tag);
|
loadOwnerData(tag);
|
||||||
loadAnimation(tag);
|
loadAnimation(tag);
|
||||||
loadTableAnimation(tag);
|
loadTableAnimation(tag);
|
||||||
@@ -554,6 +641,15 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
clearRewardCards();
|
clearRewardCards();
|
||||||
firstParticipantId = null;
|
firstParticipantId = null;
|
||||||
secondParticipantId = null;
|
secondParticipantId = null;
|
||||||
|
hudActive = false;
|
||||||
|
hudP1HandCount = 0;
|
||||||
|
hudP2HandCount = 0;
|
||||||
|
hudP1Score = 0;
|
||||||
|
hudP2Score = 0;
|
||||||
|
hudRules = "";
|
||||||
|
hudGameState = "";
|
||||||
|
hudTurn = "";
|
||||||
|
hudInstruction = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadOwnerData(CompoundTag tag) {
|
private void loadOwnerData(CompoundTag tag) {
|
||||||
@@ -585,6 +681,30 @@ public class DuelTableBlockEntity extends BlockEntity {
|
|||||||
tag.put("RewardTakeAnimations", animationsTag);
|
tag.put("RewardTakeAnimations", animationsTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveHudState(CompoundTag tag) {
|
||||||
|
tag.putBoolean("HudActive", hudActive);
|
||||||
|
tag.putInt("HudP1HandCount", hudP1HandCount);
|
||||||
|
tag.putInt("HudP2HandCount", hudP2HandCount);
|
||||||
|
tag.putInt("HudP1Score", hudP1Score);
|
||||||
|
tag.putInt("HudP2Score", hudP2Score);
|
||||||
|
tag.putString("HudRules", hudRules);
|
||||||
|
tag.putString("HudGameState", hudGameState);
|
||||||
|
tag.putString("HudTurn", hudTurn);
|
||||||
|
tag.putString("HudInstruction", hudInstruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadHudState(CompoundTag tag) {
|
||||||
|
hudActive = tag.getBoolean("HudActive");
|
||||||
|
hudP1HandCount = tag.getInt("HudP1HandCount");
|
||||||
|
hudP2HandCount = tag.getInt("HudP2HandCount");
|
||||||
|
hudP1Score = tag.getInt("HudP1Score");
|
||||||
|
hudP2Score = tag.getInt("HudP2Score");
|
||||||
|
hudRules = tag.getString("HudRules");
|
||||||
|
hudGameState = tag.getString("HudGameState");
|
||||||
|
hudTurn = tag.getString("HudTurn");
|
||||||
|
hudInstruction = tag.getString("HudInstruction");
|
||||||
|
}
|
||||||
|
|
||||||
private void loadRewardTakeAnimations(CompoundTag tag, HolderLookup.Provider registries) {
|
private void loadRewardTakeAnimations(CompoundTag tag, HolderLookup.Provider registries) {
|
||||||
rewardTakeAnimations.clear();
|
rewardTakeAnimations.clear();
|
||||||
if (!tag.contains("RewardTakeAnimations", Tag.TAG_COMPOUND)) {
|
if (!tag.contains("RewardTakeAnimations", Tag.TAG_COMPOUND)) {
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package com.trunksbomb.minetriad.client.hud;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.trunksbomb.minetriad.blockentity.DuelTableBlockEntity;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.neoforged.neoforge.client.event.ClientTickEvent;
|
||||||
|
import net.neoforged.neoforge.client.event.RenderGuiLayerEvent;
|
||||||
|
|
||||||
|
public final class LocalDuelHudOverlay {
|
||||||
|
private static final int SCAN_INTERVAL_TICKS = 10;
|
||||||
|
private static final int STALE_TIMEOUT_TICKS = 20;
|
||||||
|
private static final double MAX_DISTANCE_SQ = 10.0D * 10.0D;
|
||||||
|
|
||||||
|
private static BlockPos trackedTablePos;
|
||||||
|
private static int nextScanIn;
|
||||||
|
private static int staleTicksRemaining;
|
||||||
|
|
||||||
|
private LocalDuelHudOverlay() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onClientTick(ClientTickEvent.Post event) {
|
||||||
|
Minecraft minecraft = Minecraft.getInstance();
|
||||||
|
if (minecraft.level == null || minecraft.player == null) {
|
||||||
|
clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trackedTablePos != null && !isValidTrackedTable(minecraft, trackedTablePos)) {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextScanIn > 0) {
|
||||||
|
nextScanIn--;
|
||||||
|
} else {
|
||||||
|
trackedTablePos = findNearestActiveTable(minecraft);
|
||||||
|
nextScanIn = SCAN_INTERVAL_TICKS;
|
||||||
|
staleTicksRemaining = trackedTablePos == null ? 0 : STALE_TIMEOUT_TICKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trackedTablePos != null) {
|
||||||
|
staleTicksRemaining--;
|
||||||
|
if (staleTicksRemaining <= 0 && !isValidTrackedTable(minecraft, trackedTablePos)) {
|
||||||
|
clear();
|
||||||
|
} else if (isValidTrackedTable(minecraft, trackedTablePos)) {
|
||||||
|
staleTicksRemaining = STALE_TIMEOUT_TICKS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onRenderGui(RenderGuiLayerEvent.Post event) {
|
||||||
|
Minecraft minecraft = Minecraft.getInstance();
|
||||||
|
if (minecraft.level == null || minecraft.player == null || trackedTablePos == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DuelTableBlockEntity table = duelTableAt(minecraft, trackedTablePos);
|
||||||
|
if (table == null || !table.hudActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Component> lines = new ArrayList<>();
|
||||||
|
lines.add(Component.literal("P1 Cards in hand: " + table.hudP1HandCount()));
|
||||||
|
lines.add(Component.literal("P2 Cards in hand: " + table.hudP2HandCount()));
|
||||||
|
lines.add(Component.literal("Score: " + table.hudP1Score() + ":" + table.hudP2Score()));
|
||||||
|
lines.add(Component.literal("Rules: " + table.hudRules()));
|
||||||
|
lines.add(Component.literal("Game state: " + table.hudGameState()));
|
||||||
|
lines.add(Component.literal("Turn: " + table.hudTurn()));
|
||||||
|
lines.add(Component.literal("Next: " + table.hudInstruction()));
|
||||||
|
|
||||||
|
GuiGraphics guiGraphics = event.getGuiGraphics();
|
||||||
|
int x = 8;
|
||||||
|
int y = 8;
|
||||||
|
int lineHeight = 10;
|
||||||
|
int width = 0;
|
||||||
|
for (Component line : lines) {
|
||||||
|
width = Math.max(width, minecraft.font.width(line));
|
||||||
|
}
|
||||||
|
int height = lines.size() * lineHeight + 8;
|
||||||
|
guiGraphics.fill(x - 4, y - 4, x + width + 4, y + height - 4, 0x80000000);
|
||||||
|
for (int index = 0; index < lines.size(); index++) {
|
||||||
|
guiGraphics.drawString(minecraft.font, lines.get(index), x, y + index * lineHeight, 0xFFFFFF, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BlockPos findNearestActiveTable(Minecraft minecraft) {
|
||||||
|
BlockPos origin = minecraft.player.blockPosition();
|
||||||
|
BlockPos nearest = null;
|
||||||
|
double nearestDistance = MAX_DISTANCE_SQ;
|
||||||
|
for (BlockPos pos : BlockPos.betweenClosed(origin.offset(-8, -4, -8), origin.offset(8, 4, 8))) {
|
||||||
|
DuelTableBlockEntity table = duelTableAt(minecraft, pos);
|
||||||
|
if (table == null || !table.hudActive()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double distance = pos.distSqr(minecraft.player.blockPosition());
|
||||||
|
if (distance <= nearestDistance) {
|
||||||
|
nearestDistance = distance;
|
||||||
|
nearest = pos.immutable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isValidTrackedTable(Minecraft minecraft, BlockPos pos) {
|
||||||
|
DuelTableBlockEntity table = duelTableAt(minecraft, pos);
|
||||||
|
return table != null
|
||||||
|
&& table.hudActive()
|
||||||
|
&& pos.distSqr(minecraft.player.blockPosition()) <= MAX_DISTANCE_SQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DuelTableBlockEntity duelTableAt(Minecraft minecraft, BlockPos pos) {
|
||||||
|
if (minecraft.level == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BlockEntity blockEntity = minecraft.level.getBlockEntity(pos);
|
||||||
|
return blockEntity instanceof DuelTableBlockEntity duelTableBlockEntity ? duelTableBlockEntity : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void clear() {
|
||||||
|
trackedTablePos = null;
|
||||||
|
nextScanIn = 0;
|
||||||
|
staleTicksRemaining = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -108,6 +108,78 @@ public final class DuelSession {
|
|||||||
return aiVsAi;
|
return aiVsAi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int playerHandCount() {
|
||||||
|
return match.handFor(playerParticipant).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int opponentHandCount() {
|
||||||
|
return match.handFor(opponentParticipant).size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int playerScore() {
|
||||||
|
return match.scoreFor(playerParticipant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int opponentScore() {
|
||||||
|
return match.scoreFor(opponentParticipant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String rulesSummary() {
|
||||||
|
List<String> rules = new ArrayList<>();
|
||||||
|
if (match.ruleSet().sameRule()) {
|
||||||
|
rules.add("Same");
|
||||||
|
}
|
||||||
|
if (match.ruleSet().sameWallRule()) {
|
||||||
|
rules.add("Same Wall");
|
||||||
|
}
|
||||||
|
if (match.ruleSet().plusRule()) {
|
||||||
|
rules.add("Plus");
|
||||||
|
}
|
||||||
|
if (match.ruleSet().openHands()) {
|
||||||
|
rules.add("Open");
|
||||||
|
}
|
||||||
|
if (rules.isEmpty()) {
|
||||||
|
return "None";
|
||||||
|
}
|
||||||
|
return String.join(", ", rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String turnIndicator() {
|
||||||
|
return isPlayerTurn() ? "P1" : "P2";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gameStateLabel() {
|
||||||
|
return switch (phase) {
|
||||||
|
case PLAYING -> "Playing";
|
||||||
|
case PLAYER_ANIMATION, OPPONENT_ANIMATION -> "Animating";
|
||||||
|
case CLOSING_ANIMATION -> "Closing";
|
||||||
|
case OVERVIEW -> "Overview";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public String nextStepInstruction() {
|
||||||
|
if (isComplete()) {
|
||||||
|
int playerScore = playerScore();
|
||||||
|
int opponentScore = opponentScore();
|
||||||
|
String winner = playerScore == opponentScore ? "Draw" : playerScore > opponentScore ? "P1" : "P2";
|
||||||
|
if (isInOverview()) {
|
||||||
|
return opponentRewardCards().isEmpty()
|
||||||
|
? "Ready for next game"
|
||||||
|
: winner + " choosing 1 cards to keep";
|
||||||
|
}
|
||||||
|
return "Game over - " + winner + (winner.equals("Draw") ? "" : " wins");
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch (phase) {
|
||||||
|
case PLAYER_ANIMATION, OPPONENT_ANIMATION -> "Resolving animations";
|
||||||
|
case CLOSING_ANIMATION -> "Clearing board";
|
||||||
|
case OVERVIEW -> "Choose a reward card or finish";
|
||||||
|
case PLAYING -> isPlayerTurn()
|
||||||
|
? "Waiting for you to place a card"
|
||||||
|
: "Waiting for P2 to place a card";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public void enterOverview() {
|
public void enterOverview() {
|
||||||
phase = Phase.OVERVIEW;
|
phase = Phase.OVERVIEW;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ public class DuelTableBlock extends BaseEntityBlock {
|
|||||||
}
|
}
|
||||||
table.clearBoard();
|
table.clearBoard();
|
||||||
table.setParticipants(session.playerParticipantId(), session.opponentParticipantId());
|
table.setParticipants(session.playerParticipantId(), session.opponentParticipantId());
|
||||||
|
table.updateHudState(session);
|
||||||
if (aiVsAi) {
|
if (aiVsAi) {
|
||||||
player.displayClientMessage(Component.literal("AI vs AI duel started. Empty-hand click on a Duel Table launches an autoplay match.").withStyle(ChatFormatting.GOLD), false);
|
player.displayClientMessage(Component.literal("AI vs AI duel started. Empty-hand click on a Duel Table launches an autoplay match.").withStyle(ChatFormatting.GOLD), false);
|
||||||
if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
|
if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
|
||||||
@@ -144,6 +145,7 @@ public class DuelTableBlock extends BaseEntityBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
session.beginPlayerAnimation();
|
session.beginPlayerAnimation();
|
||||||
|
table.updateHudState(session);
|
||||||
table.startMoveAnimation(playerMove, DuelTableBlockEntity.OWNER_FIRST);
|
table.startMoveAnimation(playerMove, DuelTableBlockEntity.OWNER_FIRST);
|
||||||
return ItemInteractionResult.CONSUME;
|
return ItemInteractionResult.CONSUME;
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
@@ -284,6 +286,7 @@ public class DuelTableBlock extends BaseEntityBlock {
|
|||||||
DuelTableBlockEntity table = getTableEntity(level, pos);
|
DuelTableBlockEntity table = getTableEntity(level, pos);
|
||||||
if (table != null) {
|
if (table != null) {
|
||||||
session.beginClosingAnimation();
|
session.beginClosingAnimation();
|
||||||
|
table.updateHudState(session);
|
||||||
table.startClearWaveAnimation();
|
table.startClearWaveAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user