Kleiner Codefetzen: Optimiertes PlayerMoveEvent

Dieses Thema im Forum "Programmierung" wurde erstellt von Chrisliebaer, 3. August 2013.

  1. Chrisliebaer
    Online

    Chrisliebaer

    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.

    Code (Text):
    1. import java.util.WeakHashMap;
    2.  
    3. import org.bukkit.Location;
    4. import org.bukkit.Server;
    5. import org.bukkit.World;
    6. import org.bukkit.entity.Player;
    7. import org.bukkit.event.EventHandler;
    8. import org.bukkit.event.Listener;
    9. import org.bukkit.event.player.PlayerMoveEvent;
    10.  
    11. public class MoveEventFilter implements Listener
    12. {
    13.     public static class PlayerBlockMoveEvent extends PlayerMoveEvent
    14.     {
    15.         public PlayerBlockMoveEvent(PlayerMoveEvent pEvent)
    16.         {
    17.             super(pEvent.getPlayer(), pEvent.getFrom(), pEvent.getTo());
    18.         }
    19.     }
    20.    
    21.     private static class BlockPosition
    22.     {
    23.         public int x;
    24.         public int y;
    25.         public int z;
    26.         public World world;
    27.     }
    28.    
    29.     private Server mServer;
    30.     private WeakHashMap<Player, BlockPosition> mLastPosition = new WeakHashMap<Player, BlockPosition>();
    31.    
    32.     public MoveEventFilter(Server pServer)
    33.     {
    34.         mServer = pServer;
    35.     }
    36.    
    37.     @EventHandler
    38.     public void onPlayerMove(PlayerMoveEvent pEvent)
    39.     {
    40.         if(pEvent.isCancelled() || pEvent instanceof PlayerBlockMoveEvent)
    41.         {
    42.             return;
    43.         }
    44.        
    45.         BlockPosition lastPos = mLastPosition.get(pEvent.getPlayer());
    46.         Location currentPos = pEvent.getTo();
    47.         boolean fireEvent = false;
    48.        
    49.         if(lastPos == null)
    50.         {
    51.             lastPos = new BlockPosition();
    52.             mLastPosition.put(pEvent.getPlayer(), lastPos);
    53.             fireEvent = true;
    54.         }
    55.         else if(lastPos.x != currentPos.getBlockX() || lastPos.z != currentPos.getBlockZ() || lastPos.y != currentPos.getBlockY())
    56.         {
    57.             fireEvent = true;
    58.         }
    59.         else if(lastPos.world != currentPos.getWorld())
    60.         {
    61.             fireEvent = true;
    62.         }
    63.        
    64.         if(fireEvent)
    65.         {
    66.             // make sure that our event is synchronous
    67.             assert !pEvent.isAsynchronous();
    68.            
    69.             // fire event
    70.             PlayerBlockMoveEvent event = new PlayerBlockMoveEvent(pEvent);
    71.             mServer.getPluginManager().callEvent(event);
    72.  
    73.             // check event state and only update new position if event does not gets canceled
    74.             if(!event.isCancelled())
    75.             {
    76.                 // update new position
    77.                 lastPos.world = currentPos.getWorld();
    78.                 lastPos.x = currentPos.getBlockX();
    79.                 lastPos.y = currentPos.getBlockY();
    80.                 lastPos.z = currentPos.getBlockZ();
    81.             }
    82.         }
    83.     }
    84. }
    Lizensiert zur freien Verwendung als: CC-Zero (damit Cabraca schlafen kann ;))
     
    #1
  2. Nexus15
    Offline

    Nexus15

    Registriert seit:
    30. September 2012
    Beiträge:
    91
    Danke, werde ich bei bedarf definitiv anwenden. :)
     
    #2
  3. Cabraca
    Online

    Cabraca

    Ich vermute jetzt einfach mal GPL?
     
    #3