diff --git a/src/resources/objects/building/BuildingObject.java b/src/resources/objects/building/BuildingObject.java index f3dc4d31..2247591e 100644 --- a/src/resources/objects/building/BuildingObject.java +++ b/src/resources/objects/building/BuildingObject.java @@ -210,9 +210,8 @@ public class BuildingObject extends TangibleObject implements IPersistent, Seria return getCustomName(); } - public void setBuildingName(String buildingName, CreatureObject owner) { + public void setBuildingName(String buildingName) { setCustomName(buildingName); - ((CreatureObject) owner).sendSystemMessage("Structure renamed.", DisplayType.Broadcast); SWGObject sign = (SWGObject) getAttachment("sign"); if(sign != null) sign.setCustomName(buildingName); diff --git a/src/services/bazaar/BazaarService.java b/src/services/bazaar/BazaarService.java index 0dce7454..5932bb25 100644 --- a/src/services/bazaar/BazaarService.java +++ b/src/services/bazaar/BazaarService.java @@ -23,6 +23,7 @@ package services.bazaar; import java.nio.ByteOrder; import java.util.ArrayList; +import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -35,6 +36,10 @@ import java.util.concurrent.TimeUnit; + + + + import main.NGECore; import engine.clients.Client; import engine.resources.common.CRC; @@ -46,12 +51,15 @@ import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; import resources.common.Opcodes; import resources.common.OutOfBand; +import resources.common.ProsePackage; import resources.datatables.DisplayType; import resources.objects.building.BuildingObject; import resources.objects.creature.CreatureObject; import resources.objects.intangible.IntangibleObject; import resources.objects.manufacture.ManufactureSchematicObject; import resources.objects.tangible.TangibleObject; +import services.chat.Mail; +import services.chat.WaypointAttachment; import protocol.swg.auctionManagerClientListener.AuctionQueryHeadersMessage; import protocol.swg.auctionManagerClientListener.AuctionQueryHeadersResponseMessage; import protocol.swg.auctionManagerClientListener.BidAuctionMessage; @@ -422,17 +430,60 @@ public class BazaarService implements INetworkDispatch { else retrieveExpire = timeUntilExpire + VENDOR_EXPIRE; + CreatureObject seller = (CreatureObject) core.objectService.getObject(item.getOwnerId()); + item.setStatus(AuctionItem.SOLD); item.setBuyerId(player.getObjectID()); item.setExpireTime(retrieveExpire); item.setBidderName(player.getCustomName()); player.setBankCredits(player.getBankCredits() - item.getPrice()); player.getClient().getSession().write(new BidAuctionResponseMessage(item.getObjectId(), BidAuctionResponseMessage.SUCCESS).serialize()); + + WaypointAttachment waypoint = new WaypointAttachment(); + waypoint.positionX = vendor.getWorldPosition().x; + waypoint.positionZ = vendor.getWorldPosition().z; + waypoint.planetCRC = CRC.StringtoCRC(vendor.getPlanet().getName()); + waypoint.name = vendor.getCustomName() == null ? vendor.getObjectName().getStfValue() : vendor.getCustomName(); - // TODO send mail with WP + Mail sellerMail = new Mail(); + Mail buyerMail = new Mail(); - CreatureObject seller = (CreatureObject) core.objectService.getObject(item.getOwnerId()); + sellerMail.setMailId(NGECore.getInstance().chatService.generateMailId()); + sellerMail.setMessage(""); + sellerMail.setRecieverId(item.getOwnerId()); + sellerMail.setStatus(Mail.NEW); + sellerMail.setTimeStamp((int) (new Date().getTime() / 1000)); + sellerMail.setSenderName("SWG." + core.getGalaxyName() + ".auctioner"); + if(item.isOnBazaar()) { + sellerMail.setSubject("@auction:subject_instant_seller"); + sellerMail.addProseAttachment(new ProsePackage("@auction:seller_success", "TO", item.getObjectId(), item.getItemName(), "TT", player.getObjectID(), item.getBidderName(), "DI", item.getPrice())); + } else { + sellerMail.setSubject("@auction:subject_vendor_seller"); + sellerMail.addProseAttachment(new ProsePackage("@auction:seller_success_vendor", "TO", item.getObjectId(), item.getItemName(), "TT", player.getObjectID(), item.getBidderName(), "DI", item.getPrice())); + } + sellerMail.addProseAttachment(new ProsePackage("@auction:seller_success_location", "TO", 0, "@planet_n:" + vendor.getPlanet().getName(), "TT", 0, core.mapService.getClosestCityName(vendor))); + sellerMail.addWaypointAttachment(waypoint); + + buyerMail.setMailId(NGECore.getInstance().chatService.generateMailId()); + buyerMail.setMessage(""); + buyerMail.setRecieverId(player.getObjectID()); + buyerMail.setStatus(Mail.NEW); + buyerMail.setTimeStamp((int) (new Date().getTime() / 1000)); + buyerMail.setSenderName("SWG." + core.getGalaxyName() + ".auctioner"); + if(item.isOnBazaar()) + buyerMail.setSubject("@auction:subject_instant_buyer"); + else + buyerMail.setSubject("@auction:subject_vendor_buyer"); + buyerMail.addProseAttachment(new ProsePackage("@auction:buyer_success", "TO", item.getObjectId(), item.getItemName(), "TT", item.getOwnerId(), item.getOwnerName(), "DI", item.getPrice())); + buyerMail.addProseAttachment(new ProsePackage("@auction:buyer_success_location", "TO", 0, "@planet_n:" + vendor.getPlanet().getName(), "TT", 0, core.mapService.getClosestCityName(vendor))); + buyerMail.addWaypointAttachment(waypoint); + core.chatService.storePersistentMessage(buyerMail); + core.chatService.storePersistentMessage(sellerMail); + core.chatService.sendPersistentMessageHeader(player.getClient(), buyerMail); + if(seller != null && seller.getClient() != null) + core.chatService.sendPersistentMessageHeader(seller.getClient(), sellerMail); + if(seller == null) { seller = core.objectService.getCreatureFromDB(item.getOwnerId()); seller.setBankCredits(seller.getBankCredits() + item.getPrice()); diff --git a/src/services/housing/HousingService.java b/src/services/housing/HousingService.java index 49ab652d..4e2f099b 100644 --- a/src/services/housing/HousingService.java +++ b/src/services/housing/HousingService.java @@ -34,8 +34,15 @@ import java.util.Map; import java.util.Random; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + import main.NGECore; import protocol.swg.EnterStructurePlacementModeMessage; +import resources.datatables.DisplayType; import resources.objects.building.BuildingObject; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; @@ -55,6 +62,7 @@ public class HousingService implements INetworkDispatch { private NGECore core; private Map housingTemplates = new ConcurrentHashMap(); private Map houseToDeed = new ConcurrentHashMap(); + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); public HousingService(NGECore core) { this.core = core; @@ -139,8 +147,11 @@ public class HousingService implements INetworkDispatch { admins.add(actor.getObjectID()); building.setAttachment("sign", sign); // meh workaround + building.setAttachment("nextMaintenance", System.currentTimeMillis() + 3600000); building.setAttachment("structureOwner", actor.getObjectID()); building.setAttachment("structureAdmins", admins); + building.setAttachment("isCondemned", false); + building.setAttachment("outstandingMaint", 0); building.setDeedTemplate(deed.getTemplate()); building.setMaintenanceAmount(houseTemplate.getBaseMaintenanceRate()); building.setConditionDamage(100); // Ouch @@ -169,6 +180,43 @@ public class HousingService implements INetworkDispatch { } core.objectService.persistObject(building.getObjectID(), building, core.getSWGObjectODB()); + + } + + public void startMaintenanceTask(BuildingObject building) { + + AtomicReference> ref = new AtomicReference>(); + ref.set(scheduler.scheduleAtFixedRate(() -> { + + int amount = building.getBMR(); + boolean needSave = false; + CreatureObject owner = (CreatureObject) core.objectService.getObject((long) building.getAttachment("structureOwner")); + if(owner == null) { + needSave = true; + owner = core.objectService.getCreatureFromDB((long) building.getAttachment("structureOwner")); + } + if(building.getMaintenanceAmount() >= amount) { + building.setMaintenanceAmount(building.getMaintenanceAmount() - amount); + } else { + if(owner == null) + ref.get().cancel(true); + if(owner.getBankCredits() >= amount) { + owner.setBankCredits(owner.getBankCredits() - amount); + } else if(owner.getCashCredits() >= amount) { + owner.setCashCredits(owner.getCashCredits() - amount); + } else { + if(building.getAttachment("isCondemned") != null && !((boolean) building.getAttachment("isCondemned"))) { + building.setAttachment("isCondemned", true); + building.setBuildingName(building.getBuildingName() + " \\#FF0000(CONDEMNED)\\#FFFFFF"); + } + building.setAttachment("outstandingMaint", (int) building.getAttachment("outstandingMaint") + amount); + // TODO: lock down building, add option to pay outstanding maintenance and uncondemn building + } + } + if(needSave && owner != null) + core.objectService.persistObject(owner.getObjectID(), owner, core.getSWGObjectODB()); + + }, (long) building.getAttachment("nextMaintenance") - System.currentTimeMillis(), 3600000, TimeUnit.MILLISECONDS)); } @@ -292,6 +340,8 @@ public class HousingService implements INetworkDispatch { deed.setIntAttribute("@obj_attr_n:examine_maintenance", (int) building.getMaintenanceAmount()); core.objectService.destroyObject(building.getObjectID()); + if(building.getAttachment("sign") != null) + core.objectService.destroyObject((SWGObject) building.getAttachment("sign")); SWGObject ownerInventory = owner.getSlottedObject("inventory"); ownerInventory.add(deed); @@ -394,8 +444,8 @@ public class HousingService implements INetworkDispatch { } public void handleSetName(CreatureObject owner, TangibleObject target,String name) { - - ((BuildingObject) target).setBuildingName(name,owner); + ((BuildingObject) target).setBuildingName(name); + owner.sendSystemMessage("Structure renamed.", DisplayType.Broadcast); } public void createStatusSUIPage(SWGObject owner, TangibleObject target) { diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index c2aa8e82..ace233d5 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -205,6 +205,8 @@ public class ObjectService implements INetworkDispatch { sign.initAfterDBLoad(); objectList.put(sign.getObjectID(), sign); } + if(building.getAttachment("structureOwner") != null && ((BuildingObject) building).getMaintenanceAmount() > 0) + core.housingService.startMaintenanceTask((BuildingObject) building); } cursor.close();