2022-04-30 09:41:17 -04:00
package engine.net.client.handlers ;
2023-04-23 11:19:34 -04:00
import engine.Enum ;
2022-04-30 09:41:17 -04:00
import engine.Enum.DispatchChannel ;
import engine.Enum.GameObjectType ;
import engine.Enum.ProfitType ;
import engine.exception.MsgSendException ;
import engine.gameManager.BuildingManager ;
import engine.gameManager.DbManager ;
import engine.gameManager.SessionManager ;
import engine.math.FastMath ;
import engine.math.Vector3fImmutable ;
import engine.net.Dispatch ;
import engine.net.DispatchMessage ;
import engine.net.client.ClientConnection ;
import engine.net.client.msg.* ;
import engine.objects.* ;
import org.pmw.tinylog.Logger ;
import java.util.ArrayList ;
/*
* @Author:
* @Summary: Processes application protocol message which keeps
* client's tcp connection open.
*/
public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
// Constants used for incoming message type
private static final int CLIENT_UPGRADE_REQUEST = 3 ;
private static final int CLIENT_REDEED_REQUEST = 6 ;
private static final int SVR_CLOSE_WINDOW = 4 ;
public OrderNPCMsgHandler () {
super ( OrderNPCMsg . class );
}
2023-09-09 08:58:41 -04:00
public static void processRedeedHireling ( AbstractCharacter hireling , Building building , ClientConnection origin ) {
2023-04-23 11:19:34 -04:00
PlayerCharacter player ;
Contract contract ;
CharacterItemManager itemMan ;
ItemBase itemBase ;
Item item ;
player = SessionManager . getPlayerCharacter ( origin );
itemMan = player . getCharItemManager ();
2023-09-09 08:58:41 -04:00
contract = hireling . contract ;
2023-04-23 11:19:34 -04:00
if ( ! player . getCharItemManager (). hasRoomInventory (( short ) 1 )) {
ErrorPopupMsg . sendErrorPopup ( player , 21 );
return ;
}
2023-09-09 08:44:00 -04:00
if ( ! building . getHirelings (). containsKey ( hireling ))
2023-04-23 11:19:34 -04:00
return ;
2023-09-09 08:44:00 -04:00
BuildingManager . removeHireling ( building , hireling );
2023-04-23 11:19:34 -04:00
itemBase = ItemBase . getItemBase ( contract . getContractID ());
if ( itemBase == null ) {
2023-09-09 08:44:00 -04:00
Logger . error ( "Could not find Contract for npc: " + hireling . getObjectUUID ());
2023-04-23 11:19:34 -04:00
return ;
}
boolean itemWorked = false ;
2024-03-02 11:07:07 -05:00
item = new Item ( itemBase . getUUID ());
item . ownerID = player . getObjectUUID ();
item . ownerType = Enum . OwnerType . PlayerCharacter ;
item . chargesRemaining = ( byte ) hireling . getRank () - 1 ;
2023-04-23 11:19:34 -04:00
item . containerType = Enum . ItemContainerType . INVENTORY ;
try {
2024-03-02 09:55:30 -05:00
item = DbManager . ItemQueries . PERSIST ( item );
2023-04-23 11:19:34 -04:00
itemWorked = true ;
} catch ( Exception e ) {
Logger . error ( e );
}
if ( itemWorked ) {
itemMan . addItemToInventory ( item );
itemMan . updateInventory ();
}
ManageCityAssetsMsg mca = new ManageCityAssetsMsg ();
mca . actionType = NPC . SVR_CLOSE_WINDOW ;
mca . setTargetType ( building . getObjectType (). ordinal ());
mca . setTargetID ( building . getObjectUUID ());
origin . sendMsg ( mca );
}
private static void modifyBuyProfit ( OrderNPCMsg msg , ClientConnection origin ) {
NPC npc ;
PlayerCharacter player ;
Building building ;
float percent ;
ProfitType profitType = null ;
player = origin . getPlayerCharacter ();
if ( player == null )
return ;
npc = NPC . getFromCache ( msg . getNpcUUID ());
if ( npc == null )
return ;
building = npc . getBuilding ();
if ( building == null )
return ;
NPCProfits profit = NPC . GetNPCProfits ( npc );
if ( profit == null )
return ;
switch ( msg . getActionType ()) {
case 10 :
profitType = ProfitType . BuyNormal ;
break ;
case 11 :
profitType = ProfitType . BuyGuild ;
break ;
case 12 :
profitType = ProfitType . BuyNation ;
}
percent = msg . getBuySellPercent ();
percent = FastMath . clamp ( percent , 0 . 0f , 1 . 0f );
NPCProfits . UpdateProfits ( npc , profit , profitType , percent );
}
private static void modifySellProfit ( OrderNPCMsg orderNPCMsg , ClientConnection origin ) {
NPC npc ;
PlayerCharacter player ;
Building building ;
float percent ;
ProfitType profitType = null ;
player = origin . getPlayerCharacter ();
if ( player == null )
return ;
npc = NPC . getFromCache ( orderNPCMsg . getNpcUUID ());
if ( npc == null )
return ;
building = npc . getBuilding ();
if ( building == null )
return ;
NPCProfits profit = NPC . GetNPCProfits ( npc );
if ( profit == null )
return ;
switch ( orderNPCMsg . getActionType ()) {
case 7 :
profitType = ProfitType . SellNormal ;
break ;
case 8 :
profitType = ProfitType . SellGuild ;
break ;
case 9 :
profitType = ProfitType . SellNation ;
}
percent = orderNPCMsg . getBuySellPercent ();
percent -= 1f ;
percent = FastMath . clamp ( percent , 0 . 0f , 3 . 0f );
NPCProfits . UpdateProfits ( npc , profit , profitType , percent );
}
private static void handleCityCommand ( OrderNPCMsg orderNpcMsg , PlayerCharacter player ) {
Building building = BuildingManager . getBuildingFromCache ( orderNpcMsg . getBuildingUUID ());
if ( building == null )
return ;
if ( ManageCityAssetMsgHandler . playerCanManageNotFriends ( player , building ) == false )
return ;
if ( orderNpcMsg . getPatrolSize () >= 20 )
Logger . info ( player . getName () + " is attempting to add patrol points amount " + orderNpcMsg . getPatrolSize ());
if ( orderNpcMsg . getSentrySize () >= 20 )
Logger . info ( player . getName () + " is attempting to add patrol points amount " + orderNpcMsg . getSentryPoints ());
if ( orderNpcMsg . getPatrolPoints () != null ) {
if ( ! AddPatrolPoints ( building . getObjectUUID (), orderNpcMsg . getPatrolPoints ())) {
ErrorPopupMsg . sendErrorMsg ( player , "Patrol Points must be placed on city zone." );
return ;
}
} else if ( building . getPatrolPoints () != null )
ClearPatrolPoints ( building . getObjectUUID ());
if ( orderNpcMsg . getSentryPoints () != null ) {
AddSentryPoints ( building . getObjectUUID (), orderNpcMsg . getSentryPoints ());
} else if ( building . getSentryPoints () != null )
ClearSentryPoints ( building . getObjectUUID ());
}
private static void processUpgradeNPC ( PlayerCharacter player , AbstractCharacter abstractCharacter ) {
Building building ;
switch ( abstractCharacter . getObjectType ()) {
case NPC :
NPC npc = ( NPC ) abstractCharacter ;
building = npc . getBuilding ();
// Cannot upgrade an npc not within a building
if ( building == null )
return ;
City buildingCity = building . getCity ();
if ( buildingCity == null ) {
npc . processUpgradeNPC ( player );
return ;
}
buildingCity . transactionLock . writeLock (). lock ();
try {
npc . processUpgradeNPC ( player );
} catch ( Exception e ) {
Logger . error ( e );
} finally {
buildingCity . transactionLock . writeLock (). unlock ();
}
break ;
case Mob :
Mob mob = ( Mob ) abstractCharacter ;
building = mob . building ;
if ( mob . building == null )
return ;
City mobCity = building . getCity ();
if ( mobCity == null ) {
mob . processUpgradeMob ( player );
return ;
}
mobCity . transactionLock . writeLock (). lock ();
try {
mob . processUpgradeMob ( player );
} catch ( Exception e ) {
// TODO Auto-generated catch block
Logger . error ( e );
} finally {
mobCity . transactionLock . writeLock (). unlock ();
}
break ;
}
}
private static boolean AddPatrolPoints ( int buildingID , ArrayList < Vector3fImmutable > patrolPoints ) {
Building building = BuildingManager . getBuildingFromCache ( buildingID );
if ( building == null )
return false ;
Zone zone = building . getParentZone ();
if ( zone == null )
return false ;
2023-09-20 15:53:41 -04:00
if ( zone . playerCityUUID == 0 )
2023-04-23 11:19:34 -04:00
return false ;
City city = building . getCity ();
if ( city == null )
return false ;
//clear first.
for ( Vector3fImmutable point : patrolPoints ) {
if ( city . isLocationOnCityZone ( point ) == false ) {
return false ;
}
}
DbManager . BuildingQueries . CLEAR_PATROL ( buildingID );
for ( Vector3fImmutable point : patrolPoints ) {
if ( ! DbManager . BuildingQueries . ADD_TO_PATROL ( buildingID , point ))
return false ;
}
building . patrolPoints = patrolPoints ;
return true ;
}
private static boolean AddSentryPoints ( int buildingID , ArrayList < Vector3fImmutable > sentryPoints ) {
Building building = BuildingManager . getBuildingFromCache ( buildingID );
if ( building == null )
return false ;
building . sentryPoints = sentryPoints ;
return true ;
}
private static boolean ClearPatrolPoints ( int buildingID ) {
Building building = BuildingManager . getBuildingFromCache ( buildingID );
if ( building == null )
return false ;
if ( building . patrolPoints == null )
return true ;
if ( DbManager . BuildingQueries . CLEAR_PATROL ( buildingID ) == false )
return false ;
building . patrolPoints . clear ();
return true ;
}
private static boolean ClearSentryPoints ( int buildingID ) {
Building building = BuildingManager . getBuildingFromCache ( buildingID );
if ( building == null )
return false ;
if ( building . sentryPoints == null )
return true ;
building . sentryPoints . clear ();
return true ;
}
2022-04-30 09:41:17 -04:00
@Override
protected boolean _handleNetMsg ( ClientNetMsg baseMsg , ClientConnection origin ) throws MsgSendException {
// Member variable declarations
PlayerCharacter player ;
NPC npc ;
Mob mob ;
Building building ;
OrderNPCMsg orderNPCMsg ;
ManageCityAssetsMsg outMsg ;
// Member variable assignment
orderNPCMsg = ( OrderNPCMsg ) baseMsg ;
if ( origin . ordernpcspam > System . currentTimeMillis ())
return true ;
origin . ordernpcspam = System . currentTimeMillis () + 500 ;
player = SessionManager . getPlayerCharacter ( origin );
if ( player == null )
return true ;
if ( orderNPCMsg . getActionType () == 28 ) {
OrderNPCMsgHandler . handleCityCommand ( orderNPCMsg , player );
return true ;
}
if ( orderNPCMsg . getObjectType () == GameObjectType . NPC . ordinal ()) {
npc = NPC . getFromCache ( orderNPCMsg . getNpcUUID ());
if ( npc == null )
return true ;
building = BuildingManager . getBuildingFromCache ( orderNPCMsg . getBuildingUUID ());
if ( building == null )
return true ;
if ( building . getHirelings (). containsKey ( npc ) == false )
return true ;
if ( player . getCharItemManager (). getTradingWith () != null ) {
ErrorPopupMsg . sendErrorMsg ( player , "Cannot barter and trade with same timings." );
return true ;
}
player . lastBuildingAccessed = building . getObjectUUID ();
switch ( orderNPCMsg . getActionType ()) {
case 2 :
player = SessionManager . getPlayerCharacter ( origin );
if ( ManageCityAssetMsgHandler . playerCanManageNotFriends ( player , building ) == false )
return true ;
if ( building . getHirelings (). containsKey ( npc ) == false )
return true ;
if ( npc . remove () == false ) {
PlaceAssetMsg . sendPlaceAssetError ( player . getClientConnection (), 1 , "A Serious error has occurred. Please post details for to ensure transaction integrity" );
return true ;
}
ManageCityAssetsMsg manageCityAssetsMsg = new ManageCityAssetsMsg ();
manageCityAssetsMsg . actionType = SVR_CLOSE_WINDOW ;
manageCityAssetsMsg . setTargetType ( building . getObjectType (). ordinal ());
manageCityAssetsMsg . setTargetID ( building . getObjectUUID ());
Dispatch dispatch = Dispatch . borrow ( player , manageCityAssetsMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , DispatchChannel . SECONDARY );
return true ;
case CLIENT_UPGRADE_REQUEST :
if ( BuildingManager . playerCanManage ( player , building ) == false )
return true ;
processUpgradeNPC ( player , npc );
outMsg = new ManageCityAssetsMsg ( player , building );
// Action TYPE
outMsg . actionType = 3 ;
outMsg . setTargetType ( building . getObjectType (). ordinal ());
outMsg . setTargetID ( building . getObjectUUID ());
outMsg . setTargetType3 ( building . getObjectType (). ordinal ());
outMsg . setTargetID3 ( building . getObjectUUID ());
outMsg . setAssetName1 ( building . getName ());
outMsg . setUnknown54 ( 1 );
dispatch = Dispatch . borrow ( player , outMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , DispatchChannel . SECONDARY );
break ;
case CLIENT_REDEED_REQUEST :
if ( BuildingManager . PlayerCanControlNotOwner ( building , player ) == false )
return true ;
2023-09-09 08:58:41 -04:00
processRedeedHireling ( npc , building , origin );
2022-04-30 09:41:17 -04:00
return true ;
//MB TODO HANDLE all profits.
case 7 :
case 8 :
case 9 :
if ( BuildingManager . PlayerCanControlNotOwner ( building , player ) == false )
return true ;
modifySellProfit ( orderNPCMsg , origin );
dispatch = Dispatch . borrow ( player , orderNPCMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , DispatchChannel . SECONDARY );
return true ;
case 10 :
case 11 :
case 12 :
if ( BuildingManager . PlayerCanControlNotOwner ( building , player ) == false )
return true ;
modifyBuyProfit ( orderNPCMsg , origin );
dispatch = Dispatch . borrow ( player , orderNPCMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , DispatchChannel . SECONDARY );
return true ;
}
// Validation check Owner or IC or friends
if ( BuildingManager . PlayerCanControlNotOwner ( building , player ) == false )
if ( BuildingManager . playerCanManage ( player , building ) == false )
return true ;
ManageNPCMsg manageNPCMsg = new ManageNPCMsg ( npc );
Dispatch dispatch = Dispatch . borrow ( player , manageNPCMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , DispatchChannel . SECONDARY );
return true ;
} else if ( orderNPCMsg . getObjectType () == GameObjectType . Mob . ordinal ()) {
2023-08-25 15:23:02 -04:00
mob = Mob . getMob ( orderNPCMsg . getNpcUUID ());
2022-04-30 09:41:17 -04:00
if ( mob == null )
return true ;
building = BuildingManager . getBuildingFromCache ( orderNPCMsg . getBuildingUUID ());
if ( building == null )
return true ;
if ( ! building . getHirelings (). containsKey ( mob ))
return true ;
if ( player . getCharItemManager (). getTradingWith () != null ) {
ErrorPopupMsg . sendErrorMsg ( player , "Cannot barter and trade with same timings." );
return true ;
}
player . lastBuildingAccessed = building . getObjectUUID ();
switch ( orderNPCMsg . getActionType ()) {
case 2 :
if ( BuildingManager . playerCanManage ( player , building ) == false )
return true ;
if ( building . getHirelings (). containsKey ( mob ) == false )
return true ;
2023-09-09 08:58:41 -04:00
BuildingManager . removeHireling ( building , mob );
2022-04-30 09:41:17 -04:00
ManageCityAssetsMsg manageCityAssetsMsg = new ManageCityAssetsMsg ();
manageCityAssetsMsg . actionType = SVR_CLOSE_WINDOW ;
manageCityAssetsMsg . setTargetType ( building . getObjectType (). ordinal ());
manageCityAssetsMsg . setTargetID ( building . getObjectUUID ());
Dispatch dispatch = Dispatch . borrow ( player , manageCityAssetsMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , DispatchChannel . SECONDARY );
break ;
case 3 :
if ( BuildingManager . PlayerCanControlNotOwner ( building , player ) == false )
return true ;
processUpgradeNPC ( player , mob );
outMsg = new ManageCityAssetsMsg ( player , building );
// Action TYPE
outMsg . actionType = 3 ;
outMsg . setTargetType ( building . getObjectType (). ordinal ());
outMsg . setTargetID ( building . getObjectUUID ());
outMsg . setTargetType3 ( building . getObjectType (). ordinal ());
outMsg . setTargetID3 ( building . getObjectUUID ());
outMsg . setAssetName1 ( building . getName ());
outMsg . setUnknown54 ( 1 );
dispatch = Dispatch . borrow ( player , outMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , DispatchChannel . SECONDARY );
break ;
case 6 :
if ( BuildingManager . PlayerCanControlNotOwner ( building , player ) == false )
return true ;
2023-09-09 08:58:41 -04:00
processRedeedHireling ( mob , building , origin );
2022-04-30 09:41:17 -04:00
return true ;
//MB TODO HANDLE all profits.
case 7 :
case 8 :
case 9 :
break ;
case 10 :
case 11 :
case 12 :
break ;
}
// Validation check Owner or IC
if ( BuildingManager . PlayerCanControlNotOwner ( building , player ) == false )
if ( BuildingManager . playerCanManage ( player , building ) == false )
return true ;
ManageNPCMsg manageNPCMsg = new ManageNPCMsg ( mob );
Dispatch dispatch = Dispatch . borrow ( player , manageNPCMsg );
DispatchMessage . dispatchMsgDispatch ( dispatch , DispatchChannel . SECONDARY );
return true ;
}
return true ;
}
}