Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ run
runs
run-data

repo
repo
.vscode
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import mrbysco.constructionstick.containers.ContainerTrace;

public interface IContainerHandler {
public interface IContainerHandler
{
boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack);

int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack);
// Ender Chest is 0
int getSignature(Player player, ItemStack inventoryStack);

int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count);
int countItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack);

int useItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack, int count);
}
29 changes: 17 additions & 12 deletions src/main/java/mrbysco/constructionstick/basics/StickUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import mrbysco.constructionstick.api.IStickUpgrade;
import mrbysco.constructionstick.config.ConstructionConfig;
import mrbysco.constructionstick.containers.ContainerManager;
import mrbysco.constructionstick.containers.ContainerTrace;
import mrbysco.constructionstick.items.stick.ItemStick;
import mrbysco.constructionstick.stick.StickItemUseContext;
import net.minecraft.ChatFormatting;
Expand All @@ -13,6 +14,7 @@
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
Expand Down Expand Up @@ -187,18 +189,21 @@ public static int countItem(Player player, Item item) {
if (player.isCreative()) return Integer.MAX_VALUE;

int total = 0;
ContainerManager containerManager = ConstructionStick.containerManager;
List<ItemStack> inventory = StickUtil.getFullInv(player);

for (ItemStack stack : inventory) {
if (stack == null || stack.isEmpty()) continue;

if (StickUtil.stackEquals(stack, item)) {
total += stack.getCount();
} else {
int amount = containerManager.countItems(player, new ItemStack(item), stack);
if (amount == Integer.MAX_VALUE) return Integer.MAX_VALUE;
total += amount;
if(player instanceof ServerPlayer serverPlayer) {
ContainerManager containerManager = ConstructionStick.containerManager;
ContainerTrace trace = new ContainerTrace(serverPlayer);
List<ItemStack> inventory = StickUtil.getFullInv(serverPlayer);

for (ItemStack stack : inventory) {
if (stack == null || stack.isEmpty()) continue;

if (StickUtil.stackEquals(stack, item)) {
total += stack.getCount();
} else {
int amount = containerManager.countItems(serverPlayer, trace, new ItemStack(item), stack);
if (amount == Integer.MAX_VALUE) return Integer.MAX_VALUE;
total += amount;
}
}
}
return total;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import mrbysco.constructionstick.basics.StickUtil;
import mrbysco.constructionstick.items.stick.ItemStick;
import mrbysco.constructionstick.stick.StickJob;
import mrbysco.constructionstick.network.ModMessages;
import mrbysco.constructionstick.network.PacketRequestPreview;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
Expand All @@ -22,8 +22,10 @@
import java.util.Set;

public class RenderBlockPreview {
private StickJob stickJob;
private BlockHitResult lastRayTraceResult = null;
private ItemStack lastStick = ItemStack.EMPTY;
public Set<BlockPos> undoBlocks;
public Set<BlockPos> previewBlocks;

@SubscribeEvent
public void renderBlockHighlight(RenderHighlightEvent.Block event) {
Expand All @@ -38,18 +40,21 @@ public void renderBlockHighlight(RenderHighlightEvent.Block event) {
ItemStack stick = StickUtil.holdingStick(player);
if (stick == null) return;

if (!KeybindHandler.KEY_SHOW_PREVIOUS.isDown()) {
if (KeybindHandler.KEY_SHOW_PREVIOUS.isDown()) {
blocks = undoBlocks;
colorG = 1;
}
else {
// Use cached stickJob for previews of the same target pos/dir
// Exception: always update if blockCount < 2 to prevent 1-block previews when block updates
// from the last placement are lagging
if (stickJob == null || !compareRTR(stickJob.blockHitResult, target) || !(stickJob.stick.equals(stick))
|| stickJob.blockCount() < 2) {
stickJob = ItemStick.getStickJob(player, player.level(), target, stick);
if(lastRayTraceResult == null || !compareRTR(lastRayTraceResult, target) || !lastStick.equals(stick)
|| previewBlocks == null || previewBlocks.size() < 2) {
lastRayTraceResult = target;
lastStick = stick;
ModMessages.sendToServer(new PacketRequestPreview(target, stick));
}
blocks = stickJob.getBlockPositions();
} else {
blocks = undoBlocks;
colorG = 1;
blocks = previewBlocks;
}

if (blocks == null || blocks.isEmpty()) return;
Expand All @@ -72,7 +77,9 @@ public void renderBlockHighlight(RenderHighlightEvent.Block event) {
}

public void reset() {
stickJob = null;
lastRayTraceResult = null;
lastStick = ItemStack.EMPTY;
previewBlocks = null;
}

private static boolean compareRTR(BlockHitResult rtr1, BlockHitResult rtr2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import net.minecraft.world.item.ItemStack;

import java.util.ArrayList;
import java.util.List;

public class ContainerManager {
private final List<IContainerHandler> handlers;
public class ContainerManager
{
private final ArrayList<IContainerHandler> handlers;

public ContainerManager() {
handlers = new ArrayList<IContainerHandler>();
Expand All @@ -18,19 +18,31 @@ public boolean register(IContainerHandler handler) {
return handlers.add(handler);
}

public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) {
for (IContainerHandler handler : handlers) {
if (handler.matches(player, itemStack, inventoryStack)) {
return handler.countItems(player, itemStack, inventoryStack);
public int countItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack) {
for(IContainerHandler handler : handlers) {
if(handler.matches(player, itemStack, inventoryStack)) {
int sig = handler.getSignature(player, inventoryStack);
if (trace.push(sig)) {
int count = handler.countItems(player, trace, itemStack, inventoryStack);
return count;
} else {
return 0;
}
}
}
return 0;
}

public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) {
for (IContainerHandler handler : handlers) {
if (handler.matches(player, itemStack, inventoryStack)) {
return handler.useItems(player, itemStack, inventoryStack, count);
public int useItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack, int count) {
for(IContainerHandler handler : handlers) {
if(handler.matches(player, itemStack, inventoryStack)) {
int sig = handler.getSignature(player, inventoryStack);
if (trace.push(sig)) {
int remaining = handler.useItems(player, trace, itemStack, inventoryStack, count);
return remaining;
} else {
return count;
}
}
}
return count;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package mrbysco.constructionstick.containers;

import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;

public class ContainerTrace {

private final HashSet<Integer> visited = new HashSet<>();

public final ServerLevel level;
@Nullable
public final ServerPlayer player;

public ContainerTrace(ServerLevel level) {
this.level = level;
this.player = null;
visited.add(-1);
}

public ContainerTrace(ServerPlayer player) {
this.player = player;
this.level = player.serverLevel();
visited.add(-1);
}

public boolean push(int sig) {
if (visited.contains(sig)) {
return false;
}
visited.add(sig);
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import mrbysco.constructionstick.api.IContainerHandler;
import mrbysco.constructionstick.basics.StickUtil;
import mrbysco.constructionstick.containers.ContainerTrace;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
Expand All @@ -19,13 +20,18 @@ public boolean matches(Player player, ItemStack itemStack, ItemStack inventorySt
}

@Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) {
public int getSignature(Player player, ItemStack inventoryStack) {
return inventoryStack.hashCode();
}

@Override
public int countItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack) {
return getContents(inventoryStack).filter((stack) -> StickUtil.stackEquals(stack, itemStack))
.map(ItemStack::getCount).reduce(0, Integer::sum);
}

@Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) {
public int useItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack, int count) {
AtomicInteger newCount = new AtomicInteger(count);

List<ItemStack> itemStacks = getContents(inventoryStack).filter((stack -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import mrbysco.constructionstick.api.IContainerHandler;
import mrbysco.constructionstick.basics.StickUtil;
import mrbysco.constructionstick.containers.ContainerTrace;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.capabilities.Capabilities;
Expand All @@ -14,7 +15,12 @@ public boolean matches(Player player, ItemStack itemStack, ItemStack inventorySt
}

@Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) {
public int getSignature(Player player, ItemStack inventoryStack) {
return inventoryStack.hashCode();
}

@Override
public int countItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack) {
IItemHandler itemHandler = inventoryStack.getCapability(Capabilities.ItemHandler.ITEM);
if (itemHandler == null) return 0;

Expand All @@ -30,7 +36,7 @@ public int countItems(Player player, ItemStack itemStack, ItemStack inventorySta
}

@Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) {
public int useItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack, int count) {
IItemHandler itemHandler = inventoryStack.getCapability(Capabilities.ItemHandler.ITEM);
if (itemHandler == null) return 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import mrbysco.constructionstick.api.IContainerHandler;
import mrbysco.constructionstick.basics.StickUtil;
import mrbysco.constructionstick.containers.ContainerTrace;
import net.minecraft.core.NonNullList;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.entity.player.Player;
Expand All @@ -19,7 +20,12 @@ public boolean matches(Player player, ItemStack itemStack, ItemStack inventorySt
}

@Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) {
public int getSignature(Player player, ItemStack inventoryStack) {
return inventoryStack.hashCode();
}

@Override
public int countItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack) {
int count = 0;

for (ItemStack stack : getItemList(inventoryStack)) {
Expand All @@ -30,7 +36,7 @@ public int countItems(Player player, ItemStack itemStack, ItemStack inventorySta
}

@Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) {
public int useItems(Player player, ContainerTrace trace, ItemStack itemStack, ItemStack inventoryStack, int count) {
NonNullList<ItemStack> itemList = getItemList(inventoryStack);
boolean changed = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public static void registerPayloads(final RegisterPayloadHandlersEvent event) {
registrar.playToClient(PacketUndoBlocks.ID, PacketUndoBlocks.CODEC, PacketUndoBlocks.Handler::handle);
registrar.playToServer(PacketQueryUndo.ID, PacketQueryUndo.CODEC, PacketQueryUndo.Handler::handle);
registrar.playToServer(PacketStickOption.ID, PacketStickOption.CODEC, PacketStickOption.Handler::handle);
registrar.playToServer(PacketRequestPreview.ID, PacketRequestPreview.CODEC, PacketRequestPreview.Handler::handle);
registrar.playToClient(PacketPreviewResult.ID, PacketPreviewResult.CODEC, PacketPreviewResult.Handler::handle);
}

public static void sendToServer(CustomPacketPayload message) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package mrbysco.constructionstick.network;

import mrbysco.constructionstick.ConstructionStick;
import mrbysco.constructionstick.client.ClientHandler;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.server.level.ServerPlayer;
import net.neoforged.neoforge.network.handling.IPayloadContext;

import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;


public record PacketPreviewResult(HashSet<BlockPos> previewBlocks) implements CustomPacketPayload {
public static final StreamCodec<FriendlyByteBuf, PacketPreviewResult> CODEC = CustomPacketPayload.codec(
PacketPreviewResult::encode,
PacketPreviewResult::new);
public static final Type<PacketPreviewResult> ID = new Type<>(ConstructionStick.modLoc("preview_result"));

public PacketPreviewResult(FriendlyByteBuf buffer) {
this(getSet(buffer));
}

public PacketPreviewResult(Set<BlockPos> previewBlocks) {
this(new HashSet<>(previewBlocks));
}

private static HashSet<BlockPos> getSet(FriendlyByteBuf buffer) {
HashSet<BlockPos> previewBlocks = new HashSet<>();

while (buffer.isReadable()) {
previewBlocks.add(buffer.readBlockPos());
}
return previewBlocks;
}

public void encode(FriendlyByteBuf buffer) {
for (BlockPos pos : previewBlocks) {
buffer.writeBlockPos(pos);
}
}

@Override
public Type<? extends CustomPacketPayload> type() {
return ID;
}

public static class Handler {
public static void handle(final PacketPreviewResult msg, final IPayloadContext ctx) {
ctx.enqueueWork(() -> {
ClientHandler.renderBlockPreview.previewBlocks = msg.previewBlocks;
})
.exceptionally(e -> {
ctx.disconnect(Component.translatable("constructionstick.networking.preview_result.failed", e.getMessage()));
return null;
});

}
}
}
Loading