/******************************************************************************* * Copyright (c) 2013 * * This File is part of NGECore2. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. ******************************************************************************/ package services.playercities; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Vector; import resources.objects.building.BuildingObject; import resources.objects.creature.CreatureObject; import resources.objects.waypoint.WaypointObject; import services.chat.Mail; import services.chat.WaypointAttachment; import main.NGECore; import engine.resources.objects.SWGObject; import engine.resources.scene.Point3D; /** * @author Charon */ public class PlayerCity implements Serializable { private static final long serialVersionUID = 1L; public static final int DESERTED = 0; public static final int NEWCITY = 0; public static final int OUTPOST = 1; public static final int VILLAGE = 2; public static final int TOWNSHIP = 3; public static final int CITY = 4; public static final int METROPOLIS = 5; public static final int CLONE_LAB = 1; public static final int DNA_LABORATORY = 2; public static final int ENCORE_PERFORMANCE = 3; public static final int ENTERTAINMENT_DISTRICT = 4; public static final int IMPROVED_JOB_MARKET = 5; public static final int MANUFACTURING_CENTER = 6; public static final int MEDICAL_CENTER = 7; public static final int RESEARCH_CENTER = 8; public static final int SAMPLE_RICH = 9; public static final int INDUSTRIAL_SOCIETY = 10; public static final int SCIENTIFIC_SOCIETY = 11; public static final int STRONGHOLD = 12; public static final String[] specialisationSTFNames = new String[]{"city_spec_cloning", "city_spec_bm_incubator", "city_spec_storyteller", "city_spec_entertainer", "city_spec_missions", "city_spec_industry", "city_spec_doctor", "city_spec_research", "city_spec_sample_rich", "city_spec_master_manufacturing", "city_spec_master_healing", "city_spec_stronghold"}; public static final int BANK = 1; public static final int CLONING_FACILITY = 2; public static final int GARAGE = 3; public static final int MEDIUM_GARDEN = 4; public static final int LARGE_GARDEN = 5; public static final int SHUTTLEPORT = 6; private String cityName = ""; private int cityID = -1; private Point3D cityCenterPosition = new Point3D(0,0,0); private int cityRadius = 0; private int cityRank = 0; private int specialization = -1; private long mayorID = 0L; private int cityTreasury = 0; private int maintenanceFee = 0; private int GCW_Alignment = 0; private long nextElectionDate = 0L; private long nextCityUpdate = 0L; private long foundationTime = 0L; private int incomeTax = 0; private int propertyTax = 0; private int salesTax = 0; private int travelTax = 0; private int garageTax = 0; private boolean founded = false; private boolean shuttlePort = false; private boolean registered = false; private boolean zoningEnabled = false; //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; private Vector placedStructures = new Vector(); private Vector citizens = new Vector(); private Vector electionCandidates = new Vector(); private Vector electionVotes = new Vector(); private Vector cityBanList = new Vector(); private Vector militiaList = new Vector(); private Vector foundersList = new Vector(); public PlayerCity(){} public PlayerCity(CreatureObject founder, int cityID){ setCityCenterPosition(founder.getPosition()); setCityRadius(150); setFoundationTime(System.currentTimeMillis()); setMaintenanceFee(1); setNextCityUpdate(foundationTime+cityUpdateSpan); setNextElectionDate(foundationTime+legislationPeriod); citizens.add(founder.getObjectID()); this.cityID = cityID; setMayorID(founder.getObjectID()); } public void handleGrantZoning() { } public void handleBuildRequest() { } public void checkPlacementPermission() { } public void processElection() { // ToDo: handle everything long winnerID = mayorID; mayorID = winnerID; electionVotes.clear(); electionCandidates.clear(); electionCandidates.add(mayorID); setNextElectionDate(System.currentTimeMillis()+legislationPeriod); } public void processCityUpdate() { // has something changed? System.out.println("processCityUpdate"); int censusResult = citizens.size(); int currentRank = getRank(); switch (currentRank) { case NEWCITY : if (censusResult>=5){ setRank(++currentRank); // Expand to Outpost sendCityExpandMailAll(); } if (censusResult<5){ // kill city } break; case OUTPOST : if (censusResult>=10){ setRank(++currentRank); // Expand to Village sendCityExpandMailAll(); } if (censusResult<5){ setRank(--currentRank); // Contract to Deserted sendCityContractMailAll(); } break; case VILLAGE : if (censusResult>=15){ setRank(++currentRank); // Expand to Township sendCityExpandMailAll(); } if (censusResult<10){ setRank(--currentRank); // Contract to Outpost sendCityContractMailAll(); } break; case TOWNSHIP : if (censusResult>=30){ setRank(++currentRank); // Expand to City sendCityExpandMailAll(); } if (censusResult<15){ setRank(--currentRank); // Contract to Village sendCityContractMailAll(); } break; case CITY : if (censusResult>=40){ setRank(++currentRank); // Expand to Metropolis sendCityExpandMailAll(); } if (censusResult<15){ setRank(--currentRank); // Contract to Township sendCityContractMailAll(); } break; case METROPOLIS : if (censusResult<40){ setRank(--currentRank); // Contract to City sendCityContractMailAll(); } break; } NGECore core = NGECore.getInstance(); // collect taxes for (long citizen : citizens) { CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); if(citizenObject == null) continue; // ToDo: Handle tax evaders etc. int incomeTax = getIncomeTax(); citizenObject.setBankCredits(citizenObject.getBankCredits()-incomeTax); cityTreasury += incomeTax; int propertyTaxRate = getPropertyTax()/100; Vector allStructuresOfCitizen = new Vector(); // Collect the structures int cumulatedPropertyTax = 0; for (BuildingObject structure : allStructuresOfCitizen){ cumulatedPropertyTax += propertyTaxRate*structure.getBMR(); } citizenObject.setBankCredits(citizenObject.getBankCredits()-cumulatedPropertyTax); cityTreasury += cumulatedPropertyTax; } demolishHighRankStructures(); setNextCityUpdate(System.currentTimeMillis()+cityUpdateSpan); } public void cityFixUp(){ } public void demolishHighRankStructures() { // Check if there are any structures in the city // that require a higher rank than the current one synchronized(placedStructures){ Vector wreckingBall = new Vector(); for (long structureID : placedStructures){ SWGObject structure = NGECore.getInstance().objectService.getObject(structureID); int structureCode = (int) structure.getAttachment("CityStructureCode"); if (structureCode==BANK && cityRank<2){ wreckingBall.add(structure); } if (structureCode==CLONING_FACILITY && cityRank<3){ wreckingBall.add(structure); } if (structureCode==GARAGE && cityRank<2){ wreckingBall.add(structure); } if (structureCode==MEDIUM_GARDEN && cityRank<2){ wreckingBall.add(structure); } if (structureCode==LARGE_GARDEN && cityRank<3){ wreckingBall.add(structure); } if (structureCode==SHUTTLEPORT && cityRank<4){ wreckingBall.add(structure); } } for (SWGObject wreck : wreckingBall){ placedStructures.remove(wreck.getObjectID()); NGECore.getInstance().objectService.destroyObject(wreck.getObjectID()); } } } public boolean checkFoundationSuccess() { Vector founders = getFoundersList(); Vector citizenList = getCitizens(); int founderCitizenCount = 0; NGECore core = NGECore.getInstance(); for (long founderId : founders){ CreatureObject citizenObject = core.objectService.getObject(founderId) == null ? core.objectService.getCreatureFromDB(founderId) : (CreatureObject) core.objectService.getObject(founderId); if(citizenObject == null) continue; if (citizenList.contains(founderId) && (long)citizenObject.getAttachment("residentCity")==this.getCityID()) founderCitizenCount++; } if (founderCitizenCount==founders.size()){ return true; // All founders are citizens now } return false; } public void calculateMaintenance() { } public void handleBanRequest() { } public void handlePardonRequest() { } public int getRank() { return cityRank; } public void setRank(int cityRank) { this.cityRank = cityRank; } public int getSpecialization() { return specialization; } public void setSpecialization(int specialization) { this.specialization = specialization; sendSpecUpdateMail(specialization); } public long getMayorID() { return mayorID; } public void setMayorID(long mayorID) { this.mayorID = mayorID; } public int getCityTreasury() { return cityTreasury; } public void setCityTreasury(int cityTreasury) { this.cityTreasury = cityTreasury; } public int getMaintenanceFee() { return maintenanceFee; } public void setMaintenanceFee(int maintenanceFee) { this.maintenanceFee = maintenanceFee; } public int getGCW_Alignment() { return GCW_Alignment; } public void setGCW_Alignment(int gCW_Alignment) { GCW_Alignment = gCW_Alignment; } public Vector getPlacedStructures() { synchronized(placedStructures){ return placedStructures; } } public void setPlacedStructures(Vector placedStructures) { synchronized(placedStructures){ this.placedStructures = placedStructures; } } public void addNewStructure(long newStructure) { synchronized(placedStructures){ this.placedStructures.add(newStructure); } } public Vector getCitizens() { synchronized(citizens){ return citizens; } } public void setCitizens(Vector citizens) { synchronized(citizens){ this.citizens = citizens; } } public void addCitizen(long citizen) { citizens.add(citizen); CreatureObject citizenObject = (CreatureObject) NGECore.getInstance().objectService.getObject(citizen); sendNewCitizenMailAll(citizenObject); sendNewCitizenMail(citizenObject); } public void removeCitizen(long citizen) { 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); } public long getNextElectionDate() { return nextElectionDate; } public void setNextElectionDate(long nextElectionDate) { this.nextElectionDate = nextElectionDate; } public Vector getElectionCandidates() { return electionCandidates; } public void setElectionCandidates(Vector electionCandidates) { this.electionCandidates = electionCandidates; } public long getNextCityUpdate() { return nextCityUpdate; } public void setNextCityUpdate(long nextCityUpdate) { this.nextCityUpdate = nextCityUpdate; } public Vector getCityBanList() { return cityBanList; } public void setCityBanList(Vector cityBanList) { this.cityBanList = cityBanList; } public Vector getElectionVotes() { return electionVotes; } public void addToElectionVotes(byte vote) { electionVotes.add(vote); } public void addToTreasury(int amountToAdd) { cityTreasury += amountToAdd; } public void removeFromTreasury(int amountToDeduct) { cityTreasury -= amountToDeduct; } // Stalinesque method :D public void setElectionVotes(Vector electionVotes) { this.electionVotes = electionVotes; } public Point3D getCityCenterPosition() { return cityCenterPosition; } public void setCityCenterPosition(Point3D cityCenterPosition) { this.cityCenterPosition = cityCenterPosition; } public int getCityRadius() { return cityRadius; } public void setCityRadius(int cityRadius) { this.cityRadius = cityRadius; } public Vector getMilitiaList() { return militiaList; } public void setMilitiaList(Vector militiaList) { this.militiaList = militiaList; } public Vector getFoundersList() { return foundersList; } public void setFoundersList(Vector foundersList) { this.foundersList = foundersList; } public long getFoundationTime() { return foundationTime; } public void setFoundationTime(long foundationTime) { this.foundationTime = foundationTime; } public boolean isFounded() { return founded; } public void setFounded(boolean founded) { this.founded = founded; } public String getCityName() { return cityName; } public void setCityName(String cityName) { this.cityName = cityName; sendNameChangeMail(cityName); return; } public int getCityID() { return cityID; } public void setCityID(int cityID) { this.cityID = cityID; } public int getIncomeTax() { return incomeTax; } public void setIncomeTax(int incomeTax) { this.incomeTax = incomeTax; } public int getPropertyTax() { return propertyTax; } public void setPropertyTax(int propertyTax) { this.propertyTax = propertyTax; } public int getSalesTax() { return salesTax; } public void setSalesTax(int salesTax) { this.salesTax = salesTax; } public int getTravelTax() { return travelTax; } public void setTravelTax(int travelTax) { this.travelTax = travelTax; } public int getGarageTax() { return garageTax; } public void setGarageTax(int garageTax) { this.garageTax = garageTax; } public boolean hasShuttlePort() { return shuttlePort; } public void setShuttlePort(boolean shuttlePort) { this.shuttlePort = shuttlePort; } public boolean isRegistered() { return registered; } public void setRegistered(boolean registered) { this.registered = registered; } public boolean isZoningEnabled() { return zoningEnabled; } public void setZoningEnabled(boolean zoningEnabled) { this.zoningEnabled = zoningEnabled; } public boolean isMilitiaMember(long actor){ if (getMilitiaList().contains(actor)) return true; return false; } public boolean hasCitizen(long actor){ if (getCitizens().contains(actor)) return true; return false; } public static String[] getSpecialisationSTFNames() { return specialisationSTFNames; } public List getSpecializationSTFNamesAsList() { return Arrays.asList(specialisationSTFNames); } public void sendSpecUpdateMail(int cityID) { // city_version_update_subject_4 // city_version_update_body_4 Vector citizenList = getCitizens(); NGECore core = NGECore.getInstance(); for (long citizen : citizenList){ CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); if(citizenObject == null) continue; Mail actorMail = new Mail(); actorMail.setMailId(NGECore.getInstance().chatService.generateMailId()); actorMail.setRecieverId(citizen); actorMail.setStatus(Mail.NEW); actorMail.setTimeStamp((int) (new Date().getTime() / 1000)); actorMail.setMessage("@city/city:city_version_update_body_4"); actorMail.setSubject("@city/city:city_version_update_subject_4"); actorMail.setSenderName("City: " + this.cityName); /* List attachments = new ArrayList(); WaypointAttachment attachment = new WaypointAttachment(); attachment.active = false; attachments.add(attachment); attachment.cellID = 0; attachment.color = (byte)1; attachment.name = "City"; attachment.planetCRC = engine.resources.common.CRC.StringtoCRC(citizenObject.getPlanet().getName()); attachment.positionX = object.getPosition().x; attachment.positionY = 0; attachment.positionZ = object.getPosition().z; actorMail.setWaypointAttachments(attachments);*/ NGECore.getInstance().chatService.storePersistentMessage(actorMail); if (citizenObject.getClient()!=null) NGECore.getInstance().chatService.sendPersistentMessageHeader(citizenObject.getClient(), actorMail); } } public void sendNameChangeMail(String name) { } public void sendNewCitizenMailAll(CreatureObject newCitizen) { Vector citizenList = getCitizens(); NGECore core = NGECore.getInstance(); for (long citizen : citizenList){ CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); if(citizenObject == null) continue; Mail actorMail = new Mail(); actorMail.setMailId(NGECore.getInstance().chatService.generateMailId()); actorMail.setRecieverId(citizen); actorMail.setStatus(Mail.NEW); actorMail.setTimeStamp((int) (new Date().getTime() / 1000)); actorMail.setMessage("@city/city:new_city_citizen_body"); actorMail.setSubject("@city/city:new_city_citizen_subject"); actorMail.setSenderName("City " + this.cityName); List attachments = new ArrayList(); WaypointObject constructionWaypoint = (WaypointObject)NGECore.getInstance().objectService.createObject("object/waypoint/shared_world_waypoint_blue.iff", citizenObject.getPlanet(), citizenObject.getPosition().x, 0 ,citizenObject.getPosition().z); WaypointAttachment attachment = new WaypointAttachment(); attachment.active = false; attachment.cellID = constructionWaypoint.getCellId(); attachment.color = (byte)1; attachment.name = "City"; attachment.planetCRC = engine.resources.common.CRC.StringtoCRC(citizenObject.getPlanet().getName()); attachment.positionX = citizenObject.getPosition().x; attachment.positionY = 0; attachment.positionZ = citizenObject.getPosition().z; attachments.add(attachment); actorMail.setWaypointAttachments(attachments); NGECore.getInstance().chatService.storePersistentMessage(actorMail); if (newCitizen.getClient()!=null) NGECore.getInstance().chatService.sendPersistentMessageHeader(newCitizen.getClient(), actorMail); } } public void sendNewCitizenMail(CreatureObject citizen) { Mail actorMail = new Mail(); actorMail.setMailId(NGECore.getInstance().chatService.generateMailId()); actorMail.setRecieverId(citizen.getObjectID()); actorMail.setStatus(Mail.NEW); actorMail.setTimeStamp((int) (new Date().getTime() / 1000)); actorMail.setMessage("@city/city:new_city_citizen_other_body"); actorMail.setSubject("@city/city:new_city_citizen_other_subject"); actorMail.setSenderName("City " + this.cityName); List attachments = new ArrayList(); WaypointObject constructionWaypoint = (WaypointObject)NGECore.getInstance().objectService.createObject("object/waypoint/shared_world_waypoint_blue.iff", citizen.getPlanet(), citizen.getPosition().x, 0 ,citizen.getPosition().z); WaypointAttachment attachment = new WaypointAttachment(); attachment.active = false; attachment.cellID = constructionWaypoint.getCellId(); attachment.color = (byte)1; attachment.name = "City"; attachment.planetCRC = engine.resources.common.CRC.StringtoCRC(citizen.getPlanet().getName()); attachment.positionX = citizen.getPosition().x; attachment.positionY = 0; attachment.positionZ = citizen.getPosition().z; attachments.add(attachment); actorMail.setWaypointAttachments(attachments); NGECore.getInstance().chatService.storePersistentMessage(actorMail); NGECore.getInstance().chatService.sendPersistentMessageHeader(citizen.getClient(), actorMail); } public void sendCitizenLeftMailAll(CreatureObject newCitizen) { Vector citizenList = getCitizens(); NGECore core = NGECore.getInstance(); for (long citizen : citizenList){ CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); if(citizenObject == null) continue; Mail actorMail = new Mail(); actorMail.setMailId(NGECore.getInstance().chatService.generateMailId()); actorMail.setRecieverId(citizen); actorMail.setStatus(Mail.NEW); actorMail.setTimeStamp((int) (new Date().getTime() / 1000)); actorMail.setMessage("@city/city:lost_citizen_body"); actorMail.setSubject("@city/city:lost_citizen_subject"); actorMail.setSenderName("City " + this.cityName); List attachments = new ArrayList(); WaypointObject constructionWaypoint = (WaypointObject)NGECore.getInstance().objectService.createObject("object/waypoint/shared_world_waypoint_blue.iff", citizenObject.getPlanet(), citizenObject.getPosition().x, 0 ,citizenObject.getPosition().z); WaypointAttachment attachment = new WaypointAttachment(); attachment.active = false; attachment.cellID = constructionWaypoint.getCellId(); attachment.color = (byte)1; attachment.name = "City"; attachment.planetCRC = engine.resources.common.CRC.StringtoCRC(citizenObject.getPlanet().getName()); attachment.positionX = citizenObject.getPosition().x; attachment.positionY = 0; attachment.positionZ = citizenObject.getPosition().z; attachments.add(attachment); actorMail.setWaypointAttachments(attachments); NGECore.getInstance().chatService.storePersistentMessage(actorMail); if (newCitizen.getClient()!=null) NGECore.getInstance().chatService.sendPersistentMessageHeader(newCitizen.getClient(), actorMail); } } public void sendCityExpandMailAll() { Vector citizenList = getCitizens(); NGECore core = NGECore.getInstance(); for (long citizen : citizenList){ CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); if(citizenObject == null) continue; Mail actorMail = new Mail(); actorMail.setMailId(NGECore.getInstance().chatService.generateMailId()); actorMail.setRecieverId(citizen); actorMail.setStatus(Mail.NEW); actorMail.setTimeStamp((int) (new Date().getTime() / 1000)); actorMail.setMessage("@city/city:city_expand_body"); actorMail.setSubject("@city/city:city_expand_subject"); actorMail.setSenderName("City " + this.cityName); List attachments = new ArrayList(); WaypointObject constructionWaypoint = (WaypointObject)NGECore.getInstance().objectService.createObject("object/waypoint/shared_world_waypoint_blue.iff", citizenObject.getPlanet(), citizenObject.getPosition().x, 0 ,citizenObject.getPosition().z); WaypointAttachment attachment = new WaypointAttachment(); attachment.active = false; attachment.cellID = constructionWaypoint.getCellId(); attachment.color = (byte)1; attachment.name = "City"; attachment.planetCRC = engine.resources.common.CRC.StringtoCRC(citizenObject.getPlanet().getName()); attachment.positionX = citizenObject.getPosition().x; attachment.positionY = 0; attachment.positionZ = citizenObject.getPosition().z; attachments.add(attachment); actorMail.setWaypointAttachments(attachments); NGECore.getInstance().chatService.storePersistentMessage(actorMail); } } public void sendCityContractMailAll() { Vector citizenList = getCitizens(); NGECore core = NGECore.getInstance(); for (long citizen : citizenList){ CreatureObject citizenObject = core.objectService.getObject(citizen) == null ? core.objectService.getCreatureFromDB(citizen) : (CreatureObject) core.objectService.getObject(citizen); if(citizenObject == null) continue; Mail actorMail = new Mail(); actorMail.setMailId(NGECore.getInstance().chatService.generateMailId()); actorMail.setRecieverId(citizen); actorMail.setStatus(Mail.NEW); actorMail.setTimeStamp((int) (new Date().getTime() / 1000)); actorMail.setMessage("@city/city:city_contract_body"); actorMail.setSubject("@city/city:city_contract_subject"); actorMail.setSenderName("City " + this.cityName); List attachments = new ArrayList(); WaypointObject constructionWaypoint = (WaypointObject)NGECore.getInstance().objectService.createObject("object/waypoint/shared_world_waypoint_blue.iff", citizenObject.getPlanet(), citizenObject.getPosition().x, 0 ,citizenObject.getPosition().z); WaypointAttachment attachment = new WaypointAttachment(); attachment.active = false; attachment.cellID = constructionWaypoint.getCellId(); attachment.color = (byte)1; attachment.name = "City"; attachment.planetCRC = engine.resources.common.CRC.StringtoCRC(citizenObject.getPlanet().getName()); attachment.positionX = citizenObject.getPosition().x; attachment.positionY = 0; attachment.positionZ = citizenObject.getPosition().z; attachments.add(attachment); actorMail.setWaypointAttachments(attachments); NGECore.getInstance().chatService.storePersistentMessage(actorMail); } } // Test method to be deleted later public void Add10MoreCitizens() { synchronized(citizens){ for (int i=0;i<10;i++){ this.citizens.add(this.getMayorID()); } } } // Test method to be deleted later public void Deduct10Citizens() { int citizenCount = this.getCitizens().size(); synchronized(citizens){ this.citizens.clear(); for (int i=0;i