Skip to content

Commit

Permalink
fix(trigger): drop items when inventory is full
Browse files Browse the repository at this point in the history
Signed-off-by: SettingDust <[email protected]>
  • Loading branch information
SettingDust committed Jun 5, 2022
1 parent 00c01ba commit cf6eb2d
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@

import org.spongepowered.api.Sponge;
import org.spongepowered.api.block.transaction.Operations;
import org.spongepowered.api.data.Keys;
import org.spongepowered.api.data.value.Value;
import org.spongepowered.api.entity.EntityTypes;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.block.ChangeBlockEvent;
import org.spongepowered.api.event.filter.Getter;
import org.spongepowered.api.scheduler.Task;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.util.Ticks;
import org.spongepowered.api.world.BlockChangeFlags;
import org.spongepowered.api.world.server.ServerWorld;
import org.spongepowered.plugin.PluginContainer;
Expand Down Expand Up @@ -55,12 +51,7 @@ public void onChangeBlock(ChangeBlockEvent.All event, @Getter("world") ServerWor
.plugin(plugin)
.execute(() -> it.restore(true, BlockChangeFlags.DEFAULT_PLACEMENT))
.build()),
() -> {
final var item = location.createEntity(EntityTypes.ITEM.get());
item.offer(Value.mutableOf(Keys.ITEM_STACK_SNAPSHOT, processedItem));
item.offer(Value.mutableOf(Keys.PICKUP_DELAY, Ticks.of(40L)));
location.spawnEntity(item);
});
() -> location.spawnEntity(ItemUtils.droppedItem(processedItem, location)));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.google.inject.Singleton;
import net.kyori.adventure.audience.Audience;
import team.ebi.epicbanitem.EpicBanItem;
import team.ebi.epicbanitem.util.InventoryUtils;

