<s> import time , struct , os , StringIO , datetime , json <EOL> NAME = "<STR_LIT>" <EOL> ID = "<STR_LIT>" <EOL> VERSION = ( <NUM_LIT:0> , <NUM_LIT:1> ) <EOL> SUMMARY = "<STR_LIT>" <EOL> DESCRIPTION = SUMMARY + "<STR_LIT>" <EOL> class Main : <EOL> def __init__ ( self , api , log ) : <EOL> self . api = api <EOL> self . minecraft = api . minecraft <EOL> self . log = log <EOL> self . time = <NUM_LIT:0> <EOL> self . toggled = [ ] <EOL> def onEnable ( self ) : <EOL> self . api . registerEvent ( "<STR_LIT>" , self . breakBlock ) <EOL> self . api . registerEvent ( "<STR_LIT>" , self . placeBlock ) <EOL> self . api . registerEvent ( "<STR_LIT>" , self . timer ) <EOL> self . api . registerEvent ( "<STR_LIT>" , self . onServerStart ) <EOL> self . api . registerCommand ( "<STR_LIT>" , self . _sb ) <EOL> if self . minecraft . isServerStarted ( ) : <EOL> self . onServerStart ( { } ) <EOL> def onDisable ( self ) : <EOL> self . logger . flush ( ) <EOL> def onServerStart ( self , payload ) : <EOL> self . logger = Logger ( self . minecraft . getWorldName ( ) ) <EOL> self . logger . init ( ) <EOL> def timer ( self , payload ) : <EOL> self . time += <NUM_LIT:1> <EOL> if self . time == <NUM_LIT> * <NUM_LIT:2> : <EOL> self . logger . flush ( ) <EOL> self . time = <NUM_LIT:0> <EOL> def breakBlock ( self , payload ) : <EOL> player = payload [ "<STR_LIT>" ] <EOL> x , y , z = payload [ "<STR_LIT>" ] <EOL> uuid = player . uuid <EOL> if player . name in self . toggled : <EOL> actions = self . lookupBlock ( x , y , z ) <EOL> found = False <EOL> for action in actions : <EOL> self . displayEntry ( player , action ) <EOL> if len ( actions ) < <NUM_LIT:1> : <EOL> player . message ( { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT>" : "<STR_LIT>" } ) <EOL> else : <EOL> player . message ( { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT>" : "<STR_LIT>" , "<STR_LIT>" : True } ) <EOL> return False <EOL> else : <EOL> self . logger . dig_block ( uuid , x , y , z , - <NUM_LIT:1> , <NUM_LIT:0> ) <EOL> def placeBlock ( self , payload ) : <EOL> if payload [ "<STR_LIT>" ] == None : return <EOL> player = payload [ "<STR_LIT>" ] <EOL> x , y , z = payload [ "<STR_LIT>" ] <EOL> uuid = player . uuid <EOL> if player . name in self . toggled : <EOL> actions = self . lookupBlock ( x , y , z ) <EOL> found = False <EOL> for action in actions : <EOL> self . displayEntry ( player , action ) <EOL> if len ( actions ) < <NUM_LIT:1> : <EOL> player . message ( { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT>" : "<STR_LIT>" } ) <EOL> else : <EOL> player . message ( { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT>" : "<STR_LIT>" , "<STR_LIT>" : True } ) <EOL> return False <EOL> else : <EOL> if payload [ "<STR_LIT>" ] [ "<STR_LIT:id>" ] < <NUM_LIT:255> : <EOL> self . logger . place_block ( uuid , x , y , z , payload [ "<STR_LIT>" ] [ "<STR_LIT:id>" ] , payload [ "<STR_LIT>" ] [ "<STR_LIT>" ] ) <EOL> def localize ( self , p ) : <EOL> return ( ( ( p [ <NUM_LIT:0> ] / <NUM_LIT> ) - int ( p [ <NUM_LIT:0> ] / <NUM_LIT> ) ) * <NUM_LIT> , p [ <NUM_LIT:1> ] , ( ( p [ <NUM_LIT:2> ] / <NUM_LIT> ) - int ( p [ <NUM_LIT:2> ] / <NUM_LIT> ) ) * <NUM_LIT> ) <EOL> def deny ( self , player ) : <EOL> if player . isOp ( ) : return True <EOL> else : <EOL> player . message ( "<STR_LIT>" ) <EOL> return False <EOL> def _sb ( self , player , args ) : <EOL> if not self . deny ( player ) : return <EOL> if len ( args ) > <NUM_LIT:0> : <EOL> subcommand = args [ <NUM_LIT:0> ] <EOL> if subcommand == "<STR_LIT>" : <EOL> radius = args [ <NUM_LIT:1> ] <EOL> player . message ( "<STR_LIT>" ) <EOL> elif subcommand == "<STR_LIT>" : <EOL> if player . username in self . toggled : <EOL> self . toggled . remove ( player . username ) <EOL> player . message ( "<STR_LIT>" ) <EOL> else : <EOL> self . toggled . append ( player . username ) <EOL> player . message ( "<STR_LIT>" ) <EOL> elif subcommand == "<STR_LIT>" : <EOL> x , y , z = int ( args [ <NUM_LIT:1> ] ) , int ( args [ <NUM_LIT:2> ] ) , int ( args [ <NUM_LIT:3> ] ) <EOL> actions = self . lookupBlock ( x , y , z ) <EOL> found = False <EOL> for action in actions : <EOL> self . displayEntry ( player , action ) <EOL> if len ( actions ) < <NUM_LIT:1> : <EOL> player . message ( { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT>" : "<STR_LIT>" } ) <EOL> else : <EOL> player . message ( { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT>" : "<STR_LIT>" , "<STR_LIT>" : True } ) <EOL> elif subcommand == "<STR_LIT>" : <EOL> x , y , z = player . getPosition ( ) <EOL> chunk = ChunkReader ( int ( x / <NUM_LIT> ) , int ( z / <NUM_LIT> ) , self . logger . worldName ) <EOL> actions = chunk . load ( ) <EOL> for i in actions : <EOL> player . message ( str ( i ) ) <EOL> elif subcommand == "<STR_LIT>" : <EOL> player . message ( "<STR_LIT>" ) <EOL> commands = { "<STR_LIT>" : { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT:args>" : "<STR_LIT>" } , <EOL> "<STR_LIT>" : { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT:args>" : "<STR_LIT>" } , <EOL> "<STR_LIT>" : { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT:args>" : "<STR_LIT>" } } <EOL> for i in commands : <EOL> com = commands [ i ] <EOL> player . message ( "<STR_LIT>" % ( i , com [ "<STR_LIT:args>" ] , com [ "<STR_LIT:text>" ] ) ) <EOL> else : <EOL> player . message ( "<STR_LIT>" % subcommand ) <EOL> else : <EOL> player . message ( "<STR_LIT>" ) <EOL> player . message ( "<STR_LIT>" ) <EOL> def displayEntry ( self , player , action ) : <EOL> j = [ ] <EOL> timestamp = datetime . datetime . fromtimestamp ( int ( action [ <NUM_LIT:1> ] ) ) . strftime ( '<STR_LIT>' ) <EOL> uuid , type , payload = action [ <NUM_LIT:0> ] , action [ <NUM_LIT:2> ] , action [ <NUM_LIT:3> ] <EOL> playerName = self . minecraft . lookupUUID ( uuid ) [ "<STR_LIT:name>" ] <EOL> if playerName == None : playerName == uuid <EOL> j . append ( { "<STR_LIT:text>" : "<STR_LIT>" % timestamp , "<STR_LIT>" : "<STR_LIT>" } ) <EOL> j . append ( { "<STR_LIT:text>" : playerName + "<STR_LIT:U+0020>" , "<STR_LIT>" : "<STR_LIT>" , "<STR_LIT>" : { "<STR_LIT:action>" : "<STR_LIT>" , "<STR_LIT:value>" : uuid } } ) <EOL> if type in ( "<STR_LIT>" , "<STR_LIT>" ) : <EOL> if type == "<STR_LIT>" : <EOL> j . append ( { "<STR_LIT:text>" : "<STR_LIT>" } ) <EOL> elif type == "<STR_LIT>" : <EOL> j . append ( { "<STR_LIT:text>" : "<STR_LIT>" } ) <EOL> item = json . dumps ( { "<STR_LIT:id>" : payload [ "<STR_LIT>" ] , "<STR_LIT>" : <NUM_LIT:0> , "<STR_LIT>" : <NUM_LIT:1> , "<STR_LIT>" : { } } ) . replace ( '<STR_LIT:">' , "<STR_LIT>" ) <EOL> j . append ( { "<STR_LIT:text>" : payload [ "<STR_LIT>" ] , "<STR_LIT>" : "<STR_LIT>" , "<STR_LIT>" : { "<STR_LIT:action>" : "<STR_LIT>" , "<STR_LIT:value>" : item } } ) <EOL> player . message ( { "<STR_LIT:text>" : "<STR_LIT>" , "<STR_LIT>" : j } ) <EOL> def getLoggedUUIDs ( self ) : <EOL> l = os . listdir ( self . logger . getPath ( ) + "<STR_LIT>" ) <EOL> a = [ ] <EOL> for i in l : <EOL> if len ( i ) > <NUM_LIT> : <EOL> a . append ( i ) <EOL> return a <EOL> def lookupBlock ( self , x , y , z ) : <EOL> actions = [ ] <EOL> for uuid in self . getLoggedUUIDs ( ) : <EOL> chunk = Reader ( uuid , self . logger . worldName ) <EOL> for action in chunk . load ( ) : <EOL> timestamp , type , payload = action <EOL> if type in ( "<STR_LIT>" , "<STR_LIT>" ) : <EOL> if payload [ "<STR_LIT>" ] == ( x , y , z ) : <EOL> actions . append ( [ uuid , timestamp , type , payload ] ) <EOL> return actions <EOL> class Reader : <EOL> def __init__ ( self , uuid , worldName ) : <EOL> self . uuid = uuid <EOL> self . worldName = worldName <EOL> self . actions = [ ] <EOL> def load ( self ) : <EOL> if os . path . exists ( self . getPath ( ) + "<STR_LIT>" % self . uuid ) : <EOL> self . file = open ( self . getPath ( ) + "<STR_LIT>" % self . uuid , "<STR_LIT:r>" ) <EOL> self . parse ( ) <EOL> return self . actions <EOL> def getPath ( self ) : <EOL> return "<STR_LIT>" % self . worldName <EOL> def getPayload ( self ) : <EOL> length = struct . unpack ( "<STR_LIT:B>" , self . file . read ( <NUM_LIT:1> ) ) [ <NUM_LIT:0> ] <EOL> payload = self . file . read ( length ) <EOL> if len ( payload ) == <NUM_LIT:0> : <EOL> raise EOFError <EOL> return StringIO . StringIO ( payload ) <EOL> def getPacket ( self ) : <EOL> self . packet = self . getPayload ( ) <EOL> id = self . read_byte ( ) <EOL> timestamp = self . read_double ( ) <EOL> return id , timestamp <EOL> def read_byte ( self ) : <EOL> return struct . unpack ( "<STR_LIT:b>" , self . packet . read ( <NUM_LIT:1> ) ) [ <NUM_LIT:0> ] <EOL> def read_ubyte ( self ) : <EOL> return struct . unpack ( "<STR_LIT:B>" , self . packet . read ( <NUM_LIT:1> ) ) [ <NUM_LIT:0> ] <EOL> def read_short ( self ) : <EOL> return struct . unpack ( "<STR_LIT:h>" , self . packet . read ( <NUM_LIT:2> ) ) [ <NUM_LIT:0> ] <EOL> def read_ushort ( self ) : <EOL> return struct . unpack ( "<STR_LIT:H>" , self . packet . read ( <NUM_LIT:2> ) ) [ <NUM_LIT:0> ] <EOL> def read_int ( self ) : <EOL> return struct . unpack ( "<STR_LIT:i>" , self . packet . read ( <NUM_LIT:4> ) ) [ <NUM_LIT:0> ] <EOL> def read_double ( self ) : <EOL> return struct . unpack ( "<STR_LIT:d>" , self . packet . read ( <NUM_LIT:8> ) ) [ <NUM_LIT:0> ] <EOL> def read_position ( self ) : <EOL> return ( self . read_int ( ) , self . read_ubyte ( ) , self . read_int ( ) ) <EOL> def read ( self , expressions ) : <EOL> data = { } <EOL> for i in expressions . split ( "<STR_LIT:|>" ) : <EOL> name , type = i . split ( "<STR_LIT::>" ) <EOL> if type == "<STR_LIT>" : data [ name ] = self . read_byte ( ) <EOL> if type == "<STR_LIT>" : data [ name ] = self . read_ubyte ( ) <EOL> if type == "<STR_LIT>" : data [ name ] = self . read_short ( ) <EOL> if type == "<STR_LIT>" : data [ name ] = self . read_ushort ( ) <EOL> if type == "<STR_LIT>" : data [ name ] = self . read_double ( ) <EOL> if type == "<STR_LIT>" : data [ name ] = self . read_position ( ) <EOL> return data <EOL> def parse ( self ) : <EOL> while True : <EOL> try : <EOL> id , timestamp = self . getPacket ( ) <EOL> except : <EOL> break <EOL> if id == <NUM_LIT> : <EOL> data = self . read ( "<STR_LIT>" ) <EOL> self . actions . append ( [ timestamp , "<STR_LIT>" , data ] ) <EOL> if id == <NUM_LIT> : <EOL> data = self . read ( "<STR_LIT>" ) <EOL> self . actions . append ( [ timestamp , "<STR_LIT>" , data ] ) <EOL> class Logger : <EOL> def __init__ ( self , worldName ) : <EOL> self . worldName = worldName <EOL> self . queue = { } <EOL> def init ( self ) : <EOL> if not os . path . exists ( self . getPath ( ) ) : <EOL> os . mkdir ( self . getPath ( ) ) <EOL> if not os . path . exists ( self . getPath ( ) + "<STR_LIT>" ) : <EOL> os . mkdir ( self . getPath ( ) + "<STR_LIT>" ) <EOL> def __del__ ( self ) : <EOL> self . flush ( ) <EOL> def cleanup ( self ) : <EOL> pass <EOL> def getPath ( self ) : <EOL> return "<STR_LIT>" % self . worldName <EOL> def flush ( self ) : <EOL> for uuid in self . queue : <EOL> path = self . getPath ( ) + "<STR_LIT>" % uuid <EOL> with open ( path , "<STR_LIT:a>" ) as f : <EOL> for packet in self . queue [ uuid ] : <EOL> f . write ( packet ) <EOL> self . queue = { } <EOL> def push ( self , uuid , payload ) : <EOL> if not uuid in self . queue : <EOL> self . queue [ uuid ] = [ ] <EOL> self . queue [ uuid ] . append ( self . pack_byte ( len ( payload ) ) + payload ) <EOL> def write ( self , id , expressions , payload ) : <EOL> b = self . pack_byte ( id ) <EOL> b += self . pack_double ( time . time ( ) ) <EOL> for i , v in enumerate ( expressions . split ( "<STR_LIT:|>" ) ) : <EOL> type , value = v , payload [ i ] <EOL> if type == "<STR_LIT>" : b += self . pack_byte ( value ) <EOL> if type == "<STR_LIT>" : b += self . pack_short ( value ) <EOL> if type == "<STR_LIT>" : b += self . pack_ushort ( value ) <EOL> if type == "<STR_LIT:int>" : b += self . pack_int ( value ) <EOL> if type == "<STR_LIT:string>" : b += self . pack_string ( value ) <EOL> if type == "<STR_LIT>" : b += self . pack_double ( value ) <EOL> if type == "<STR_LIT>" : b += self . pack_bytearray ( value ) <EOL> if type == "<STR_LIT>" : b += self . pack_position ( value ) <EOL> return b <EOL> def place_block ( self , uuid , x , y , z , blockid , damage ) : <EOL> self . push ( uuid , self . write ( <NUM_LIT> , "<STR_LIT>" , ( ( x , y , z ) , blockid , damage ) ) ) <EOL> def dig_block ( self , uuid , x , y , z , blockid , damage ) : <EOL> self . push ( uuid , self . write ( <NUM_LIT> , "<STR_LIT>" , ( ( x , y , z ) , blockid , damage ) ) ) <EOL> def open_chest ( self , x , y , z ) : <EOL> return self . write ( <NUM_LIT> , "<STR_LIT>" , ( x , y , z ) ) <EOL> def close_chest ( self , x , y , z ) : <EOL> return self . write ( uuid , <NUM_LIT> , "<STR_LIT>" , ( x , y , z ) ) <EOL> def chest_action ( self , x , y , z , action , slot , itemid , damage ) : <EOL> return self . write ( uuid , <NUM_LIT> , "<STR_LIT>" , ( ( x , y , z ) , action , slot , itemid , damage ) ) <EOL> def pack_byte ( self , b ) : <EOL> return struct . pack ( "<STR_LIT:b>" , b ) <EOL> def pack_ubyte ( self , b ) : <EOL> return struct . pack ( "<STR_LIT:B>" , b ) <EOL> def pack_double ( self , b ) : <EOL> return struct . pack ( "<STR_LIT:d>" , b ) <EOL> def pack_short ( self , b ) : <EOL> return struct . pack ( "<STR_LIT:h>" , b ) <EOL> def pack_ushort ( self , b ) : <EOL> return struct . pack ( "<STR_LIT:H>" , b ) <EOL> def pack_int ( self , b ) : <EOL> return struct . pack ( "<STR_LIT:i>" , b ) <EOL> def pack_bytearray ( self , b ) : <EOL> return self . pack_ushort ( len ( b ) ) + b <EOL> def pack_string ( self , b ) : <EOL> return self . pack_ushort ( len ( b . encode ( "<STR_LIT:utf-8>" ) ) ) + b . encode ( "<STR_LIT:utf-8>" ) <EOL> def pack_position ( self , b ) : <EOL> return self . pack_int ( b [ <NUM_LIT:0> ] ) + self . pack_ubyte ( b [ <NUM_LIT:1> ] ) + self . pack_int ( b [ <NUM_LIT:2> ] ) </s>
