From 968438bbef2da403505d511d670b13eb196fe6da Mon Sep 17 00:00:00 2001 From: Light2 Date: Thu, 12 Jun 2014 01:09:54 +0200 Subject: [PATCH] Added city update process, added city fixup process, --- src/services/playercities/PlayerCity.java | 244 +++++++++++++----- .../playercities/PlayerCityService.java | 35 +-- 2 files changed, 181 insertions(+), 98 deletions(-) diff --git a/src/services/playercities/PlayerCity.java b/src/services/playercities/PlayerCity.java index b9938fa7..d7a52c6e 100644 --- a/src/services/playercities/PlayerCity.java +++ b/src/services/playercities/PlayerCity.java @@ -91,6 +91,7 @@ public class PlayerCity implements Serializable { public static final int LARGE_GARDEN = 5; public static final int SHUTTLEPORT = 6; + public static final int[] citizensPerRank = new int[] { 5, 10, 15, 30, 40 }; private String cityName = ""; private int planetId; @@ -118,11 +119,13 @@ public class PlayerCity implements Serializable { private boolean zoningEnabled = false; private transient CollidableCircle area; - //private final long cityUpdateSpan = 7*86400*1000; - private final long cityUpdateSpan = 100*1000; - - //private final long legislationPeriod = 21*86400*1000; - private final long legislationPeriod = 100*1000; + //public static final long cityUpdateSpan = 7*86400*1000; + public static final long cityUpdateSpan = 100*1000; + //public static final long cityUpdateSpan = 86400*1000; + public static final long newCityGraceSpan = 100*1000; + + //public static final long legislationPeriod = 21*86400*1000; + public static final long legislationPeriod = 100*1000; private Vector placedStructures = new Vector(); private Vector citizens = new Vector(); @@ -178,71 +181,25 @@ public class PlayerCity implements Serializable { public void processCityUpdate() { // has something changed? - System.out.println("processCityUpdate"); + System.out.println("processCityUpdate for " + cityName); + + fixupCitizens(); int censusResult = citizens.size(); int currentRank = getRank(); - switch (currentRank) { - /*case NEWCITY : if (censusResult>=5){ - setRank(++currentRank); // Expand to Outpost - sendCityExpandMail(); - } - - if (censusResult<5){ - // kill city - } - break;*/ - - case OUTPOST : if (censusResult>=10){ - setRank(++currentRank); // Expand to Village - sendCityExpandMail(); - } - if (censusResult<5){ - setRank(--currentRank); // Contract to Deserted - sendCityContractMail(); - } - break; - - case VILLAGE : if (censusResult>=15){ - setRank(++currentRank); // Expand to Township - sendCityExpandMail(); - } - if (censusResult<10){ - setRank(--currentRank); // Contract to Outpost - sendCityContractMail(); - } - break; - - case TOWNSHIP : if (censusResult>=30){ - setRank(++currentRank); // Expand to City - sendCityExpandMail(); - } - if (censusResult<15){ - setRank(--currentRank); // Contract to Village - sendCityContractMail(); - } - break; - - case CITY : if (censusResult>=40){ - setRank(++currentRank); // Expand to Metropolis - sendCityExpandMail(); - } - if (censusResult<30){ - setRank(--currentRank); // Contract to Township - sendCityContractMail(); - } - break; - - case METROPOLIS : if (censusResult<40){ - setRank(--currentRank); // Contract to City - sendCityContractMail(); - } - break; - - + int minCitizen = citizensPerRank[currentRank - 1]; + + if(censusResult < minCitizen) { + contractCity(); + } else { + if(getRank() != METROPOLIS && citizensPerRank[currentRank] <= censusResult) + expandCity(); } + NGECore core = NGECore.getInstance(); // collect taxes + if(core.objectService.getObject(cityHallId) == null) + return; for (long citizen : citizens) { CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); if(citizenObject == null) @@ -266,11 +223,141 @@ public class PlayerCity implements Serializable { } demolishHighRankStructures(); calculateAndPayMaintenance(); + core.playerCityService.schedulePlayerCityUpdate(this, cityUpdateSpan); setNextCityUpdate(System.currentTimeMillis()+cityUpdateSpan); } - public void cityFixUp(){ + public void contractCity() { + NGECore core = NGECore.getInstance(); + int newRank = getRank() - 1; + CreatureObject mayor = core.objectService.getObject(getMayorID()) == null ? core.objectService.getCreatureFromDB(getMayorID()) : (CreatureObject) core.objectService.getObject(getMayorID()); + if(mayor == null) + return; + + if(newRank < 1) { + core.housingService.destroyStructure((BuildingObject) core.objectService.getObject(cityHallId)); + return; + } + + // TODO unregister city if rank < 3 + + setRank(newRank); + demolishCivicStructuresOutsideRadius(); + demolishHighRankStructures(); + sendCityContractMail(); + fixupCitizens(); + } + + private void demolishCivicStructuresOutsideRadius() { + NGECore core = NGECore.getInstance(); + List remove = new ArrayList(); + placedStructures.stream().map(core.objectService::getObject) + .filter(o -> o.getAttachment("isCivicStructure") != null && (boolean) o.getAttachment("isCivicStructure")) + .filter(o -> !area.doesCollide(o)).forEach(remove::add); + remove.forEach(b -> core.housingService.destroyStructure((BuildingObject) b)); + } + + public void expandCity() { + + NGECore core = NGECore.getInstance(); + CreatureObject mayor = core.objectService.getObject(getMayorID()) == null ? core.objectService.getCreatureFromDB(getMayorID()) : (CreatureObject) core.objectService.getObject(getMayorID()); + if(mayor == null) + return; + + if(getRank() == METROPOLIS) + return; + + int newRank = getRank() + 1; + setRank(newRank); + sendCityExpandMail(); + fixupCitizens(); + + } + + // cleanup in case something went wrong + public void fixupCitizens() { + List residents = new ArrayList(); + List added = new ArrayList(); + List removed = new ArrayList(); + // TODO: add extra mail for deleted characters + + NGECore core = NGECore.getInstance(); + CreatureObject mayor = core.objectService.getObject(getMayorID()) == null ? core.objectService.getCreatureFromDB(getMayorID()) : (CreatureObject) core.objectService.getObject(getMayorID()); + if(mayor == null) + return; + + for (long structureID : new Vector(placedStructures)) { + BuildingObject structure = (BuildingObject) NGECore.getInstance().objectService.getObject(structureID); + if(structure == null) + return; + if(structure.getResidency()) + residents.add((Long) structure.getAttachment("structureOwner")); + } + for(long citizenId : new Vector(citizens)) { + if(!residents.contains(citizenId)) { + removeCitizen(citizenId, false); + CreatureObject citizenObject = core.objectService.getObject(citizenId) == null ? core.objectService.getCreatureFromDB(citizenId) : (CreatureObject) core.objectService.getObject(citizenId); + if(citizenObject != null) + removed.add(citizenObject); + } + } + for(long residentId : residents) { + if(!citizens.contains(residentId)) { + addCitizen(residentId, false); + CreatureObject citizenObject = core.objectService.getObject(residentId) == null ? core.objectService.getCreatureFromDB(residentId) : (CreatureObject) core.objectService.getObject(residentId); + if(citizenObject != null) + added.add(citizenObject); + } + } + + String addTT = ""; + for(CreatureObject addedCitizen : added) { + if(added.indexOf(addedCitizen) == added.size() - 1) + addTT += addedCitizen.getCustomName(); + else + addTT += (addedCitizen.getCustomName() + ", "); + } + + String removedTT = ""; + for(CreatureObject removedCitizen : removed) { + if(removed.indexOf(removedCitizen) == removed.size() - 1) + removedTT += removedCitizen.getCustomName(); + else + removedTT += (removedCitizen.getCustomName() + ", "); + } + + if(added.size() > 0) { + Mail mail = new Mail(); + mail.setMailId(core.chatService.generateMailId()); + mail.setRecieverId(getMayorID()); + mail.setStatus(Mail.NEW); + mail.setTimeStamp((int) (new Date().getTime() / 1000)); + mail.setSubject("@city/city:city_fixup_add_citizens_subject"); + mail.setSenderName("@city/city:new_city_from"); + mail.addProseAttachment(new ProsePackage("@city/city:city_fixup_add_citizens_body", "TT", addTT)); + + core.chatService.storePersistentMessage(mail); + if(mayor.getClient() != null) + core.chatService.sendPersistentMessageHeader(mayor.getClient(), mail); + } + + if(removed.size() > 0) { + Mail mail = new Mail(); + mail.setMailId(core.chatService.generateMailId()); + mail.setRecieverId(getMayorID()); + mail.setStatus(Mail.NEW); + mail.setTimeStamp((int) (new Date().getTime() / 1000)); + mail.setSubject("@city/city:city_fixup_remove_citizens_subject"); + mail.setSenderName("@city/city:new_city_from"); + mail.addProseAttachment(new ProsePackage("@city/city:city_fixup_remove_citizens_body", "TT", removedTT)); + + core.chatService.storePersistentMessage(mail); + if(mayor.getClient() != null) + core.chatService.sendPersistentMessageHeader(mayor.getClient(), mail); + } + + } public void demolishHighRankStructures() { @@ -278,7 +365,7 @@ public class PlayerCity implements Serializable { // that require a higher rank than the current one synchronized(placedStructures){ Vector wreckingBall = new Vector(); - for (long structureID : placedStructures){ + for (long structureID : placedStructures) { SWGObject structure = NGECore.getInstance().objectService.getObject(structureID); int structureCode = (int) structure.getAttachment("CityStructureCode"); @@ -526,19 +613,34 @@ public class PlayerCity implements Serializable { } public void addCitizen(long citizen) { - citizens.add(citizen); - CreatureObject citizenObject = (CreatureObject) NGECore.getInstance().objectService.getObject(citizen); - sendNewCitizenMailAll(citizenObject); - sendNewCitizenMail(citizenObject); + addCitizen(citizen, true); } public void removeCitizen(long citizen) { + removeCitizen(citizen, true); + } + + public void addCitizen(long citizen, boolean sendMail) { + citizens.add(citizen); + NGECore core = NGECore.getInstance(); + CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); + if(citizenObject == null) + return; + if(sendMail) { + sendNewCitizenMailAll(citizenObject); + sendNewCitizenMail(citizenObject); + } + } + + public void removeCitizen(long citizen, boolean sendMail) { citizens.remove(citizen); NGECore core = NGECore.getInstance(); CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); if(citizenObject == null) return; - sendCitizenLeftMailAll(citizenObject); + if(sendMail) { + sendCitizenLeftMailAll(citizenObject); + } } public long getNextElectionDate() { diff --git a/src/services/playercities/PlayerCityService.java b/src/services/playercities/PlayerCityService.java index a1d17b65..5d497ea5 100644 --- a/src/services/playercities/PlayerCityService.java +++ b/src/services/playercities/PlayerCityService.java @@ -66,37 +66,11 @@ public class PlayerCityService implements INetworkDispatch { public PlayerCityService(NGECore core) { this.core = core; core.scriptService.callScript("scripts/", "cityRankCaps", "addCityRankCaps", core); - scheduler.scheduleAtFixedRate(() -> { - administratePlayerCities(); - }, 0, 1, TimeUnit.MINUTES); } public void addCityRankCap(String planetName, int[] caps) { cityRankCaps.put(planetName, caps); } - - public void administratePlayerCities() { - synchronized(playerCities){ - Vector unfoundedCities = new Vector(); - for (PlayerCity city : playerCities){ - - if (city.getNextCityUpdate() <= System.currentTimeMillis()) - city.processCityUpdate(); - - if (city.getNextElectionDate() <= System.currentTimeMillis()) - city.processElection(); - - if (! city.isFounded() && city.getFoundationTime()<=System.currentTimeMillis()-(60*60*24*1000)){ - if (! city.checkFoundationSuccess()) - unfoundedCities.add(city); - } - } - - if (unfoundedCities.size()>0){ - unfoundedCities.forEach(this::destroyCity); - } - } - } public boolean isRankCapped(Planet planet, int rank) { if(cityRankCaps.get(planet.getName()) == null) @@ -128,7 +102,7 @@ public class PlayerCityService implements INetworkDispatch { return; if(isRankCapped(actor.getPlanet(), PlayerCity.OUTPOST)) { - actor.sendSystemMessage("This Planet can not support any more cities", (byte) 0); + actor.sendSystemMessage("This Planet can not support any more cities.", (byte) 0); return; } @@ -164,6 +138,7 @@ public class PlayerCityService implements INetworkDispatch { } PlayerCity playerCity = addNewPlayerCity(actor, cityHall); + PlayerCityService.this.schedulePlayerCityUpdate(playerCity, PlayerCity.newCityGraceSpan); cityHall.setAttachment("structureCity", playerCity.getCityID()); actor.setAttachment("residentCity", playerCity.getCityID()); core.housingService.declareResidency(actor, cityHall); @@ -397,5 +372,11 @@ public class PlayerCityService implements INetworkDispatch { playerCities.remove(city); + } + + public void schedulePlayerCityUpdate(PlayerCity playerCity, long time) { + scheduler.schedule(() -> { + playerCity.processCityUpdate(); + }, time, TimeUnit.MILLISECONDS); } }