Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the modify containers rule #65

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Leukocyte provides various rules that can be applied within authorities. These r
- `hunger` controls whether players will become hungry
- `throw_items` controls whether players can throw items from their inventory
- `pickup_items` controls whether items can be picked up by players or other entities
- `modify_containers` controls whether players can interact with slots and buttons in containers or other handled screens
- `unstable_tnt` controls tnt automatically igniting when placed
- `ignite_tnt` controls whether tnt can be ignited
- `firework_explode` controls whether fireworks can explode instead of only fizzling out
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/xyz/nucleoid/leukocyte/rule/ProtectionRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public final class ProtectionRule {
public static final ProtectionRule THROW_ITEMS = register("throw_items");
public static final ProtectionRule PICKUP_ITEMS = register("pickup_items");

public static final ProtectionRule MODIFY_CONTAINERS = register("modify_containers");

public static final ProtectionRule UNSTABLE_TNT = register("unstable_tnt");
public static final ProtectionRule IGNITE_TNT = register("ignite_tnt");
public static final ProtectionRule FIREWORK_EXPLODE = register("firework_explode");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@
import net.minecraft.entity.mob.Monster;
import net.minecraft.entity.passive.AnimalEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.play.ButtonClickC2SPacket;
import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket;
import net.minecraft.registry.tag.DamageTypeTags;
import net.minecraft.screen.PlayerScreenHandler;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.TypedActionResult;
import xyz.nucleoid.leukocyte.rule.ProtectionRule;
Expand All @@ -31,6 +38,7 @@
import xyz.nucleoid.stimuli.event.item.ItemThrowEvent;
import xyz.nucleoid.stimuli.event.item.ItemUseEvent;
import xyz.nucleoid.stimuli.event.player.PlayerAttackEntityEvent;
import xyz.nucleoid.stimuli.event.player.PlayerC2SPacketEvent;
import xyz.nucleoid.stimuli.event.player.PlayerConsumeHungerEvent;
import xyz.nucleoid.stimuli.event.player.PlayerDamageEvent;
import xyz.nucleoid.stimuli.event.player.PlayerRegenerateEvent;
Expand Down Expand Up @@ -100,6 +108,20 @@ public void applyTo(ProtectionRuleMap rules, EventRegistrar events) {
this.forRule(events, rules.test(ProtectionRule.PICKUP_ITEMS))
.applySimple(ItemPickupEvent.EVENT, rule -> (player, entity, stack) -> rule);

this.forRule(events, rules.test(ProtectionRule.MODIFY_CONTAINERS))
.applySimple(PlayerC2SPacketEvent.EVENT, rule -> {
return (sender, message) -> {
if (message instanceof ClickSlotC2SPacket clickSlotPacket && sender.currentScreenHandler.syncId == clickSlotPacket.getSyncId() && !isPlayerSlot(sender, clickSlotPacket)) {
sender.currentScreenHandler.syncState();
return rule;
} else if (message instanceof ButtonClickC2SPacket) {
return rule;
}

return ActionResult.PASS;
};
});

this.forRule(events, rules.test(ProtectionRule.SPAWN_MONSTERS))
.applySimple(EntitySpawnEvent.EVENT, rule -> entity -> entity instanceof Monster ? rule : ActionResult.PASS);

Expand Down Expand Up @@ -210,4 +232,25 @@ private void applyWorldRules(ProtectionRuleMap rules, EventRegistrar events) {
this.forRule(events, rules.test(ProtectionRule.CORAL_DEATH))
.applySimple(CoralDeathEvent.EVENT, rule -> (world, pos, from, to) -> rule);
}

private static boolean isPlayerSlot(ServerPlayerEntity sender, ClickSlotC2SPacket clickSlotPacket) {
// All slots in the player screen handler are valid
ScreenHandler screenHandler = sender.currentScreenHandler;
if (screenHandler instanceof PlayerScreenHandler) return true;

// Defer to vanilla handling for invalid and special case slots
int slot = clickSlotPacket.getSlot();

if (!screenHandler.isValid(slot)) return true;
if (slot < 0) return true;

// Avoid action types that can affect both player and container slots
SlotActionType actionType = clickSlotPacket.getActionType();

if (actionType == SlotActionType.QUICK_MOVE) return false;
if (actionType == SlotActionType.PICKUP_ALL) return false;

// Check the inventory associated with the slot
return screenHandler.getSlot(slot).inventory instanceof PlayerInventory;
}
}