2018-07-06 13:30:00 +00:00
package com.eu.habbo.habbohotel.bots ;
import com.eu.habbo.Emulator ;
2018-12-22 10:39:00 +00:00
import com.eu.habbo.habbohotel.items.Item ;
2018-09-12 16:45:00 +00:00
import com.eu.habbo.habbohotel.permissions.Permission ;
2018-07-06 13:30:00 +00:00
import com.eu.habbo.habbohotel.rooms.* ;
import com.eu.habbo.habbohotel.users.Habbo ;
2018-12-22 10:39:00 +00:00
import com.eu.habbo.habbohotel.users.HabboItem ;
2018-07-06 13:30:00 +00:00
import com.eu.habbo.messages.outgoing.generic.alerts.BotErrorComposer ;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertComposer ;
import com.eu.habbo.messages.outgoing.generic.alerts.BubbleAlertKeys ;
import com.eu.habbo.messages.outgoing.inventory.AddBotComposer ;
import com.eu.habbo.messages.outgoing.inventory.RemoveBotComposer ;
import com.eu.habbo.messages.outgoing.rooms.users.RoomUsersComposer ;
import com.eu.habbo.plugin.events.bots.BotPickUpEvent ;
import com.eu.habbo.plugin.events.bots.BotPlacedEvent ;
import gnu.trove.map.hash.THashMap ;
2020-05-04 22:24:09 +02:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
2018-07-06 13:30:00 +00:00
import java.lang.reflect.Method ;
import java.sql.* ;
import java.util.Map ;
2020-06-04 16:44:19 +01:00
2019-05-26 21:14:53 +03:00
public class BotManager {
2020-05-04 22:24:09 +02:00
private static final Logger LOGGER = LoggerFactory . getLogger ( BotManager . class ) ;
2018-09-28 19:25:00 +00:00
2019-05-26 21:14:53 +03:00
final private static THashMap < String , Class < ? extends Bot > > botDefenitions = new THashMap < > ( ) ;
2018-07-06 13:30:00 +00:00
public static int MINIMUM_CHAT_SPEED = 7 ;
2018-09-28 19:25:00 +00:00
public static int MAXIMUM_CHAT_SPEED = 604800 ;
public static int MAXIMUM_CHAT_LENGTH = 120 ;
public static int MAXIMUM_NAME_LENGTH = 15 ;
2020-06-04 16:44:19 +01:00
public static int MAXIMUM_BOT_INVENTORY_SIZE = 25 ;
2018-07-08 21:32:00 +00:00
2019-05-26 21:14:53 +03:00
public BotManager ( ) throws Exception {
2018-07-06 13:30:00 +00:00
long millis = System . currentTimeMillis ( ) ;
2019-03-18 01:22:00 +00:00
addBotDefinition ( " generic " , Bot . class ) ;
addBotDefinition ( " bartender " , ButlerBot . class ) ;
addBotDefinition ( " visitor_log " , VisitorBot . class ) ;
2018-07-06 13:30:00 +00:00
this . reload ( ) ;
2020-05-04 22:24:09 +02:00
LOGGER . info ( " Bot Manager -> Loaded! ( " + ( System . currentTimeMillis ( ) - millis ) + " MS) " ) ;
2018-07-06 13:30:00 +00:00
}
2019-05-26 21:14:53 +03:00
public static void addBotDefinition ( String type , Class < ? extends Bot > botClazz ) throws Exception {
if ( botClazz . getDeclaredConstructor ( ResultSet . class ) = = null ) {
throw new Exception ( " Missing Bot(ResultSet) constructor! " ) ;
} else {
botClazz . getDeclaredConstructor ( ResultSet . class ) . setAccessible ( true ) ;
2018-07-08 21:32:00 +00:00
2019-05-26 21:14:53 +03:00
botDefenitions . put ( type , botClazz ) ;
}
}
public boolean reload ( ) {
for ( Map . Entry < String , Class < ? extends Bot > > set : botDefenitions . entrySet ( ) ) {
try {
2018-07-06 13:30:00 +00:00
Method m = set . getValue ( ) . getMethod ( " initialise " ) ;
m . setAccessible ( true ) ;
m . invoke ( null ) ;
2019-05-26 21:14:53 +03:00
} catch ( NoSuchMethodException e ) {
2020-05-04 22:24:09 +02:00
LOGGER . info ( " Bot Manager -> Failed to execute initialise method upon bot type ' " + set . getKey ( ) + " '. No Such Method! " ) ;
2018-07-06 13:30:00 +00:00
return false ;
2019-05-26 21:14:53 +03:00
} catch ( Exception e ) {
2020-05-04 22:24:09 +02:00
LOGGER . info ( " Bot Manager -> Failed to execute initialise method upon bot type ' " + set . getKey ( ) + " '. Error: " + e . getMessage ( ) ) ;
2018-07-06 13:30:00 +00:00
return false ;
}
}
return true ;
}
2019-05-26 21:14:53 +03:00
public Bot createBot ( THashMap < String , String > data , String type ) {
2018-07-06 13:30:00 +00:00
Bot bot = null ;
2019-05-26 21:14:53 +03:00
try ( Connection connection = Emulator . getDatabase ( ) . getDataSource ( ) . getConnection ( ) ; PreparedStatement statement = connection . prepareStatement ( " INSERT INTO bots (user_id, room_id, name, motto, figure, gender, type) VALUES (0, 0, ?, ?, ?, ?, ?) " , Statement . RETURN_GENERATED_KEYS ) ) {
2018-07-06 13:30:00 +00:00
statement . setString ( 1 , data . get ( " name " ) ) ;
statement . setString ( 2 , data . get ( " motto " ) ) ;
statement . setString ( 3 , data . get ( " figure " ) ) ;
statement . setString ( 4 , data . get ( " gender " ) . toUpperCase ( ) ) ;
statement . setString ( 5 , type ) ;
statement . execute ( ) ;
2019-05-26 21:14:53 +03:00
try ( ResultSet set = statement . getGeneratedKeys ( ) ) {
if ( set . next ( ) ) {
try ( PreparedStatement stmt = connection . prepareStatement ( " SELECT users.username AS owner_name, bots.* FROM bots LEFT JOIN users ON bots.user_id = users.id WHERE bots.id = ? LIMIT 1 " ) ) {
2018-07-06 13:30:00 +00:00
stmt . setInt ( 1 , set . getInt ( 1 ) ) ;
2019-05-26 21:14:53 +03:00
try ( ResultSet resultSet = stmt . executeQuery ( ) ) {
if ( resultSet . next ( ) ) {
2018-07-06 13:30:00 +00:00
bot = this . loadBot ( resultSet ) ;
}
}
2019-05-26 21:14:53 +03:00
} catch ( SQLException e ) {
2020-05-04 22:24:09 +02:00
LOGGER . error ( " Caught SQL exception " , e ) ;
2018-07-06 13:30:00 +00:00
}
}
}
2019-05-26 21:14:53 +03:00
} catch ( SQLException e ) {
2020-05-04 22:24:09 +02:00
LOGGER . error ( " Caught SQL exception " , e ) ;
2018-07-06 13:30:00 +00:00
}
return bot ;
}
2019-05-26 21:14:53 +03:00
public void placeBot ( Bot bot , Habbo habbo , Room room , RoomTile location ) {
2018-07-06 13:30:00 +00:00
BotPlacedEvent event = new BotPlacedEvent ( bot , location , habbo ) ;
Emulator . getPluginManager ( ) . fireEvent ( event ) ;
2019-05-26 21:14:53 +03:00
if ( event . isCancelled ( ) )
2018-07-06 13:30:00 +00:00
return ;
2019-05-26 21:14:53 +03:00
if ( room ! = null & & bot ! = null & & habbo ! = null ) {
2020-06-05 04:12:49 -04:00
if ( room . getOwnerId ( ) = = habbo . getHabboInfo ( ) . getId ( ) | | habbo . hasPermission ( Permission . ACC_ANYROOMOWNER ) | | habbo . hasPermission ( Permission . ACC_PLACEFURNI ) ) {
if ( room . getCurrentBots ( ) . size ( ) > = Room . MAXIMUM_BOTS & & ! habbo . hasPermission ( Permission . ACC_UNLIMITED_BOTS ) ) {
2018-07-06 13:30:00 +00:00
habbo . getClient ( ) . sendResponse ( new BotErrorComposer ( BotErrorComposer . ROOM_ERROR_MAX_BOTS ) ) ;
return ;
}
2020-02-27 23:59:27 +02:00
if ( room . hasHabbosAt ( location . x , location . y ) | | ( ! location . isWalkable ( ) & & location . state ! = RoomTileState . SIT & & location . state ! = RoomTileState . LAY ) )
2018-07-06 13:30:00 +00:00
return ;
RoomUnit roomUnit = new RoomUnit ( ) ;
roomUnit . setRotation ( RoomUserRotation . SOUTH ) ;
roomUnit . setLocation ( location ) ;
2018-12-22 10:39:00 +00:00
HabboItem topItem = room . getTopItemAt ( location . x , location . y ) ;
2020-02-27 23:52:40 +02:00
double topItemHeight = 0 ;
if ( topItem ! = null ) topItemHeight = Item . getCurrentHeight ( topItem ) ;
roomUnit . setPreviousLocationZ ( roomUnit . getCurrentLocation ( ) . getStackHeight ( ) - topItemHeight ) ;
2018-07-06 13:30:00 +00:00
roomUnit . setPathFinderRoom ( room ) ;
roomUnit . setRoomUnitType ( RoomUnitType . BOT ) ;
roomUnit . setCanWalk ( room . isAllowBotsWalk ( ) ) ;
bot . setRoomUnit ( roomUnit ) ;
bot . setRoom ( room ) ;
bot . needsUpdate ( true ) ;
room . addBot ( bot ) ;
Emulator . getThreading ( ) . run ( bot ) ;
room . sendComposer ( new RoomUsersComposer ( bot ) . compose ( ) ) ;
habbo . getInventory ( ) . getBotsComponent ( ) . removeBot ( bot ) ;
habbo . getClient ( ) . sendResponse ( new RemoveBotComposer ( bot ) ) ;
bot . onPlace ( habbo , room ) ;
2018-12-22 10:39:00 +00:00
2019-05-26 21:14:53 +03:00
if ( topItem ! = null ) {
try {
2018-12-22 10:39:00 +00:00
topItem . onWalkOn ( bot . getRoomUnit ( ) , room , null ) ;
2019-05-26 21:14:53 +03:00
} catch ( Exception e ) {
2020-05-04 22:24:09 +02:00
LOGGER . error ( " Caught exception " , e ) ;
2018-12-22 10:39:00 +00:00
}
}
2018-07-06 13:30:00 +00:00
bot . cycle ( false ) ;
2019-05-26 21:14:53 +03:00
} else {
2018-12-22 10:39:00 +00:00
habbo . getClient ( ) . sendResponse ( new BubbleAlertComposer ( BubbleAlertKeys . FURNITURE_PLACEMENT_ERROR . key , FurnitureMovementError . NO_RIGHTS . errorCode ) ) ;
2018-07-06 13:30:00 +00:00
}
}
}
2019-05-26 21:14:53 +03:00
public void pickUpBot ( int botId , Habbo habbo ) {
if ( habbo . getHabboInfo ( ) . getCurrentRoom ( ) ! = null ) {
2018-07-06 13:30:00 +00:00
this . pickUpBot ( habbo . getHabboInfo ( ) . getCurrentRoom ( ) . getBot ( Math . abs ( botId ) ) , habbo ) ;
}
}
2019-05-26 21:14:53 +03:00
public void pickUpBot ( Bot bot , Habbo habbo ) {
2020-06-04 16:44:19 +01:00
2019-05-26 21:14:53 +03:00
if ( bot ! = null & & habbo ! = null ) {
2018-07-06 13:30:00 +00:00
BotPickUpEvent pickedUpEvent = new BotPickUpEvent ( bot , habbo ) ;
Emulator . getPluginManager ( ) . fireEvent ( pickedUpEvent ) ;
2019-05-26 21:14:53 +03:00
if ( pickedUpEvent . isCancelled ( ) )
2018-07-06 13:30:00 +00:00
return ;
2019-05-26 21:14:53 +03:00
if ( bot . getOwnerId ( ) = = habbo . getHabboInfo ( ) . getId ( ) | | habbo . hasPermission ( Permission . ACC_ANYROOMOWNER ) ) {
2020-06-05 16:35:08 +01:00
if ( ! habbo . hasPermission ( Permission . ACC_UNLIMITED_BOTS ) & & habbo . getInventory ( ) . getBotsComponent ( ) . getBots ( ) . size ( ) > = BotManager . MAXIMUM_BOT_INVENTORY_SIZE ) {
habbo . alert ( Emulator . getTexts ( ) . getValue ( " error.bots.max.inventory " ) . replace ( " %amount% " , BotManager . MAXIMUM_BOT_INVENTORY_SIZE + " " ) ) ;
return ;
2020-06-04 14:23:19 +01:00
}
2018-07-06 13:30:00 +00:00
bot . onPickUp ( habbo , habbo . getHabboInfo ( ) . getCurrentRoom ( ) ) ;
habbo . getHabboInfo ( ) . getCurrentRoom ( ) . removeBot ( bot ) ;
bot . stopFollowingHabbo ( ) ;
bot . setOwnerId ( habbo . getHabboInfo ( ) . getId ( ) ) ;
bot . setOwnerName ( habbo . getHabboInfo ( ) . getUsername ( ) ) ;
bot . needsUpdate ( true ) ;
Emulator . getThreading ( ) . run ( bot ) ;
habbo . getInventory ( ) . getBotsComponent ( ) . addBot ( bot ) ;
habbo . getClient ( ) . sendResponse ( new AddBotComposer ( bot ) ) ;
}
}
}
2019-05-26 21:14:53 +03:00
public Bot loadBot ( ResultSet set ) {
try {
2018-07-06 13:30:00 +00:00
String type = set . getString ( " type " ) ;
Class < ? extends Bot > botClazz = botDefenitions . get ( type ) ;
2019-05-26 21:14:53 +03:00
if ( botClazz ! = null )
2018-07-06 13:30:00 +00:00
return botClazz . getDeclaredConstructor ( ResultSet . class ) . newInstance ( set ) ;
else
2020-05-04 22:24:09 +02:00
LOGGER . error ( " Unknown Bot Type: " + type ) ;
2019-05-26 21:14:53 +03:00
} catch ( SQLException e ) {
2020-05-04 22:24:09 +02:00
LOGGER . error ( " Caught SQL exception " , e ) ;
2019-05-26 21:14:53 +03:00
} catch ( Exception e ) {
2020-05-04 22:24:09 +02:00
LOGGER . error ( " Caught exception " , e ) ;
2018-07-06 13:30:00 +00:00
}
return null ;
}
2019-05-26 21:14:53 +03:00
public boolean deleteBot ( Bot bot ) {
try ( Connection connection = Emulator . getDatabase ( ) . getDataSource ( ) . getConnection ( ) ; PreparedStatement statement = connection . prepareStatement ( " DELETE FROM bots WHERE id = ? LIMIT 1 " ) ) {
2018-07-06 13:30:00 +00:00
statement . setInt ( 1 , bot . getId ( ) ) ;
return statement . execute ( ) ;
2019-05-26 21:14:53 +03:00
} catch ( SQLException e ) {
2020-05-04 22:24:09 +02:00
LOGGER . error ( " Caught SQL exception " , e ) ;
2018-07-06 13:30:00 +00:00
}
return false ;
}
2019-05-26 21:14:53 +03:00
public void dispose ( ) {
for ( Map . Entry < String , Class < ? extends Bot > > set : botDefenitions . entrySet ( ) ) {
try {
2018-07-06 13:30:00 +00:00
Method m = set . getValue ( ) . getMethod ( " dispose " ) ;
m . setAccessible ( true ) ;
m . invoke ( null ) ;
2019-05-26 21:14:53 +03:00
} catch ( NoSuchMethodException e ) {
2020-05-04 22:24:09 +02:00
LOGGER . info ( " Bot Manager -> Failed to execute dispose method upon bot type ' " + set . getKey ( ) + " '. No Such Method! " ) ;
2019-05-26 21:14:53 +03:00
} catch ( Exception e ) {
2020-05-04 22:24:09 +02:00
LOGGER . info ( " Bot Manager -> Failed to execute dispose method upon bot type ' " + set . getKey ( ) + " '. Error: " + e . getMessage ( ) ) ;
2018-07-06 13:30:00 +00:00
}
}
}
}