C
Chrisliebaer
Guest
Mit Abstand das teuerste Event in der Bukkit API ist das PlayerMoveEvent. Es wird mehrfach in der Sekunde gefeuert und lässt sich nicht weiter aufteilen. Jeder Listener muss checken, ob er sich für das Event interessiert. Oftmals interessiert man sicht jedoch gar nicht für alle Teile des Events. Viel mehr interessiert man sich lediglich dann, wenn der Spieler einen neuen Block betreten hat. Daher hab ich vor einiger Zeit einen kleinen Event Listener geschrieben.
Nachdem er als Listener registriert wurde, erzeugt er immer dann, wenn ein Spieler einen neuen Block betritt ein PlayerBlockMoveEvent. Das ist insofern von Vorteil, da dadurch nur einmal geprüft wird, ob ein Spieler einen neuen Block betreten hat. Die Anzahl der gefeuerten Events ließ sich dadurch bei meinem Test deutlich verringern. Natürlich macht das ganze erst dann Sinn, wenn mehrere Plugins so ein System nutzen würden.
Ich wollte das ganze sogar noch weiter treiben und ein eigenes Kollisionssystem für Trigger-Zonen schreiben, um selbst das Verarbeiten von mehreren tausend solcher Events an verschiedenen Orten effektiv zu machen. Da ich aber inzwischen von der Bukkit-API echt angewiedert bin, wird das vermutlich nicht passieren. Falls aber jemand daran interesse hat, so könnte ich ein paar Stickwörter beitragen und auch ein paar eigene Ideen, wie man das machen könnte.
Lizensiert zur freien Verwendung als: CC-Zero (damit Cabraca schlafen kann
)
Nachdem er als Listener registriert wurde, erzeugt er immer dann, wenn ein Spieler einen neuen Block betritt ein PlayerBlockMoveEvent. Das ist insofern von Vorteil, da dadurch nur einmal geprüft wird, ob ein Spieler einen neuen Block betreten hat. Die Anzahl der gefeuerten Events ließ sich dadurch bei meinem Test deutlich verringern. Natürlich macht das ganze erst dann Sinn, wenn mehrere Plugins so ein System nutzen würden.
Ich wollte das ganze sogar noch weiter treiben und ein eigenes Kollisionssystem für Trigger-Zonen schreiben, um selbst das Verarbeiten von mehreren tausend solcher Events an verschiedenen Orten effektiv zu machen. Da ich aber inzwischen von der Bukkit-API echt angewiedert bin, wird das vermutlich nicht passieren. Falls aber jemand daran interesse hat, so könnte ich ein paar Stickwörter beitragen und auch ein paar eigene Ideen, wie man das machen könnte.
Code:
import java.util.WeakHashMap;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
public class MoveEventFilter implements Listener
{
public static class PlayerBlockMoveEvent extends PlayerMoveEvent
{
public PlayerBlockMoveEvent(PlayerMoveEvent pEvent)
{
super(pEvent.getPlayer(), pEvent.getFrom(), pEvent.getTo());
}
}
private static class BlockPosition
{
public int x;
public int y;
public int z;
public World world;
}
private Server mServer;
private WeakHashMap<Player, BlockPosition> mLastPosition = new WeakHashMap<Player, BlockPosition>();
public MoveEventFilter(Server pServer)
{
mServer = pServer;
}
@EventHandler
public void onPlayerMove(PlayerMoveEvent pEvent)
{
if(pEvent.isCancelled() || pEvent instanceof PlayerBlockMoveEvent)
{
return;
}
BlockPosition lastPos = mLastPosition.get(pEvent.getPlayer());
Location currentPos = pEvent.getTo();
boolean fireEvent = false;
if(lastPos == null)
{
lastPos = new BlockPosition();
mLastPosition.put(pEvent.getPlayer(), lastPos);
fireEvent = true;
}
else if(lastPos.x != currentPos.getBlockX() || lastPos.z != currentPos.getBlockZ() || lastPos.y != currentPos.getBlockY())
{
fireEvent = true;
}
else if(lastPos.world != currentPos.getWorld())
{
fireEvent = true;
}
if(fireEvent)
{
// make sure that our event is synchronous
assert !pEvent.isAsynchronous();
// fire event
PlayerBlockMoveEvent event = new PlayerBlockMoveEvent(pEvent);
mServer.getPluginManager().callEvent(event);
// check event state and only update new position if event does not gets canceled
if(!event.isCancelled())
{
// update new position
lastPos.world = currentPos.getWorld();
lastPos.x = currentPos.getBlockX();
lastPos.y = currentPos.getBlockY();
lastPos.z = currentPos.getBlockZ();
}
}
}
}
Lizensiert zur freien Verwendung als: CC-Zero (damit Cabraca schlafen kann
Zuletzt bearbeitet von einem Moderator: