Public Repository for the Magicbane Shadowbane Emulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

548 lines
19 KiB

// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.objects;
import engine.Enum;
import engine.InterestManagement.RealmMap;
import engine.InterestManagement.WorldGrid;
import engine.db.archive.DataWarehouse;
import engine.db.archive.RealmRecord;
import engine.gameManager.BuildingManager;
import engine.gameManager.DbManager;
import engine.gameManager.GuildManager;
import engine.gameManager.PowersManager;
import engine.net.ByteBufferWriter;
import engine.net.client.msg.ErrorPopupMsg;
import engine.powers.PowersBase;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.awt.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
import static engine.Enum.CharterType;
public class Realm {
// Internal class cache
public static ConcurrentHashMap<Integer, Realm> _realms = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
public final int realmID;
private final float mapR; //Red color
private final float mapG; //Green color
private final float mapB; //Blue color
private final float mapA; //Alpha color
private final boolean canBeClaimed;
private final boolean canPlaceCities;
private final int numCities;
private final String realmName;
private final float mapY1;
private final float mapX1;
private final float mapY2;
private final float mapX2;
private final int stretchX;
private final int stretchY;
private final int locX;
private final int locY;
private final HashSet<Integer> cities = new HashSet<>();
public Color mapColor;
public LocalDateTime ruledSince;
private int rulingCityUUID;
private int rulingCharacterUUID;
private int rulingCharacterOrdinal;
private String rulingCharacterName;
private int rulingNationUUID;
private GuildTag rulingNationTags;
private String rulingNationName;
private int charterType;
private String hash;
/**
* ResultSet Constructor
*/
public Realm(ResultSet rs) throws SQLException {
this.mapColor = new Color(Integer.parseInt(rs.getString("realmColor"), 16));
this.mapR = (float) (mapColor.getRed() * 0.00392156863);
this.mapG = (float) (mapColor.getGreen() * 0.00392156863);
this.mapB = (float) (mapColor.getBlue() * 0.00392156863);
this.mapA = 1;
this.canBeClaimed = rs.getBoolean("canBeClaimed");
this.canPlaceCities = rs.getBoolean("canPlaceCities");
this.numCities = rs.getInt("numCities");
this.realmName = rs.getString("realmName");
this.rulingCityUUID = rs.getInt("rulingCityUID");
this.charterType = rs.getInt("charterType");
java.sql.Timestamp ruledTimeStamp = rs.getTimestamp("ruledSince");
if (ruledTimeStamp != null)
this.ruledSince = LocalDateTime.ofInstant(ruledTimeStamp.toInstant(), ZoneId.systemDefault());
this.mapY1 = rs.getFloat("mapY1");
this.mapX1 = rs.getFloat("mapX1");
this.mapY2 = rs.getFloat("mapY2");
this.mapX2 = rs.getFloat("mapX2");
this.stretchX = rs.getInt("stretchX");
this.stretchY = rs.getInt("stretchY");
this.locX = rs.getInt("locX");
this.locY = rs.getInt("locY");
this.realmID = rs.getInt("realmID");
this.hash = rs.getString("hash");
}
public static void configureAllRealms() {
for (Realm realm : Realm._realms.values()) {
realm.configure();
}
}
public static Realm getRealm(int realmID) {
return _realms.get(realmID);
}
public static boolean HasAllBlessings(PlayerCharacter claimer) {
if (claimer == null)
return false;
PowersBase powerBlessing = PowersManager.getPowerByIDString("BLS-POWER");
if (!claimer.effects.containsKey(Integer.toString(powerBlessing.getActions().get(0).getUUID())))
return false;
PowersBase wisdomBlessing = PowersManager.getPowerByIDString("BLS-POWER");
if (!claimer.effects.containsKey(Integer.toString(wisdomBlessing.getActions().get(0).getUUID())))
return false;
PowersBase fortuneBlessing = PowersManager.getPowerByIDString("BLS-FORTUNE");
return claimer.effects.containsKey(Integer.toString(fortuneBlessing.getActions().get(0).getUUID()));
}
public static float getRealmHealthMod(City city) {
Realm serverRealm;
int charterType;
float returnBonus = 0.0f;
serverRealm = RealmMap.getRealmForCity(city);
charterType = serverRealm.charterType;
switch (charterType) {
case 762228431:
returnBonus = 0.0f;
break;
case -15978914:
returnBonus = -.15f;
break;
case -600065291:
returnBonus = .15f;
break;
default:
break;
}
return returnBonus;
}
public static int getRealmMesh(City city) {
Realm serverRealm;
CharterType charterType;
serverRealm = city.getRealm();
charterType = CharterType.getCharterTypeByID(serverRealm.charterType);
return charterType.getMeshID();
}
public static void loadAllRealms() {
_realms = DbManager.RealmQueries.LOAD_ALL_REALMS();
}
public static boolean claimRealm(PlayerCharacter player, int charterUUID) {
Guild guild;
Realm realm;
City city;
Building tol;
float hPMod;
Warehouse warehouse;
boolean hasResources = true;
int resourceValue;
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false) {
ErrorPopupMsg.sendErrorPopup(player, 176); // Only guild leaders can claim a territory
return false;
}
guild = player.getGuild();
city = guild.getOwnedCity();
if (city == null) {
ErrorPopupMsg.sendErrorPopup(player, 179); // Only landed guilds may claim a territory
return false;
}
if (city.isLocationOnCityGrid(player.getLoc()) == false) {
ErrorPopupMsg.sendErrorPopup(player, 186); // Your tree is not inside a territory!
return false;
}
tol = city.getTOL();
if (tol.getRank() != 7) {
ErrorPopupMsg.sendErrorPopup(player, 181); // Your tree must be rank 7 before claiming a territory
return false;
}
realm = RealmMap.getRealmForCity(city);
if (realm.getCanBeClaimed() == false) {
ErrorPopupMsg.sendErrorPopup(player, 180); // This territory cannot be ruled by anyone
return false;
}
if (realm.isRuled() == true) {
ErrorPopupMsg.sendErrorPopup(player, 178); // This territory is already claimed
return false;
}
if (!HasAllBlessings(player)) {
ErrorPopupMsg.sendErrorPopup(player, 185); // You must seek the blessing of the three sages before you can rule
return false;
}
// Must have the required resources in warehouse to claim realm
warehouse = city.getWarehouse();
if (warehouse == null) {
ErrorPopupMsg.sendErrorPopup(player, 188); // You must have a warehouse to become a capital
return false;
}
resourceValue = warehouse.resources.get(ItemBase.getItemBase(7));
if (resourceValue < 5000000)
hasResources = false;
resourceValue = warehouse.resources.get(ItemBase.getItemBase(1580000));
if (resourceValue < 8000)
hasResources = false;
resourceValue = warehouse.resources.get(ItemBase.getItemBase(1580004));
if (resourceValue < 8000)
hasResources = false;
resourceValue = warehouse.resources.get(ItemBase.getItemBase(1580017));
if (resourceValue < 15)
hasResources = false;
resourceValue = warehouse.resources.get(ItemBase.getItemBase(1580018));
if (resourceValue < 15)
hasResources = false;
if (hasResources == false) {
ErrorPopupMsg.sendErrorPopup(player, 184); // Insufficient gold or resources to upgrade to capital
return false;
}
// Remove resources from warehouse before claiming realm
resourceValue = warehouse.resources.get(ItemBase.getItemBase(7));
if (DbManager.WarehouseQueries.updateGold(warehouse, resourceValue - 5000000) == true) {
warehouse.resources.put(ItemBase.getItemBase(7), resourceValue - 5000000);
Warehouse.AddTransactionToWarehouse(warehouse, Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Enum.ResourceType.GOLD, 5000000);
} else {
Logger.error("gold update failed for warehouse of UUID:" + warehouse.getObjectUUID());
return false;
}
resourceValue = warehouse.resources.get(ItemBase.getItemBase(1580000));
if (DbManager.WarehouseQueries.updateStone(warehouse, resourceValue - 8000) == true) {
warehouse.resources.put(ItemBase.getItemBase(1580000), resourceValue - 8000);
Warehouse.AddTransactionToWarehouse(warehouse, Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Enum.ResourceType.STONE, 8000);
} else {
Logger.error("stone update failed for warehouse of UUID:" + warehouse.getObjectUUID());
return false;
}
resourceValue = warehouse.resources.get(ItemBase.getItemBase(1580004));
if (DbManager.WarehouseQueries.updateLumber(warehouse, resourceValue - 8000) == true) {
warehouse.resources.put(ItemBase.getItemBase(1580004), resourceValue - 8000);
Warehouse.AddTransactionToWarehouse(warehouse, Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Enum.ResourceType.LUMBER, 8000);
} else {
Logger.error("lumber update failed for warehouse of UUID:" + warehouse.getObjectUUID());
return false;
}
resourceValue = warehouse.resources.get(ItemBase.getItemBase(1580017));
if (DbManager.WarehouseQueries.updateGalvor(warehouse, resourceValue - 15) == true) {
warehouse.resources.put(ItemBase.getItemBase(1580017), resourceValue - 15);
Warehouse.AddTransactionToWarehouse(warehouse, Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Enum.ResourceType.GALVOR, 15);
} else {
Logger.error("galvor update failed for warehouse of UUID:" + warehouse.getObjectUUID());
return false;
}
resourceValue = warehouse.resources.get(ItemBase.getItemBase(1580018));
if (DbManager.WarehouseQueries.updateWormwood(warehouse, resourceValue - 15) == true) {
warehouse.resources.put(ItemBase.getItemBase(1580018), resourceValue - 15);
Warehouse.AddTransactionToWarehouse(warehouse, Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Enum.ResourceType.WORMWOOD, 15);
} else {
Logger.error("wormwood update failed for warehouse of UUID:" + warehouse.getObjectUUID());
return false;
}
realm.claimRealmForCity(city, charterUUID);
BuildingManager.setRank(tol, 8);
WorldGrid.updateObject(tol);
for (Building building : city.getParent().zoneBuildingSet) {
if (building.getBlueprintUUID() != 0) {
// TOL Health set through regular linear equation
if (building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.TOL) {
continue;
}
hPMod = (building.getMaxHitPoints() * getRealmHealthMod(city));
building.setMaxHitPoints(building.getMaxHitPoints() + hPMod);
}
}
if (!guild.getNation().equals(guild)) {
guild.getNation().setRealmsOwned(guild.getNation().getRealmsOwned() + 1);
GuildManager.updateAllGuildTags(guild.getNation());
}
guild.setRealmsOwned(guild.getRealmsOwned() + 1);
GuildManager.updateAllGuildTags(guild);
AbstractCharacter.removeAllBlessings(player);
return true;
}
/*
* Getters
*/
public boolean isRuled() {
return (this.rulingCityUUID != 0);
}
public boolean getCanBeClaimed() {
return this.canBeClaimed;
}
public boolean getCanPlaceCities() {
return this.canPlaceCities;
}
public int getNumCities() {
return this.numCities;
}
public String getRealmName() {
return this.realmName;
}
public City getRulingCity() {
return City.getCity(this.rulingCityUUID);
}
// Call this after changing ownership before you serialize a realm
public int getRealmID() {
return this.realmID;
}
public void addCity(int cityUUID) {
if (!this.cities.add(cityUUID))
this.cities.add(cityUUID);
}
public void removeCity(int cityUUID) {
this.cities.remove(cityUUID);
}
public boolean isRealmFull() {
return this.cities.size() >= this.numCities;
}
public boolean isRealmFullAfterBane() {
return this.cities.size() > this.numCities;
}
public void configure() {
PlayerCharacter rulingCharacter;
// Configure what exactly? We won't send any of it.
if (this.rulingCityUUID == 0)
return;
if (this.getRulingCity() == null)
return;
if (this.getRulingCity().getTOL() == null)
return;
rulingCharacter = PlayerCharacter.getPlayerCharacter(this.getRulingCity().getTOL().getOwnerUUID());
if (rulingCharacter == null) {
Logger.info(this.realmName + " failed to load " + this.getRulingCity().getCityName() + " ID : " + this.rulingCityUUID);
return;
}
this.rulingCharacterUUID = rulingCharacter.getObjectUUID();
this.rulingCharacterOrdinal = rulingCharacter.getObjectType().ordinal();
this.rulingCharacterName = rulingCharacter.getFirstName() + ' ' + rulingCharacter.getLastName();
this.rulingNationUUID = rulingCharacter.getGuild().getNation().getObjectUUID();
this.rulingNationName = rulingCharacter.getGuild().getNation().getName();
this.rulingNationTags = rulingCharacter.getGuild().getNation().getGuildTag();
}
public void serializeForClientMsg(ByteBufferWriter writer) {
writer.putFloat(this.mapR);
writer.putFloat(this.mapG);
writer.putFloat(this.mapB);
writer.putFloat(this.mapA);
writer.put((byte) (this.canBeClaimed ? 0x1 : 0x0));
writer.put((byte) (this.canPlaceCities ? 0x1 : 0x0));
writer.putInt(this.numCities);
writer.putFloat(this.mapR);
writer.putFloat(this.mapG);
writer.putFloat(this.mapB);
writer.putFloat(this.mapA);
writer.putString(this.realmName);
if (isRuled() == true) {
writer.putInt(Enum.GameObjectType.Guild.ordinal());
writer.putInt(rulingNationUUID);
writer.putInt(rulingCharacterOrdinal);
writer.putInt(rulingCharacterUUID);
writer.putInt(Enum.GameObjectType.City.ordinal());
writer.putInt(rulingCityUUID);
writer.putLocalDateTime(this.ruledSince);
writer.putString(rulingNationName);
GuildTag._serializeForDisplay(rulingNationTags, writer);
writer.putString(rulingCharacterName);
writer.putInt(0xB); // Display Title: enum index starts at 10.
} else {
if (this.rulingCityUUID != 0)
Logger.error("Failed to Load realm info for city" + this.rulingCityUUID);
writer.putLong(0);
writer.putLong(0);
writer.putLong(0);
writer.put((byte) 1);
writer.put((byte) 0);
writer.putInt(0x64);
writer.put((byte) 0);
writer.put((byte) 0);
writer.put((byte) 0);
writer.putInt(0);
writer.putInt(0x10);
writer.putInt(0x10);
writer.putInt(0x10);
writer.putInt(0x0);
writer.putInt(0x0);
writer.putInt(0);
writer.putInt(0);
}
writer.putInt(0); // Male/Female
writer.putInt(this.charterType); // Charter Type
writer.putFloat(this.mapY1);
writer.putFloat(this.mapX1);
writer.putFloat(this.mapY2);
writer.putFloat(this.mapX2);
writer.putInt(this.stretchX);
writer.putInt(this.stretchY);
writer.putInt(this.locX);
writer.putInt(this.locY);
}
public void updateDatabase() {
DbManager.RealmQueries.REALM_UPDATE(this);
}
/**
* @return the charterType
*/
public int getCharterType() {
return charterType;
}
public void abandonRealm() {
// Push event to warehouse
RealmRecord realmRecord = RealmRecord.borrow(this, Enum.RecordEventType.LOST);
DataWarehouse.pushToWarehouse(realmRecord);
// No longer own a realm
this.getRulingCity().getGuild().setRealmsOwned(this.getRulingCity().getGuild().getRealmsOwned() - 1);
if (!this.getRulingCity().getGuild().getNation().equals(this.getRulingCity().getGuild()))
this.getRulingCity().getGuild().getNation().setRealmsOwned(this.getRulingCity().getGuild().getNation().getRealmsOwned() - 1);
// Configure realm
this.charterType = 0;
this.rulingCityUUID = 0;
this.ruledSince = null;
this.updateDatabase();
}
public void claimRealmForCity(City city, int charterType) {
// Configure realm
this.charterType = charterType;
this.rulingCityUUID = city.getObjectUUID();
this.ruledSince = LocalDateTime.now();
this.configure();
this.updateDatabase();
// Push event to warehouse
RealmRecord realmRecord = RealmRecord.borrow(this, Enum.RecordEventType.CAPTURE);
DataWarehouse.pushToWarehouse(realmRecord);
}
public String getHash() {
return hash;
}
}