added Anti Player Loot despawn #16
No files matched your search
@@ -0,0 +1,14 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.antiPlayerLootDespawn;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.core.appliance.Appliance;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AntiPlayerLootDespawn extends Appliance {
|
||||||
|
@Override
|
||||||
|
protected @NotNull List<Listener> listeners() {
|
||||||
|
return List.of(new AntiPlayerLootDespawnListener());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package eu.mhsl.craftattack.spawn.craftattack.appliances.metaGameplay.antiPlayerLootDespawn;
|
||||||
|
|
||||||
|
import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.entity.Item;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.entity.ItemDespawnEvent;
|
||||||
|
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class AntiPlayerLootDespawnListener extends ApplianceListener<AntiPlayerLootDespawn> {
|
||||||
|
MineTec marked this conversation as resolved
Outdated
|
|||||||
|
private static final int extraCycles = 5;
|
||||||
|
MineTec marked this conversation as resolved
Outdated
MineTec
commented
alle Konstanten zur appliance, nicht in den listener alle Konstanten zur appliance, nicht in den listener
|
|||||||
|
private static final String namespace = AntiPlayerLootDespawnListener.class.getSimpleName().toLowerCase(Locale.ROOT);
|
||||||
|
public static NamespacedKey cyclesKey = new NamespacedKey(namespace, "item_deaths_cycles".toLowerCase());
|
||||||
|
private Location lastDeathLocation;
|
||||||
|
MineTec marked this conversation as resolved
Outdated
MineTec
commented
dieses Vorgehen wird schwirig, oder sogar garnicht mehr funktionieren, sobald mehr als ein Spieler Pro Spiel-Tick sterben sollten... siehe unten für Lösung. dieses Vorgehen wird schwirig, oder sogar garnicht mehr funktionieren, sobald mehr als ein Spieler Pro Spiel-Tick sterben sollten...
siehe unten für Lösung.
|
|||||||
|
private long lastDeathTick = -1;
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onDeath(PlayerDeathEvent event) {
|
||||||
|
this.lastDeathLocation = event.getEntity().getLocation();
|
||||||
|
this.lastDeathTick = event.getPlayer().getWorld().getGameTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onItemSpawn(ItemSpawnEvent event) {
|
||||||
|
MineTec marked this conversation as resolved
Outdated
MineTec
commented
dieser Weg ist sehr sehr Hacky... Und es gibt einen viel besseren Weg: es gibt PlayerDeathEvent#getDrops. Dort können direkt alle ItemStacks welche resultiertend aus dem Tod gedroppt werden. Kein Distance-Check, keine Race conditions, mit Items die zufällit normal in dem Bereich im selbigen Tick gedroppt werden. Sowas wie Die Variablen und der Listener fallen weg. dieser Weg ist sehr sehr Hacky... Und es gibt einen viel besseren Weg: es gibt PlayerDeathEvent#getDrops. Dort können direkt alle ItemStacks welche resultiertend aus dem Tod gedroppt werden. Kein Distance-Check, keine Race conditions, mit Items die zufällit normal in dem Bereich im selbigen Tick gedroppt werden.
Sowas wie `event.getDrops().forEach(item -> item.editPersistentDataContainer(persistentDataContainer -> persistentDataContainer.set(cyclesKey, PersistentDataType.INTEGER, extraCycles));`
Die Variablen und der Listener fallen weg.
|
|||||||
|
Item item = event.getEntity();
|
||||||
|
|
||||||
|
if(this.lastDeathLocation == null) return;
|
||||||
|
if(!item.getWorld().equals(this.lastDeathLocation.getWorld())) return;
|
||||||
|
if (item.getWorld().getGameTime() != this.lastDeathTick) return;
|
||||||
|
if(item.getLocation().distanceSquared(this.lastDeathLocation) > 9) return;
|
||||||
|
|
||||||
|
item.getPersistentDataContainer().set(cyclesKey, PersistentDataType.INTEGER, extraCycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onItemDespawn(ItemDespawnEvent event) {
|
||||||
|
PersistentDataContainer data = event.getEntity().getPersistentDataContainer();
|
||||||
|
Integer cycles = data.get(cyclesKey, PersistentDataType.INTEGER);
|
||||||
|
MineTec marked this conversation as resolved
Outdated
MineTec
commented
statt dem Nullcheck wäre ein PersistentDataContainer#getOrDefault schöner mit statt dem Nullcheck wäre ein PersistentDataContainer#getOrDefault schöner mit `0` als default...
|
|||||||
|
|
||||||
|
if(cycles == null || cycles <= 0) return;
|
||||||
|
|
||||||
|
data.set(cyclesKey, PersistentDataType.INTEGER, cycles - 1);
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
die klasse kann package-private sein, dann sieht nur die Appliance den Listener, und nicht das ganze Projekt. Dazu einfach das Public ersatzlos wegnehmen.