@Singleton
public class EquipRestrictionTrigger extends EBIRestrictionTrigger {
Expand All @@ -45,22 +46,27 @@ public void onChangeEntityEquipment(
final var equipmentGroup = equipmentType.group();
if (!equipmentGroup.equals(EquipmentGroups.WORN.get())) return;
final var item = transaction.finalReplacement();
final var cause = event.cause();
if (item.isEmpty()) return;
// TODO change the cancel
final var location = entity.serverLocation();
final var cause = event.cause();
Optional<ItemStackSnapshot> processed = this.processItemCancellable(
event,
entity.serverLocation().world(),
location.world(),
cause.first(Subject.class).orElse(null),
cause.first(Audience.class).orElse(null),
item);

if (processed.isPresent()) {
if (event.isCancelled()) carrier.inventory().offer(processed.get().createStack());
else transaction.setCustom(processed.get());
if (event.isCancelled() || slot.isValidItem(processed.get().type()))
location.spawnEntities(InventoryUtils.offerOrDrop(
carrier.inventory(), location, processed.get().createStack()));
else if (!event.isCancelled()) transaction.setCustom(processed.get());
} else {
if (event.isCancelled())
carrier.inventory().offer(transaction.defaultReplacement().createStack());
location.spawnEntities(InventoryUtils.offerOrDrop(
carrier.inventory(),
location,
transaction.defaultReplacement().createStack()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,27 @@
package team.ebi.epicbanitem.trigger;

import org.spongepowered.api.Sponge;
import org.spongepowered.api.event.Event;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.entity.SpawnEntityEvent;
import org.spongepowered.api.event.filter.cause.Last;
import org.spongepowered.api.event.filter.cause.First;
import org.spongepowered.api.event.network.ServerSideConnectionEvent;
import org.spongepowered.api.item.inventory.Carrier;
import org.spongepowered.api.item.inventory.ItemStackSnapshot;
import org.spongepowered.api.item.inventory.slot.FilteringSlot;
import org.spongepowered.api.item.inventory.type.CarriedInventory;
import org.spongepowered.api.scheduler.Task;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.util.Ticks;
import org.spongepowered.api.world.Locatable;
import org.spongepowered.api.world.server.ServerLocation;
import org.spongepowered.api.world.server.ServerWorld;
import org.spongepowered.plugin.PluginContainer;

import com.google.inject.Inject;
import net.kyori.adventure.audience.Audience;
import team.ebi.epicbanitem.EpicBanItem;
import team.ebi.epicbanitem.util.InventoryUtils;

public class JoinRestrictionTrigger extends EBIRestrictionTrigger {
@Inject
Expand All @@ -31,40 +37,47 @@ public JoinRestrictionTrigger() {
}

@Listener
public void onSpawnEntity(SpawnEntityEvent.Pre event, @Last ServerWorld world) {
public void onSpawnEntity(
final SpawnEntityEvent.Pre event, final @First ServerWorld world, final @First Locatable locatable) {
final var cause = event.cause();
final var audience = cause.first(Audience.class).orElse(null);
final var subject = cause.first(Subject.class).orElse(null);
final var location = locatable.serverLocation();
event.entities().stream()
.filter(Carrier.class::isInstance)
.map(it -> ((Carrier) it).inventory())
.flatMap(it -> it.slots().stream())
.filter(it -> it.freeCapacity() == 0)
.forEach(it -> this.processItem(
event, world, subject, audience, it.peek().createSnapshot())
.map(ItemStackSnapshot::createStack)
.ifPresent(it::set));
.forEach(inventory -> handleInventory(event, world, audience, subject, location, inventory));
}

@Listener
public void onServerSideConnectionJoin(ServerSideConnectionEvent.Join event) {
public void onServerSideConnectionJoin(final ServerSideConnectionEvent.Join event) {
final var player = event.player();
final var world = player.world();
final var location = player.serverLocation();
final var inventory = player.inventory();
Sponge.server()
.scheduler()
.submit(Task.builder()
.plugin(plugin)
.delay(Ticks.of(1L))
.execute(() -> player.inventory().slots().stream()
.filter(it -> it.freeCapacity() == 0)
.forEach(it -> this.processItem(
event,
world,
player,
player,
it.peek().createSnapshot())
.map(ItemStackSnapshot::createStack)
.ifPresent(it::set)))
.execute(() -> handleInventory(event, world, player, player, location, inventory))
.build());
}

private void handleInventory(
final Event event,
final ServerWorld world,
final Audience audience,
final Subject subject,
final ServerLocation location,
final CarriedInventory<? extends Carrier> inventory) {
inventory.slots().stream().filter(it -> it.freeCapacity() == 0).forEach(it -> this.processItem(
event, world, subject, audience, it.peek().createSnapshot())
.map(ItemStackSnapshot::createStack)
.ifPresent(item -> {
if (it instanceof FilteringSlot slot && slot.isValidItem(item))
location.spawnEntities(InventoryUtils.offerOrDrop(inventory, location, item));
else it.set(item);
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import net.kyori.adventure.audience.Audience;
import team.ebi.epicbanitem.EpicBanItem;
import team.ebi.epicbanitem.util.InventoryUtils;

public class PickupRestrictionTrigger extends EBIRestrictionTrigger {
public PickupRestrictionTrigger() {
Expand Down Expand Up @@ -59,7 +60,9 @@ public void onChangeInventoryPickup(
item.offer(Value.mutableOf(Keys.ITEM_STACK_SNAPSHOT, processed.get()));
item.offer(Value.mutableOf(Keys.PICKUP_DELAY, Ticks.of(40L)));
location.spawnEntity(item);
} else inventory.offer(processed.get().createStack());
} else
InventoryUtils.offerOrDrop(
inventory, location, processed.get().createStack());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@
import java.util.concurrent.atomic.AtomicBoolean;

import org.spongepowered.api.block.transaction.Operations;
import org.spongepowered.api.data.Keys;
import org.spongepowered.api.data.value.Value;
import org.spongepowered.api.entity.EntityTypes;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.block.ChangeBlockEvent;
import org.spongepowered.api.event.filter.Getter;
import org.spongepowered.api.item.inventory.Carrier;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.util.Ticks;
import org.spongepowered.api.world.server.ServerWorld;

import net.kyori.adventure.audience.Audience;
import team.ebi.epicbanitem.EpicBanItem;
import team.ebi.epicbanitem.util.InventoryUtils;
import team.ebi.epicbanitem.util.ItemUtils;

public class PlaceRestrictionTrigger extends EBIRestrictionTrigger {
Expand All @@ -42,20 +39,17 @@ public void onChangeBlock(ChangeBlockEvent.All event, @Getter("world") ServerWor
this.processBlockCancellable(event, world, subject, audience, finalReplacement, ignored -> {
transaction.invalidate();
cancelled.set(true);
carrier.ifPresent(
it -> ItemUtils.fromBlock(finalReplacement).ifPresent(it.inventory()::offer));
carrier.ifPresent(it -> ItemUtils.fromBlock(finalReplacement)
.ifPresent(item -> InventoryUtils.offerOrDrop(it.inventory(), location, item)));
});
if (processed.isPresent() && !cancelled.get()) {
final var processedItem = processed.get();
final var blockType = processedItem.type().block();
blockType
.flatMap(ignored -> ItemUtils.toBlock(processedItem, location, finalReplacement.state()))
.ifPresentOrElse(transaction::setCustom, () -> {
final var item = location.createEntity(EntityTypes.ITEM.get());
item.offer(Value.mutableOf(Keys.ITEM_STACK_SNAPSHOT, processedItem));
item.offer(Value.mutableOf(Keys.PICKUP_DELAY, Ticks.of(40L)));
location.spawnEntity(item);
});
.ifPresentOrElse(
transaction::setCustom,
() -> location.spawnEntity(ItemUtils.droppedItem(processedItem, location)));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.google.inject.Singleton;
import net.kyori.adventure.audience.Audience;
import team.ebi.epicbanitem.EpicBanItem;
import team.ebi.epicbanitem.util.InventoryUtils;

@Singleton
public class StoreRestrictionTrigger extends EBIRestrictionTrigger {
Expand Down Expand Up @@ -95,6 +96,7 @@ public void onClickContainer(
@Getter("transactions") List<SlotTransaction> transactions,
@Getter("cursorTransaction") Transaction<ItemStackSnapshot> cursorTransaction) {
final var world = player.world();
final var location = player.serverLocation();
final var cancelled = new AtomicBoolean(false);
final var containerSlots =
transactions.stream().filter(IS_STANDARD_INVENTORY.negate()).toList();
Expand Down Expand Up @@ -136,7 +138,10 @@ public void onClickContainer(
.createSnapshot());
} else {
transaction.setCustom(ItemStack.empty());
fallbackInventory.offer(processed.get().createStack());
InventoryUtils.offerOrDrop(
fallbackInventory,
location,
processed.get().createStack());
}
} else transaction.setCustom(processed.get().createStack());
} else if (cancelled.get()) event.setCancelled(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.google.common.util.concurrent.Atomics;
import net.kyori.adventure.audience.Audience;
import team.ebi.epicbanitem.EpicBanItem;
import team.ebi.epicbanitem.util.InventoryUtils;

public class ThrowRestrictionTrigger extends EBIRestrictionTrigger {
public ThrowRestrictionTrigger() {
Expand All @@ -30,8 +31,10 @@ public void onDropItemDispense(final DropItemEvent.Dispense event) {
final var subject = cause.last(Subject.class).orElse(null);
final var hasInventory = event instanceof ChangeInventoryEvent;
final var world = Atomics.<ServerWorld>newReference(null);
final var inventory = hasInventory ? ((ChangeInventoryEvent) event).inventory() : null;
event.filterEntities(entity -> {
if (world.get() == null) world.set(entity.serverLocation().world());
final var location = entity.serverLocation();
if (world.get() == null) world.set(location.world());
if (!(entity instanceof Item item)) return true;
final var mutable = item.item();
final var snapshot = mutable.get();
Expand All @@ -45,9 +48,8 @@ public void onDropItemDispense(final DropItemEvent.Dispense event) {
if (processed.isPresent()) {
item.offer(mutable.set(processed.get()));
if (hasInventory && cancelled.get())
((ChangeInventoryEvent) event)
.inventory()
.offer(processed.get().createStack());
InventoryUtils.offerOrDrop(
inventory, location, processed.get().createStack());
}

return !cancelled.get();
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/team/ebi/epicbanitem/util/InventoryUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2022 EpicBanItem Team. All Rights Reserved.
*
* This file is part of EpicBanItem, licensed under the GNU GENERAL PUBLIC LICENSE Version 3 (GPL-3.0)
*/
package team.ebi.epicbanitem.util;

import java.util.List;

import org.spongepowered.api.entity.Item;
import org.spongepowered.api.item.inventory.Inventory;
import org.spongepowered.api.item.inventory.ItemStack;
import org.spongepowered.api.item.inventory.transaction.InventoryTransactionResult;
import org.spongepowered.api.world.server.ServerLocation;

import com.google.common.collect.Lists;

public final class InventoryUtils {
public static List<Item> offerOrDrop(Inventory inventory, ServerLocation location, ItemStack... item) {
final var result = inventory.offer(item);
List<Item> items = Lists.newArrayList();
if (!result.type().equals(InventoryTransactionResult.Type.SUCCESS))
items = result.rejectedItems().stream()
.map(it -> ItemUtils.droppedItem(it, location))
.toList();
return items;
}
}
11 changes: 11 additions & 0 deletions src/main/java/team/ebi/epicbanitem/util/ItemUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@
import org.spongepowered.api.data.Keys;
import org.spongepowered.api.data.persistence.DataQuery;
import org.spongepowered.api.data.type.PistonTypes;
import org.spongepowered.api.data.value.Value;
import org.spongepowered.api.entity.EntityTypes;
import org.spongepowered.api.entity.Item;
import org.spongepowered.api.item.ItemTypes;
import org.spongepowered.api.item.inventory.ItemStack;
import org.spongepowered.api.item.inventory.ItemStackSnapshot;
import org.spongepowered.api.plugin.PluginManager;
import org.spongepowered.api.registry.RegistryTypes;
import org.spongepowered.api.util.Ticks;
import org.spongepowered.api.world.server.ServerLocation;

import com.google.common.collect.Maps;
Expand Down Expand Up @@ -118,4 +122,11 @@ public static Optional<BlockSnapshot> toBlock(
return block;
});
}

public static Item droppedItem(final ItemStackSnapshot item, final ServerLocation location) {
final var entity = location.createEntity(EntityTypes.ITEM.get());
entity.offer(Value.mutableOf(Keys.ITEM_STACK_SNAPSHOT, item));
entity.offer(Value.mutableOf(Keys.PICKUP_DELAY, Ticks.of(40L)));
return entity;
}
}

0 comments on commit cf6eb2d

Please sign in to comment.