Browse Source

Merge remote-tracking branch 'origin/post-wipe-merge' into new-mob-ai

master
FatBoy-DOTC 2 years ago
parent
commit
e640a5064c
  1. 6
      src/discord/handlers/StatusRequestHandler.java
  2. 137
      src/engine/Enum.java
  3. 54
      src/engine/InterestManagement/RealmMap.java
  4. 73
      src/engine/db/handlers/dbRunegateHandler.java
  5. 12
      src/engine/devcmd/cmds/GateInfoCmd.java
  6. 65
      src/engine/devcmd/cmds/HotzoneCmd.java
  7. 4
      src/engine/devcmd/cmds/MineActiveCmd.java
  8. 22
      src/engine/devcmd/cmds/RealmInfoCmd.java
  9. 7
      src/engine/devcmd/cmds/SetMineExpansion.java
  10. 3
      src/engine/devcmd/cmds/SetMineTypeCmd.java
  11. 98
      src/engine/devcmd/cmds/SetRateCmd.java
  12. 22
      src/engine/gameManager/ConfigManager.java
  13. 2
      src/engine/gameManager/DbManager.java
  14. 1
      src/engine/gameManager/DevCmdManager.java
  15. 14
      src/engine/gameManager/MaintenanceManager.java
  16. 2
      src/engine/gameManager/SimulationManager.java
  17. 110
      src/engine/gameManager/ZoneManager.java
  18. 10
      src/engine/jobs/CloseGateJob.java
  19. 73
      src/engine/net/client/ClientMessagePump.java
  20. 44
      src/engine/net/client/Protocol.java
  21. 6
      src/engine/net/client/handlers/ArcLoginNotifyMsgHandler.java
  22. 2
      src/engine/net/client/handlers/ArcMineChangeProductionMsgHandler.java
  23. 82
      src/engine/net/client/handlers/CityDataHandler.java
  24. 19
      src/engine/net/client/handlers/GuildCreationFinalizeHandler.java
  25. 20
      src/engine/net/client/handlers/PlaceAssetMsgHandler.java
  26. 2
      src/engine/net/client/handlers/RequestEnterWorldHandler.java
  27. 274
      src/engine/net/client/msg/CityDataMsg.java
  28. 16
      src/engine/net/client/msg/HotzoneChangeMsg.java
  29. 2
      src/engine/net/client/msg/WorldDataMsg.java
  30. 282
      src/engine/net/client/msg/WorldObjectMsg.java
  31. 18
      src/engine/net/client/msg/WorldRealmMsg.java
  32. 2
      src/engine/objects/City.java
  33. 52
      src/engine/objects/Experience.java
  34. 17
      src/engine/objects/ItemFactory.java
  35. 5
      src/engine/objects/LootTable.java
  36. 266
      src/engine/objects/Mine.java
  37. 9
      src/engine/objects/Mob.java
  38. 2
      src/engine/objects/PlayerCharacter.java
  39. 92
      src/engine/objects/Portal.java
  40. 23
      src/engine/objects/Realm.java
  41. 180
      src/engine/objects/Runegate.java
  42. 7
      src/engine/objects/Zone.java
  43. 4
      src/engine/powers/poweractions/ClaimMinePowerAction.java
  44. 28
      src/engine/powers/poweractions/OpenGatePowerAction.java
  45. 15
      src/engine/powers/poweractions/RunegateTeleportPowerAction.java
  46. 21
      src/engine/server/MBServerStatics.java
  47. 21
      src/engine/server/world/WorldServer.java
  48. 27
      src/engine/util/MapLoader.java
  49. 218
      src/engine/workthreads/HourlyJobThread.java

6
src/discord/handlers/StatusRequestHandler.java

@ -20,12 +20,8 @@ public class StatusRequestHandler {
String outString; String outString;
// Add version information
outString = "MagicBot: " + ConfigManager.MB_MAGICBOT_BOTVERSION.getValue() + "\n" +
"MagicBane: " + ConfigManager.MB_MAGICBOT_GAMEVERSION.getValue() + "\n";
// Add server status info // Add server status info
outString += "\nServer Status: "; outString = "Server Status: ";
if (LoginServer.isPortInUse(Integer.parseInt(ConfigManager.MB_WORLD_PORT.getValue()))) if (LoginServer.isPortInUse(Integer.parseInt(ConfigManager.MB_WORLD_PORT.getValue())))
outString += "ONLINE\n"; outString += "ONLINE\n";

137
src/engine/Enum.java

@ -9,7 +9,7 @@
package engine; package engine;
import ch.claude_martin.enumbitset.EnumBitSetHelper; import ch.claude_martin.enumbitset.EnumBitSetHelper;
import engine.gameManager.BuildingManager; import engine.gameManager.ConfigManager;
import engine.gameManager.PowersManager; import engine.gameManager.PowersManager;
import engine.gameManager.ZoneManager; import engine.gameManager.ZoneManager;
import engine.math.Vector2f; import engine.math.Vector2f;
@ -18,7 +18,6 @@ import engine.objects.*;
import engine.powers.EffectsBase; import engine.powers.EffectsBase;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
@ -441,77 +440,6 @@ public class Enum {
CAPTURE; CAPTURE;
} }
public enum RealmType {
SEAFLOOR(0, 0x000000),
JOTUNHEIM(131, 0x006cff),
BOGLANDS(184, 0x00b4ff),
ESTRAGOTH(213, 0x00ff90),
RENNONVALE(232, 0X00ffea),
VOLGAARD(56, 0x1e00ff),
VOSTRAGOTH(108, 0x245fae),
NARROWS(61, 0x2f20a0),
FENMARCH(170, 0x3fb5ab),
MAELSTROM(63, 0x503e3e),
FARRICH(185, 0x52cd98),
TYRRANTHMINOR(96, 0x606060),
GREYSWATHE(88, 0x6c419d),
SUNSANVIL(64, 0x7800ff),
THERRONMARCH(206, 0x7bcdef),
DYVRENGISLE(119, 0x826b9c),
KINGSLUND(60, 0x871a94),
OUTERISLES(29, 0xa01313),
KAELENSFJORD(165, 0xa0c04a),
VARMADAI(95, 0xa16d1b),
WESTERMOORE(73, 0xaa3374),
OBLIVION(171, 0xababab),
SUDRAGOTH(196, 0xbaff00),
SKAARTHOL(183, 0xcfc57f),
KHALURAM(71, 0xe400ff),
VARSHADDUR(132, 0xf2845d),
FORBIDDENISLE(18, 0xff0000),
PIRATEISLES(48, 0xff008a),
SWATHMOORE(66, 0xff4200),
ESSENGLUND(130, 0xff9c00),
RELGOTH(177, 0xffde00);
private final int realmID;
private final Color color;
private static final HashMap<Integer, Integer> _rgbToIDMap = new HashMap<>();
RealmType(int realmID, int colorRGB) {
this.realmID = realmID;
this.color = new Color(colorRGB);
}
public void addToColorMap() {
_rgbToIDMap.put(this.color.getRGB(), this.realmID);
}
public static int getRealmIDByRGB(int realmRGB) {
return _rgbToIDMap.get(realmRGB);
}
public int getRealmID() {
return realmID;
}
public static RealmType getRealmTypeByUUID(int realmUUID) {
RealmType returnType = RealmType.SEAFLOOR;
for (RealmType realmType : RealmType.values()) {
if (realmType.realmID == realmUUID)
returnType = realmType;
}
return returnType;
}
}
public enum TaxType { public enum TaxType {
PROFIT, PROFIT,
WEEKLY, WEEKLY,
@ -619,64 +547,29 @@ public class Enum {
} }
} }
public enum RunegateType { public enum PortalType {
EARTH(6f, 19.5f, 128, 33213), EARTH(6f, 19.5f, 128),
AIR(-6f, 19.5f, 256, 33170), AIR(-6f, 19.5f, 256),
FIRE(15f, 7.5f, 512, 49612), FIRE(15f, 7.5f, 512),
WATER(-15f, 8.5f, 1024, 53073), WATER(-15f, 8.5f, 1024),
SPIRIT(0, 10.5f, 2048, 33127), SPIRIT(0, 10.5f, 2048),
CHAOS(22f, 3.5f, 8192, 58093), CHAOS(22f, 3.5f, 8192),
OBLIV(0f, 42f, 16384, 60198), OBLIV(0f, 42f, 16384),
MERCHANT(-22f, 4.5f, 4096, 60245), MERCHANT(-22f, 4.5f, 4096),
FORBID(0.0f, 0.0f, 0, 54617); FORBID(0.0f, 0.0f, 0);
private final Vector2f offset; public final Vector2f offset;
private final int bitFlag; public final int effectFlag;
private final int buildingUUID;
RunegateType(float offsetX, float offsetY, int bitFlag, PortalType(float offsetX, float offsetY, int effectFlag) {
int buildingUUID) {
this.offset = new Vector2f(offsetX, offsetY); this.offset = new Vector2f(offsetX, offsetY);
this.bitFlag = bitFlag; this.effectFlag = effectFlag;
this.buildingUUID = buildingUUID;
}
public Vector2f getOffset() {
return this.offset;
}
public int getEffectFlag() {
return this.bitFlag;
}
public int getGateUUID() {
return this.buildingUUID;
}
public Building getGateBuilding() {
return BuildingManager.getBuilding(this.buildingUUID);
}
public static RunegateType getGateTypeFromUUID(int uuid) {
RunegateType outType = RunegateType.AIR;
for (RunegateType gateType : RunegateType.values()) {
if (gateType.buildingUUID == uuid) {
outType = gateType;
return outType;
}
} }
return outType;
} }
}
// Enum for ItemBase flags // Enum for ItemBase flags

54
src/engine/InterestManagement/RealmMap.java

@ -9,8 +9,8 @@
package engine.InterestManagement; package engine.InterestManagement;
/* This class is the main interface for Magicbane's /* This class is the main interface for Magicbane's
* Interest management facilities. * Interest management facilities.
*/ */
import engine.Enum; import engine.Enum;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
@ -24,15 +24,26 @@ import engine.server.MBServerStatics;
import engine.util.MapLoader; import engine.util.MapLoader;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.awt.*;
import java.util.HashMap;
import static engine.objects.Realm.getRealm; import static engine.objects.Realm.getRealm;
public class RealmMap { public enum RealmMap {
REALM_MAP;
// Spatial hashmap. Used for detecting which Realm // Spatial hashmap. Used for determining which Realm
// a player is currently in.. // a player is currently located within.
public static int[][] _realmImageMap; public static int[][] _realmImageMap;
private static final HashMap<Integer, Integer> _rgbToIDMap = new HashMap<>();
public static int getRealmIDByRGB(int realmRGB) {
return _rgbToIDMap.get(realmRGB);
}
public static int getRealmIDAtLocation(Vector3fImmutable pos) { public static int getRealmIDAtLocation(Vector3fImmutable pos) {
@ -41,14 +52,17 @@ public class RealmMap {
if (yBuckets < 0 || yBuckets >= MBServerStatics.SPATIAL_HASH_BUCKETSY if (yBuckets < 0 || yBuckets >= MBServerStatics.SPATIAL_HASH_BUCKETSY
|| xBuckets < 0 || xBuckets >= MBServerStatics.SPATIAL_HASH_BUCKETSX) { || xBuckets < 0 || xBuckets >= MBServerStatics.SPATIAL_HASH_BUCKETSX) {
Logger.error("WorldServerRealm.getRealmFromPosition", Logger.error("Invalid range; Z: " + yBuckets + ", X: " + xBuckets);
"Invalid range; Z: " + yBuckets + ", X: " + xBuckets);
return 255; return 255;
} }
return RealmMap._realmImageMap[xBuckets][yBuckets]; return RealmMap._realmImageMap[xBuckets][yBuckets];
} }
public static void addToColorMap(Color color, int realmID) {
_rgbToIDMap.put(color.getRGB(), realmID);
}
public static Realm getRealmForCity(City city) { public static Realm getRealmForCity(City city) {
Realm outRealm = null; Realm outRealm = null;
outRealm = city.getRealm(); outRealm = city.getRealm();
@ -61,28 +75,28 @@ public class RealmMap {
} }
public static void updateRealm(PlayerCharacter player){ public static void updateRealm(PlayerCharacter player) {
int realmID = RealmMap.getRealmIDAtLocation(player.getLoc()); int realmID = RealmMap.getRealmIDAtLocation(player.getLoc());
if (realmID != player.getLastRealmID()){ if (realmID != player.getLastRealmID()) {
player.setLastRealmID(realmID); player.setLastRealmID(realmID);
Realm realm = Realm.getRealm(realmID); Realm realm = Realm.getRealm(realmID);
if (realm != null){ if (realm != null) {
if (realm.isRuled()){ if (realm.isRuled()) {
City city = realm.getRulingCity(); City city = realm.getRulingCity();
if (city != null){ if (city != null) {
TerritoryChangeMessage tcm = new TerritoryChangeMessage((PlayerCharacter)realm.getRulingCity().getOwner(),realm); TerritoryChangeMessage tcm = new TerritoryChangeMessage((PlayerCharacter) realm.getRulingCity().getOwner(), realm);
Dispatch dispatch = Dispatch.borrow(player, tcm); Dispatch dispatch = Dispatch.borrow(player, tcm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
}else{ } else {
TerritoryChangeMessage tcm = new TerritoryChangeMessage(null,realm); TerritoryChangeMessage tcm = new TerritoryChangeMessage(null, realm);
Dispatch dispatch = Dispatch.borrow(player, tcm); Dispatch dispatch = Dispatch.borrow(player, tcm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
} }
}else{ } else {
TerritoryChangeMessage tcm = new TerritoryChangeMessage(null,realm); TerritoryChangeMessage tcm = new TerritoryChangeMessage(null, realm);
Dispatch dispatch = Dispatch.borrow(player, tcm); Dispatch dispatch = Dispatch.borrow(player, tcm);
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
} }
@ -95,6 +109,12 @@ public class RealmMap {
public static void loadRealmImageMap() { public static void loadRealmImageMap() {
// Build color lookup map for realms from database
for (Realm realm : Realm._realms.values()) {
RealmMap.addToColorMap(realm.mapColor, realm.realmID);
}
RealmMap._realmImageMap = MapLoader.loadMap(); RealmMap._realmImageMap = MapLoader.loadMap();
} }

73
src/engine/db/handlers/dbRunegateHandler.java

@ -0,0 +1,73 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.db.handlers;
import engine.Enum;
import engine.gameManager.DbManager;
import engine.objects.Building;
import engine.objects.Portal;
import engine.objects.Resists;
import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class dbRunegateHandler extends dbHandlerBase {
public dbRunegateHandler() {
}
public ArrayList<Integer> GET_RUNEGATE_LIST() {
ArrayList<Integer> gateList = new ArrayList<>();
prepareCallable("SELECT DISTINCT `sourceBuilding` FROM `static_runegate_portals`;");
try {
ResultSet rs = executeQuery();
while (rs.next()) {
gateList.add(rs.getInt("sourceBuilding"));
}
} catch (SQLException e) {
} finally {
closeCallable();
}
return gateList;
}
public ArrayList<Portal> GET_PORTAL_LIST(int gateUID) {
ArrayList<Portal> portalList = new ArrayList<>();
Building sourceBuilding = (Building) DbManager.getObject(Enum.GameObjectType.Building, gateUID);
prepareCallable("SELECT * FROM `static_runegate_portals` WHERE `sourceBuilding` = ?;");
setInt(1, gateUID);
try {
ResultSet rs = executeQuery();
while (rs.next()) {
int targetBuildingID = rs.getInt("targetBuilding");
Building targetBuilding = (Building) DbManager.getObject(Enum.GameObjectType.Building, targetBuildingID);
Enum.PortalType portalType = Enum.PortalType.valueOf(rs.getString("portalType"));
Portal portal = new Portal(sourceBuilding, portalType, targetBuilding);
portalList.add(portal);
}
} catch (SQLException e) {
} finally {
closeCallable();
}
return portalList;
}
}

12
src/engine/devcmd/cmds/GateInfoCmd.java

@ -2,7 +2,6 @@ package engine.devcmd.cmds;
import engine.Enum.BuildingGroup; import engine.Enum.BuildingGroup;
import engine.Enum.GameObjectType; import engine.Enum.GameObjectType;
import engine.Enum.RunegateType;
import engine.devcmd.AbstractDevCmd; import engine.devcmd.AbstractDevCmd;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.objects.*; import engine.objects.*;
@ -21,7 +20,6 @@ public class GateInfoCmd extends AbstractDevCmd {
Building targetBuilding; Building targetBuilding;
String outString; String outString;
RunegateType runegateType;
Runegate runeGate; Runegate runeGate;
Blueprint blueprint; Blueprint blueprint;
String newline = "\r\n "; String newline = "\r\n ";
@ -41,10 +39,10 @@ public class GateInfoCmd extends AbstractDevCmd {
return; return;
} }
runegateType = RunegateType.getGateTypeFromUUID(targetBuilding.getObjectUUID());
runeGate = Runegate.getRunegates()[runegateType.ordinal()];
outString = "RungateType: " + runegateType.name(); runeGate = Runegate._runegates.get(targetBuilding.getObjectUUID());
outString = "RungateType: " + runeGate.gateBuilding.getName();
outString += newline; outString += newline;
outString += "Portal State:"; outString += "Portal State:";
@ -52,9 +50,9 @@ public class GateInfoCmd extends AbstractDevCmd {
for (Portal portal : runeGate.getPortals()) { for (Portal portal : runeGate.getPortals()) {
outString += "Portal: " + portal.getPortalType().name(); outString += "Portal: " + portal.portalType.name();
outString += " Active: " + portal.isActive(); outString += " Active: " + portal.isActive();
outString += " Dest: " + portal.getDestinationGateType().name(); outString += " Dest: " + portal.targetGate.getName();
outString += newline; outString += newline;
outString += " Origin: " + portal.getPortalLocation().x + 'x'; outString += " Origin: " + portal.getPortalLocation().x + 'x';
outString += " " + portal.getPortalLocation().y + 'y'; outString += " " + portal.getPortalLocation().y + 'y';

65
src/engine/devcmd/cmds/HotzoneCmd.java

@ -22,9 +22,8 @@ import engine.server.world.WorldServer;
/** /**
* ./hotzone <- display the current hotzone & time remaining * ./hotzone <- display the current hotzone & time remaining
* ./hotzone random <- change hotzone to random new zone * ./hotzone random <- change hotzone to random new zone
* ./hotzone name of a macrozone <- change hotzone to the zone name provided
*
*/ */
public class HotzoneCmd extends AbstractDevCmd { public class HotzoneCmd extends AbstractDevCmd {
public HotzoneCmd() { public HotzoneCmd() {
@ -32,83 +31,51 @@ public class HotzoneCmd extends AbstractDevCmd {
} }
@Override @Override
protected void _doCmd(PlayerCharacter pc, String[] words, protected void _doCmd(PlayerCharacter playerCharacter, String[] words,
AbstractGameObject target) { AbstractGameObject target) {
StringBuilder data = new StringBuilder(); StringBuilder data = new StringBuilder();
String outString;
for (String s : words) { for (String s : words) {
data.append(s); data.append(s);
data.append(' '); data.append(' ');
} }
String input = data.toString().trim(); String input = data.toString().trim();
if (input.length() == 0) { if (input.length() == 0) {
throwbackInfo(pc, "Current hotzone: " + hotzoneInfo()); outString = "Current hotZone: " + ZoneManager.hotZone.getName() + "\r\n";
outString += "Available hotZones: " + ZoneManager.availableHotZones();
throwbackInfo(playerCharacter, outString);
return; return;
} }
Zone zone;
if (input.equalsIgnoreCase("random")) { if (input.equalsIgnoreCase("random")) {
throwbackInfo(pc, "Previous hotzone: " + hotzoneInfo());
ZoneManager.generateAndSetRandomHotzone(); ZoneManager.generateAndSetRandomHotzone();
zone = ZoneManager.getHotZone(); outString = "New hotZone: " + ZoneManager.hotZone.getName() + "\r\n";
} else { outString += "Available hotZones: " + ZoneManager.availableHotZones();
zone = ZoneManager.findMacroZoneByName(input); throwbackInfo(playerCharacter, outString);
if (zone == null) {
throwbackError(pc, "Cannot find a macrozone with that name.");
return; return;
} }
if (zone == ZoneManager.getHotZone()) { if (input.equalsIgnoreCase("reset")) {
throwbackInfo(pc, "That macrozone is already the Hotzone."); ZoneManager.resetHotZones();
throwbackInfo(playerCharacter, "Available hotZones: " + ZoneManager.availableHotZones());
return; return;
} }
if (ZoneManager.validHotZone(zone) == false) {
throwbackError(pc, "That macrozone cannot be set as the Hotzone.");
return; return;
} }
throwbackInfo(pc, "Previous hotzone: " + hotzoneInfo());
ZoneManager.setHotZone(zone);
}
throwbackInfo(pc, "New hotzone: " + hotzoneInfo());
HotzoneChangeMsg hcm = new HotzoneChangeMsg(zone.getObjectType().ordinal(), zone.getObjectUUID());
WorldServer.setLastHZChange(System.currentTimeMillis());
}
@Override @Override
protected String _getHelpString() { protected String _getHelpString() {
return "Use no arguments to see the current hotzone. Specify a macrozone name to change the hotzone, or \"random\" to change it randomly."; return "Use no arguments to see the current hotzone or \"random\" to change it randomly.";
} }
@Override @Override
protected String _getUsageString() { protected String _getUsageString() {
return "'./hotzone [random | <macroZoneName>]"; return "'./hotzone [random]";
} }
private static String hotzoneInfo() {
final int hotzoneTimeLeft = FastMath.secondsUntilNextHour();
final Zone hotzone = ZoneManager.getHotZone();
String hotzoneInfo;
if (hotzone == null) {
hotzoneInfo = "none";
} else {
int hr = hotzoneTimeLeft/3600;
int rem = hotzoneTimeLeft%3600;
int mn = rem/60;
int sec = rem%60;
hotzoneInfo = hotzone.getName() +
" (" + (hr<10 ? "0" : "") + hr + ':' +
(mn<10 ? "0" : "") + mn + ':' +
(sec<10 ? "0" : "") + sec +
" remaining)";
}
return hotzoneInfo;
}
} }

4
src/engine/devcmd/cmds/MineActiveCmd.java

@ -39,14 +39,12 @@ public class MineActiveCmd extends AbstractDevCmd {
return; return;
String trigger = args[0]; String trigger = args[0];
switch (trigger){ switch (trigger) {
case "true": case "true":
HourlyJobThread.mineWindowOpen(mine); HourlyJobThread.mineWindowOpen(mine);
Mine.setLastChange(System.currentTimeMillis());
break; break;
case "false": case "false":
HourlyJobThread.mineWindowClose(mine); HourlyJobThread.mineWindowClose(mine);
Mine.setLastChange(System.currentTimeMillis());
break; break;
default: default:
this.sendUsage(pcSender); this.sendUsage(pcSender);

22
src/engine/devcmd/cmds/RealmInfoCmd.java

@ -26,43 +26,39 @@ public class RealmInfoCmd extends AbstractDevCmd {
} }
@Override @Override
protected void _doCmd(PlayerCharacter pc, String[] words, protected void _doCmd(PlayerCharacter playerCharacter, String[] words,
AbstractGameObject target) { AbstractGameObject target) {
Zone serverZone; Zone serverZone;
Zone parentZone;
Realm serverRealm; Realm serverRealm;
int realmID; int realmID;
String outString = ""; String outString = "";
if (pc == null) { if (playerCharacter == null)
throwbackError(pc, "Unable to find the pc making the request.");
return; return;
}
serverZone = ZoneManager.findSmallestZone(pc.getLoc()); serverZone = ZoneManager.findSmallestZone(playerCharacter.getLoc());
if (serverZone == null) { if (serverZone == null) {
throwbackError(pc, "Zone not found"); throwbackError(playerCharacter, "Zone not found");
return; return;
} }
parentZone = serverZone.getParent(); realmID = RealmMap.getRealmIDAtLocation(playerCharacter.getLoc());
realmID = RealmMap.getRealmIDAtLocation(pc.getLoc());
String newline = "\r\n "; String newline = "\r\n ";
outString = newline; outString = newline;
outString += "RealmID: " + realmID; outString += "Realm: " + realmID + "(";
serverRealm = Realm.getRealm(realmID); serverRealm = Realm.getRealm(realmID);
if (serverRealm == null) if (serverRealm == null)
outString += " Name: SeaFloor"; outString += "SeaFloor";
else else
outString += serverRealm.getRealmName(); outString += serverRealm.getRealmName();
outString += ")";
outString += newline; outString += newline;
outString += " Zone: " + serverZone.getName(); outString += " Zone: " + serverZone.getName();
@ -76,7 +72,7 @@ public class RealmInfoCmd extends AbstractDevCmd {
outString += newline; outString += newline;
throwbackInfo(pc, outString); throwbackInfo(playerCharacter, outString);
} }
@Override @Override

7
src/engine/devcmd/cmds/SetMineExpansion.java

@ -21,9 +21,7 @@ import engine.objects.Mine;
import engine.objects.PlayerCharacter; import engine.objects.PlayerCharacter;
/** /**
*
* @author Eighty * @author Eighty
*
*/ */
public class SetMineExpansion extends AbstractDevCmd { public class SetMineExpansion extends AbstractDevCmd {
@ -54,7 +52,6 @@ public class SetMineExpansion extends AbstractDevCmd {
return; return;
mine.setFlags(bit); mine.setFlags(bit);
ChatManager.chatSystemInfo(pcSender, mine.getZoneName() + "'s " + mine.getMineType().name + " is now an expansion mine."); ChatManager.chatSystemInfo(pcSender, mine.getZoneName() + "'s " + mine.getMineType().name + " is now an expansion mine.");
Mine.setLastChange(System.currentTimeMillis());
break; break;
case "OFF": case "OFF":
@ -63,15 +60,11 @@ public class SetMineExpansion extends AbstractDevCmd {
return; return;
mine.setFlags(bit); mine.setFlags(bit);
ChatManager.chatSystemInfo(pcSender, mine.getZoneName() + "'s " + mine.getMineType().name + " is no longer an expansion mine."); ChatManager.chatSystemInfo(pcSender, mine.getZoneName() + "'s " + mine.getMineType().name + " is no longer an expansion mine.");
Mine.setLastChange(System.currentTimeMillis());
break; break;
} }
} }
@Override @Override

3
src/engine/devcmd/cmds/SetMineTypeCmd.java

@ -18,9 +18,7 @@ import engine.gameManager.DbManager;
import engine.objects.*; import engine.objects.*;
/** /**
*
* @author Eighty * @author Eighty
*
*/ */
public class SetMineTypeCmd extends AbstractDevCmd { public class SetMineTypeCmd extends AbstractDevCmd {
@ -49,7 +47,6 @@ public class SetMineTypeCmd extends AbstractDevCmd {
return; return;
mine.setMineType(mineType.name()); mine.setMineType(mineType.name());
ChatManager.chatSystemInfo(pcSender, "The mine in " + mine.getZoneName() + " is now a(n) " + mine.getMineType().name); ChatManager.chatSystemInfo(pcSender, "The mine in " + mine.getZoneName() + " is now a(n) " + mine.getMineType().name);
Mine.setLastChange(System.currentTimeMillis());
} }
@Override @Override

98
src/engine/devcmd/cmds/SetRateCmd.java

@ -1,98 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.objects.AbstractGameObject;
import engine.objects.PlayerCharacter;
import engine.server.MBServerStatics;
/**
*
* @author Murray
*
*/
public class SetRateCmd extends AbstractDevCmd {
public SetRateCmd() {
super("setrate");
}
@Override
protected void _doCmd(PlayerCharacter pc, String[] args, AbstractGameObject target) {
if (args.length != 2) {
this.sendUsage(pc);
return;
}
float mod = 0f;
try {
mod = Float.parseFloat(args[1]);
} catch (NumberFormatException e) {
throwbackError(pc, "Supplied data failed to parse to Float.");
return;
}
if (args[0].equals("exp")){
MBServerStatics.EXP_RATE_MOD = mod;
throwbackInfo(pc, "Experience Rate set to: " + mod);
} else if (args[0].equals("gold")){
MBServerStatics.GOLD_RATE_MOD = mod;
throwbackInfo(pc, "Gold Rate set to: " + mod);
} else if (args[0].equals("drop")){
MBServerStatics.DROP_RATE_MOD = mod;
throwbackInfo(pc, "Drop Multiplier Rate set to: " + mod);
} else if (args[0].equals("hotexp")){
MBServerStatics.HOT_EXP_RATE_MOD = mod;
throwbackInfo(pc, "HOTZONE Experience Rate set to: " + mod);
} else if (args[0].equals("hotgold")){
MBServerStatics.HOT_GOLD_RATE_MOD = mod;
throwbackInfo(pc, "HOTZONE Gold Rate set to: " + mod);
} else if (args[0].equals("hotdrop")){
MBServerStatics.HOT_DROP_RATE_MOD = mod;
throwbackInfo(pc, "HOTZONE Drop Multiplier Rate set to: " + mod);
} else if (args[0].equals("production")){
MBServerStatics.PRODUCTION_TIME_MULTIPLIER = mod;
throwbackInfo(pc, "Production Time Multiplier Rate set to: " + mod);
} else {
this.sendUsage(pc);
}
}
@Override
protected String _getUsageString() {
return "' /setrate {exp|gold|drop|hotexp|hotgold|hotdrop} rate'";
}
@Override
protected String _getHelpString() {
return "Sets the rates for exp, gold or drops. Accepts a float, defaults to 1.0";
}
}

22
src/engine/gameManager/ConfigManager.java

@ -62,10 +62,20 @@ public enum ConfigManager {
MB_WORLD_UUID, MB_WORLD_UUID,
MB_WORLD_WAREHOUSE_PUSH, MB_WORLD_WAREHOUSE_PUSH,
MB_WORLD_MAINTENANCE, MB_WORLD_MAINTENANCE,
MB_WORLD_MAINTENANCE_HOUR,
MB_WORLD_GREETING, MB_WORLD_GREETING,
MB_WORLD_KEYCLONE_MAX, MB_WORLD_KEYCLONE_MAX,
//drop rates
MB_NORMAL_EXP_RATE,
MB_NORMAL_DROP_RATE,
MB_HOTZONE_EXP_RATE,
MB_HOTZONE_DROP_RATE,
MB_HOTZONE_DURATION,
MB_HOTZONE_MIN_LEVEL,
MB_PRODUCTION_RATE,
// MagicBot configuration. // MagicBot configuration.
MB_MAGICBOT_SERVERID, MB_MAGICBOT_SERVERID,
@ -78,9 +88,7 @@ public enum ConfigManager {
MB_MAGICBOT_GENERAL, MB_MAGICBOT_GENERAL,
MB_MAGICBOT_FORTOFIX, MB_MAGICBOT_FORTOFIX,
MB_MAGICBOT_RECRUIT, MB_MAGICBOT_RECRUIT,
MB_MAGICBOT_ADMINLOG, MB_MAGICBOT_ADMINLOG;
MB_MAGICBOT_BOTVERSION,
MB_MAGICBOT_GAMEVERSION;
// Map to hold our config pulled in from the environment // Map to hold our config pulled in from the environment
// We also use the config to point to the current message pump // We also use the config to point to the current message pump
@ -95,9 +103,10 @@ public enum ConfigManager {
// Called at bootstrap: ensures that all config values are loaded. // Called at bootstrap: ensures that all config values are loaded.
public static boolean init() { public static boolean init() {
Logger.info("ConfigManager: init()"); Logger.info("Loading config from environment...");
for (ConfigManager configSetting : ConfigManager.values()) for (ConfigManager configSetting : ConfigManager.values())
if (configMap.containsKey(configSetting.name())) if (configMap.containsKey(configSetting.name()))
@ -111,8 +120,9 @@ public enum ConfigManager {
// compile regex here // compile regex here
regex.put(MB_LOGIN_FNAME_REGEX, Pattern.compile(MB_LOGIN_FNAME_REGEX.getValue())); Logger.info("Compiling regex");
regex.put(MB_LOGIN_FNAME_REGEX, Pattern.compile(MB_LOGIN_FNAME_REGEX.getValue()));
return true; return true;
} }

2
src/engine/gameManager/DbManager.java

@ -311,4 +311,6 @@ public enum DbManager {
public static final dbBoonHandler BoonQueries = new dbBoonHandler(); public static final dbBoonHandler BoonQueries = new dbBoonHandler();
public static final dbShrineHandler ShrineQueries = new dbShrineHandler(); public static final dbShrineHandler ShrineQueries = new dbShrineHandler();
public static final dbHeightMapHandler HeightMapQueries = new dbHeightMapHandler(); public static final dbHeightMapHandler HeightMapQueries = new dbHeightMapHandler();
public static final dbRunegateHandler RunegateQueries = new dbRunegateHandler();
} }

1
src/engine/gameManager/DevCmdManager.java

@ -109,7 +109,6 @@ public enum DevCmdManager {
DevCmdManager.registerDevCmd(new GetCacheCountCmd()); DevCmdManager.registerDevCmd(new GetCacheCountCmd());
DevCmdManager.registerDevCmd(new GetRuneDropRateCmd()); DevCmdManager.registerDevCmd(new GetRuneDropRateCmd());
DevCmdManager.registerDevCmd(new DecachePlayerCmd()); DevCmdManager.registerDevCmd(new DecachePlayerCmd());
DevCmdManager.registerDevCmd(new SetRateCmd());
DevCmdManager.registerDevCmd(new AuditMobsCmd()); DevCmdManager.registerDevCmd(new AuditMobsCmd());
DevCmdManager.registerDevCmd(new ChangeNameCmd()); DevCmdManager.registerDevCmd(new ChangeNameCmd());
DevCmdManager.registerDevCmd(new GuildListCmd()); DevCmdManager.registerDevCmd(new GuildListCmd());

14
src/engine/gameManager/MaintenanceManager.java

@ -13,9 +13,12 @@ package engine.gameManager;
import engine.Enum; import engine.Enum;
import engine.objects.*; import engine.objects.*;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.time.DayOfWeek;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList; import java.util.ArrayList;
public enum MaintenanceManager { public enum MaintenanceManager {
@ -50,12 +53,12 @@ public enum MaintenanceManager {
if (chargeUpkeep(building) == false) if (chargeUpkeep(building) == false)
derankList.add(building); derankList.add(building);
} }
// Reset maintenance dates for these buildings // Reset maintenance dates for these buildings
for (Building building : maintList) for (Building building : maintList) {
setMaintDateTime(building, building.maintDateTime.plusDays(7)); setMaintDateTime(building, LocalDateTime.now().plusDays(7));
}
// Derak or destroy buildings that did not // Derak or destroy buildings that did not
// have funds available. // have funds available.
@ -120,6 +123,11 @@ public enum MaintenanceManager {
if (building.maintDateTime.isAfter(LocalDateTime.now())) if (building.maintDateTime.isAfter(LocalDateTime.now()))
continue; continue;
//no maintenance if day of week doesnt match
if(LocalDateTime.now().getDayOfWeek().ordinal() != building.maintDateTime.getDayOfWeek().ordinal()){
continue;
}
// Add building to maintenance queue // Add building to maintenance queue
maintList.add(building); maintList.add(building);

2
src/engine/gameManager/SimulationManager.java

@ -206,7 +206,7 @@ public enum SimulationManager {
*/ */
private void pulseRunegates() { private void pulseRunegates() {
for (Runegate runegate : Runegate.getRunegates()) { for (Runegate runegate : Runegate._runegates.values()) {
runegate.collidePortals(); runegate.collidePortals();
} }

110
src/engine/gameManager/ZoneManager.java

@ -17,9 +17,11 @@ import engine.objects.Building;
import engine.objects.City; import engine.objects.City;
import engine.objects.Zone; import engine.objects.Zone;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -35,15 +37,17 @@ public enum ZoneManager {
ZONEMANAGER; ZONEMANAGER;
public static Instant hotZoneLastUpdate;
/* Instance variables */ /* Instance variables */
private static Zone seaFloor = null; private static Zone seaFloor = null;
private static Zone hotzone = null; public static Zone hotZone = null;
private static ConcurrentHashMap<Integer, Zone> zonesByID = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD); public static int hotZoneCycle = 0; // Used with HOTZONE_DURATION from config.
private static ConcurrentHashMap<Integer, Zone> zonesByUUID = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD); private static final ConcurrentHashMap<Integer, Zone> zonesByID = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD);
private static ConcurrentHashMap<String, Zone> zonesByName = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD); private static final ConcurrentHashMap<Integer, Zone> zonesByUUID = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD);
private static Set<Zone> macroZones = Collections.newSetFromMap(new ConcurrentHashMap<>()); private static final ConcurrentHashMap<String, Zone> zonesByName = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD);
private static Set<Zone> npcCityZones = Collections.newSetFromMap(new ConcurrentHashMap<>()); public static final Set<Zone> macroZones = Collections.newSetFromMap(new ConcurrentHashMap<>());
private static Set<Zone> playerCityZones = Collections.newSetFromMap(new ConcurrentHashMap<>()); private static final Set<Zone> npcCityZones = Collections.newSetFromMap(new ConcurrentHashMap<>());
private static final Set<Zone> playerCityZones = Collections.newSetFromMap(new ConcurrentHashMap<>());
// Find all zones coordinates fit into, starting with Sea Floor // Find all zones coordinates fit into, starting with Sea Floor
@ -106,6 +110,31 @@ public enum ZoneManager {
} }
// Returns the number of available hotZones
// remaining in this cycle (1am)
public static int availableHotZones() {
int count = 0;
for (Zone zone : ZoneManager.macroZones)
if (ZoneManager.validHotZone(zone))
count = count + 1;
return count;
}
// Resets the availability of hotZones
// for this cycle
public static void resetHotZones() {
for (Zone zone : ZoneManager.macroZones)
if (zone.hasBeenHotzone)
zone.hasBeenHotzone = false;
}
public static Zone getZoneByUUID(final int zoneUUID) { public static Zone getZoneByUUID(final int zoneUUID) {
return ZoneManager.zonesByUUID.get(zoneUUID); return ZoneManager.zonesByUUID.get(zoneUUID);
} }
@ -119,22 +148,24 @@ public enum ZoneManager {
return ZoneManager.zonesByUUID.values(); return ZoneManager.zonesByUUID.values();
} }
public static final Zone getHotZone() {
return ZoneManager.hotzone;
}
public static final void setHotZone(final Zone zone) { public static final void setHotZone(final Zone zone) {
if (!zone.isMacroZone()) if (!zone.isMacroZone())
return; return;
ZoneManager.hotzone = zone;
ZoneManager.hotZone = zone;
ZoneManager.hotZoneCycle = 1; // Used with HOTZONE_DURATION from config.
zone.hasBeenHotzone = true;
ZoneManager.hotZoneLastUpdate = LocalDateTime.now().withMinute(0).withSecond(0).atZone(ZoneId.systemDefault()).toInstant();
} }
public static boolean inHotZone(final Vector3fImmutable loc) { public static boolean inHotZone(final Vector3fImmutable loc) {
if (ZoneManager.hotzone == null) if (ZoneManager.hotZone == null)
return false; return false;
return (Bounds.collide(loc, ZoneManager.hotzone.getBounds()) == true); return (Bounds.collide(loc, ZoneManager.hotZone.getBounds()) == true);
} }
public static void setSeaFloor(final Zone value) { public static void setSeaFloor(final Zone value) {
@ -185,32 +216,31 @@ public enum ZoneManager {
public static final void generateAndSetRandomHotzone() { public static final void generateAndSetRandomHotzone() {
Zone hotzone; Zone hotZone;
ArrayList<Integer> zoneArray = new ArrayList<>(); ArrayList<Integer> zoneArray = new ArrayList<>();
if (ZoneManager.macroZones.isEmpty()) if (ZoneManager.macroZones.isEmpty())
return; return;
for (Zone zone : ZoneManager.macroZones) { // Reset hotZone availability if none are left.
if (ZoneManager.availableHotZones() == 0)
ZoneManager.resetHotZones();
for (Zone zone : ZoneManager.macroZones)
if (validHotZone(zone)) if (validHotZone(zone))
zoneArray.add(zone.getObjectUUID()); zoneArray.add(zone.getObjectUUID());
}
int entryIndex = ThreadLocalRandom.current().nextInt(zoneArray.size()); int entryIndex = ThreadLocalRandom.current().nextInt(zoneArray.size());
hotzone = ZoneManager.getZoneByUUID(zoneArray.get(entryIndex)); hotZone = ZoneManager.getZoneByUUID(zoneArray.get(entryIndex));
if (hotzone == null){ if (hotZone == null) {
Logger.error( "Hotzone is null"); Logger.error("Hotzone is null");
return; return;
} }
ZoneManager.setHotZone(hotZone);
ZoneManager.setHotZone(hotzone);
WorldServer.setLastHZChange(System.currentTimeMillis());
} }
@ -225,12 +255,18 @@ public enum ZoneManager {
if (zone.equals(ZoneManager.seaFloor)) if (zone.equals(ZoneManager.seaFloor))
return false; return false;
// return false; //first time setting, accept it //no duplicate hotZones
// if (this.hotzone.getUUID() == zone.getUUID())
// return true; //no same hotzone
if (ZoneManager.hotzone != null) if (zone.hasBeenHotzone == true)
return ZoneManager.hotzone.getObjectUUID() != zone.getObjectUUID(); return false;
// Enforce min level
if (zone.minLvl < Integer.parseInt(ConfigManager.MB_HOTZONE_MIN_LEVEL.getValue()))
return false;
if (ZoneManager.hotZone != null)
return ZoneManager.hotZone.getObjectUUID() != zone.getObjectUUID();
return true; return true;
} }
@ -238,8 +274,7 @@ public enum ZoneManager {
/** /**
* Gets a MacroZone by name. * Gets a MacroZone by name.
* *
* @param inputName * @param inputName MacroZone name to search for
* MacroZone name to search for
* @return Zone of the MacroZone, or Null * @return Zone of the MacroZone, or Null
*/ */
@ -287,8 +322,6 @@ public enum ZoneManager {
localCoords.setY((serverZone.getBounds().getHalfExtents().y * 2) - localCoords.y); localCoords.setY((serverZone.getBounds().getHalfExtents().y * 2) - localCoords.y);
// TODO : Make sure this value does not go outside the zone's bounds. // TODO : Make sure this value does not go outside the zone's bounds.
return localCoords; return localCoords;
@ -327,7 +360,7 @@ public enum ZoneManager {
// handle building rotation // handle building rotation
// handle building translation // handle building translation
return building.getLoc().add(rotatedLocal.x, rotatedLocal.y,rotatedLocal.z); return building.getLoc().add(rotatedLocal.x, rotatedLocal.y, rotatedLocal.z);
} }
@ -341,11 +374,11 @@ public enum ZoneManager {
// handle building rotation // handle building rotation
// handle building translation // handle building translation
return new Vector3f(building.getLoc().add(rotatedLocal.x, rotatedLocal.y,rotatedLocal.z)); return new Vector3f(building.getLoc().add(rotatedLocal.x, rotatedLocal.y, rotatedLocal.z));
} }
public static Vector3fImmutable convertWorldToLocal(Building building, Vector3fImmutable WorldPos) { public static Vector3fImmutable convertWorldToLocal(Building building, Vector3fImmutable WorldPos) {
Vector3fImmutable convertLoc = Vector3fImmutable.rotateAroundPoint(building.getLoc(),WorldPos,-building.getBounds().getQuaternion().angleY); Vector3fImmutable convertLoc = Vector3fImmutable.rotateAroundPoint(building.getLoc(), WorldPos, -building.getBounds().getQuaternion().angleY);
convertLoc = convertLoc.subtract(building.getLoc()); convertLoc = convertLoc.subtract(building.getLoc());
@ -421,7 +454,6 @@ public enum ZoneManager {
zoneList = currentZone.getNodes(); zoneList = currentZone.getNodes();
for (Zone zone : zoneList) { for (Zone zone : zoneList) {
if (zone.isContininent()) if (zone.isContininent())

10
src/engine/jobs/CloseGateJob.java

@ -9,7 +9,8 @@
package engine.jobs; package engine.jobs;
import engine.Enum.RunegateType; import engine.Enum;
import engine.Enum.PortalType;
import engine.job.AbstractScheduleJob; import engine.job.AbstractScheduleJob;
import engine.objects.Building; import engine.objects.Building;
import engine.objects.Runegate; import engine.objects.Runegate;
@ -18,9 +19,10 @@ import org.pmw.tinylog.Logger;
public class CloseGateJob extends AbstractScheduleJob { public class CloseGateJob extends AbstractScheduleJob {
private final Building building; private final Building building;
private final RunegateType portalType; private final Enum.PortalType portalType;
public CloseGateJob(Building building, PortalType portalType) {
public CloseGateJob(Building building, RunegateType portalType) {
super(); super();
this.building = building; this.building = building;
this.portalType = portalType; this.portalType = portalType;
@ -34,7 +36,7 @@ public class CloseGateJob extends AbstractScheduleJob {
return; return;
} }
Runegate.getRunegates()[RunegateType.getGateTypeFromUUID(building.getObjectUUID()).ordinal()].deactivatePortal(portalType); Runegate._runegates.get(building.getObjectUUID()).deactivatePortal(portalType);
} }
@Override @Override

73
src/engine/net/client/ClientMessagePump.java

@ -97,9 +97,6 @@ public class ClientMessagePump implements NetMsgHandler {
case SETSELECTEDOBECT: case SETSELECTEDOBECT:
ClientMessagePump.targetObject((TargetObjectMsg) msg, origin); ClientMessagePump.targetObject((TargetObjectMsg) msg, origin);
break; break;
case CITYDATA:
ClientMessagePump.MapData(s, origin);
break;
/* /*
* Chat * Chat
@ -351,62 +348,6 @@ public class ClientMessagePump implements NetMsgHandler {
} }
private static void MapData(Session s, ClientConnection origin) {
Dispatch dispatch;
try{
if (s == null || origin == null)
return;
PlayerCharacter pc = s.getPlayerCharacter();
if (pc == null)
return;
boolean updateMine = false;
boolean updateCity = false;
//do not update Cities and mines everytime you open map. only update them to client when something's changed.
long lastRefresh = pc.getTimeStamp("mineupdate");
if (lastRefresh <= Mine.getLastChange()){
pc.setTimeStamp("mineupdate", System.currentTimeMillis());
updateMine = true;
}
long lastCityRefresh = pc.getTimeStamp("cityUpdate");
if (lastCityRefresh <= City.lastCityUpdate){
pc.setTimeStamp("cityUpdate", System.currentTimeMillis());
updateCity = true;
}
WorldObjectMsg wom = new WorldObjectMsg(s, false);
wom.updateMines(true);
wom.updateCities(updateCity);
dispatch = Dispatch.borrow(pc, wom);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
// }
lastRefresh = pc.getTimeStamp("hotzoneupdate");
if (lastRefresh <= WorldServer.getLastHZChange()) {
Zone hotzone = ZoneManager.getHotZone();
if (hotzone != null) {
HotzoneChangeMsg hcm = new HotzoneChangeMsg(hotzone.getObjectType().ordinal(), hotzone.getObjectUUID());
dispatch = Dispatch.borrow(pc, hcm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
pc.setTimeStamp("hotzoneupdate", System.currentTimeMillis() - 100);
}
}
WorldRealmMsg wrm = new WorldRealmMsg();
dispatch = Dispatch.borrow(pc, wrm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
}catch(Exception e){
e.printStackTrace();
}
}
private static void WhoRequest(WhoRequestMsg msg, ClientConnection origin) { private static void WhoRequest(WhoRequestMsg msg, ClientConnection origin) {
// Handle /who request // Handle /who request
@ -2183,23 +2124,17 @@ boolean updateCity = false;
Building rg = null; Building rg = null;
Vector3fImmutable rgLoc; Vector3fImmutable rgLoc;
for (Runegate runegate : Runegate.getRunegates()) { for (Runegate runegate : Runegate._runegates.values()) {
if ((runegate.getGateType() == RunegateType.OBLIV) ||
(runegate.getGateType() == RunegateType.CHAOS))
continue;
for (Runegate thisGate : Runegate.getRunegates()) { rgLoc = runegate.gateBuilding.getLoc();
rgLoc = thisGate.getGateType().getGateBuilding().getLoc();
float distanceSquaredToRunegate = player.getLoc().distanceSquared2D(rgLoc); float distanceSquaredToRunegate = player.getLoc().distanceSquared2D(rgLoc);
if (distanceSquaredToRunegate < sqr(dist)) if (distanceSquaredToRunegate < sqr(dist))
rg = thisGate.getGateType().getGateBuilding(); rg = runegate.gateBuilding;
} }
}
//nearest runegate found. teleport characterTarget //nearest runegate found. teleport characterTarget
if (rg != null) { if (rg != null) {

44
src/engine/net/client/Protocol.java

@ -26,7 +26,7 @@ public enum Protocol {
ACTIVATECHARTER(0x296C0B22, UseCharterMsg.class, null),// Use Guild Charter ACTIVATECHARTER(0x296C0B22, UseCharterMsg.class, null),// Use Guild Charter
ACTIVATENPC(0xC9AAE81E, ActivateNPCMessage.class, ActivateNPCMsgHandler.class), ACTIVATENPC(0xC9AAE81E, ActivateNPCMessage.class, ActivateNPCMsgHandler.class),
ACTIVATEPLEDGE(0x5A694DC0, SwearInMsg.class, SwearInHandler.class), // Swear In ACTIVATEPLEDGE(0x5A694DC0, SwearInMsg.class, SwearInHandler.class), // Swear In
ADDFRIEND(0xCFA1C787,AddFriendMessage.class,null), ADDFRIEND(0xCFA1C787, AddFriendMessage.class, null),
ALLIANCECHANGE(0x0E7D0B57, AllianceChangeMsg.class, AllianceChangeMsgHandler.class), // Remove From Allies/Enemies List ALLIANCECHANGE(0x0E7D0B57, AllianceChangeMsg.class, AllianceChangeMsgHandler.class), // Remove From Allies/Enemies List
ALLYENEMYLIST(0xAEA443FD, AllyEnemyListMsg.class, AllyEnemyListMsgHandler.class), ALLYENEMYLIST(0xAEA443FD, AllyEnemyListMsg.class, AllyEnemyListMsgHandler.class),
ARCCOMBATMODEATTACKING(0xD8B10579, SetCombatModeMsg.class, null), // Attack From Outside Combat Mode ARCCOMBATMODEATTACKING(0xD8B10579, SetCombatModeMsg.class, null), // Attack From Outside Combat Mode
@ -74,12 +74,12 @@ public enum Protocol {
CHECKUNIQUEGUILD(0x689097D7, GuildCreationOptionsMsg.class, GuildCreationOptionsHandler.class), // Set Guild Name/Motto in Use Guild Charter CHECKUNIQUEGUILD(0x689097D7, GuildCreationOptionsMsg.class, GuildCreationOptionsHandler.class), // Set Guild Name/Motto in Use Guild Charter
CITYASSET(0x7cae1678, CityAssetMsg.class, null), CITYASSET(0x7cae1678, CityAssetMsg.class, null),
CITYCHOICE(0x406610BB, CityChoiceMsg.class, CityChoiceMsgHandler.class), CITYCHOICE(0x406610BB, CityChoiceMsg.class, CityChoiceMsgHandler.class),
CITYDATA(0xB8A947D4, WorldObjectMsg.class, null), //Realm Data - Optional(?) CITYDATA(0xB8A947D4, CityDataMsg.class, CityDataHandler.class),
CITYZONE(0x254947F2, CityZoneMsg.class, null), //For Creating City Object Clientside(Terraform)/Rename City. CITYZONE(0x254947F2, CityZoneMsg.class, null), //For Creating City Object Clientside(Terraform)/Rename City.
CLAIMASSET(0x948C62CC, ClaimAssetMsg.class, ClaimAssetMsgHandler.class), // ClaimAsset CLAIMASSET(0x948C62CC, ClaimAssetMsg.class, ClaimAssetMsgHandler.class), // ClaimAsset
CLAIMGUILDTREE(0xFD1C6442, ClaimGuildTreeMsg.class, ClaimGuildTreeMsgHandler.class), CLAIMGUILDTREE(0xFD1C6442, ClaimGuildTreeMsg.class, ClaimGuildTreeMsgHandler.class),
CLIENTADMINCOMMAND(0x624EAB5F, ClientAdminCommandMsg.class, null), //Admin Command CLIENTADMINCOMMAND(0x624EAB5F, ClientAdminCommandMsg.class, null), //Admin Command
CLIENTUPDATEVAULT( 0x66EDBECD, UpdateVaultMsg.class, null), CLIENTUPDATEVAULT(0x66EDBECD, UpdateVaultMsg.class, null),
COMBATMODE(0xFE4BF353, ToggleCombatMsg.class, null), //Toggle Combat mode COMBATMODE(0xFE4BF353, ToggleCombatMsg.class, null), //Toggle Combat mode
CONFIRMPROMOTE(0x153BB5F9, ConfirmPromoteMsg.class, null), CONFIRMPROMOTE(0x153BB5F9, ConfirmPromoteMsg.class, null),
COSTTOOPENBANK(0x135BE5E8, AckBankWindowOpenedMsg.class, null), // ACK Bank Window Opened COSTTOOPENBANK(0x135BE5E8, AckBankWindowOpenedMsg.class, null), // ACK Bank Window Opened
@ -95,8 +95,8 @@ public enum Protocol {
EQUIP(0x3CB1AF8C, TransferItemFromInventoryToEquipMsg.class, null), // Transfer Item from Inventory to Equip EQUIP(0x3CB1AF8C, TransferItemFromInventoryToEquipMsg.class, null), // Transfer Item from Inventory to Equip
EXPERIENCE(0xC57802A7, GrantExperienceMsg.class, null), //TODO rename once identified EXPERIENCE(0xC57802A7, GrantExperienceMsg.class, null), //TODO rename once identified
FORGETOBJECTS(0xE307A0E1, UnloadObjectsMsg.class, null), // Unload Objects FORGETOBJECTS(0xE307A0E1, UnloadObjectsMsg.class, null), // Unload Objects
FRIENDACCEPT(0xCA297870,AcceptFriendMsg.class,FriendAcceptHandler.class), FRIENDACCEPT(0xCA297870, AcceptFriendMsg.class, FriendAcceptHandler.class),
FRIENDDECLINE(0xF08FC279,DeclineFriendMsg.class,FriendDeclineHandler.class), FRIENDDECLINE(0xF08FC279, DeclineFriendMsg.class, FriendDeclineHandler.class),
FURNITURE(0xCE7FA503, FurnitureMsg.class, FurnitureHandler.class), FURNITURE(0xCE7FA503, FurnitureMsg.class, FurnitureHandler.class),
GAMESERVERIPRESPONSE(0x6C95CF87, GameServerIPResponseMsg.class, null), // Game Server IP Response GAMESERVERIPRESPONSE(0x6C95CF87, GameServerIPResponseMsg.class, null), // Game Server IP Response
GLOBALCHANNELMESSAGE(0x2bf03fd2, null, null), GLOBALCHANNELMESSAGE(0x2bf03fd2, null, null),
@ -109,7 +109,7 @@ public enum Protocol {
GUILDMEMBERONLINE(0x7B79EB3A, GuildEnterWorldMsg.class, null), // Send Enter World Message to Guild GUILDMEMBERONLINE(0x7B79EB3A, GuildEnterWorldMsg.class, null), // Send Enter World Message to Guild
GUILDRANKCHANGE(0x0DEFB21F, ChangeRankMsg.class, ChangeRankHandler.class), // Change Rank GUILDRANKCHANGE(0x0DEFB21F, ChangeRankMsg.class, ChangeRankHandler.class), // Change Rank
GUILDTREESTATUS(0x4B95FB85, GuildTreeStatusMsg.class, null), GUILDTREESTATUS(0x4B95FB85, GuildTreeStatusMsg.class, null),
HIRELINGSERVICE(0xD3D93322,HirelingServiceMsg.class,HirelingServiceMsgHandler.class), HIRELINGSERVICE(0xD3D93322, HirelingServiceMsg.class, HirelingServiceMsgHandler.class),
IGNORE(0xBD8881EE, IgnoreMsg.class, null), //client sent /ignore command IGNORE(0xBD8881EE, IgnoreMsg.class, null), //client sent /ignore command
INITIATETRADEHUDS(0x667D29D8, OpenTradeWindowMsg.class, null), // Open Trade Window INITIATETRADEHUDS(0x667D29D8, OpenTradeWindowMsg.class, null), // Open Trade Window
INVITEGROUP(0x004A2012, GroupInviteMsg.class, GroupInviteHandler.class), // Send/Receive/Deny Group Invite INVITEGROUP(0x004A2012, GroupInviteMsg.class, GroupInviteHandler.class), // Send/Receive/Deny Group Invite
@ -168,7 +168,7 @@ public enum Protocol {
RECOMMENDNATION(0x6D4579E9, RecommendNationMsg.class, RecommendNationMsgHandler.class), // Recommend as Ally/Enemy, error RECOMMENDNATION(0x6D4579E9, RecommendNationMsg.class, RecommendNationMsgHandler.class), // Recommend as Ally/Enemy, error
RECYCLEPOWER(0x24033B67, RecyclePowerMsg.class, null), //Unlock power for reUse RECYCLEPOWER(0x24033B67, RecyclePowerMsg.class, null), //Unlock power for reUse
REMOVECHAR(0x5D3F9739, DeleteCharacterMsg.class, null), // Delete Character REMOVECHAR(0x5D3F9739, DeleteCharacterMsg.class, null), // Delete Character
REMOVEFRIEND(0xE0D5DB42,RemoveFriendMessage.class,RemoveFriendHandler.class), REMOVEFRIEND(0xE0D5DB42, RemoveFriendMessage.class, RemoveFriendHandler.class),
REPAIRBUILDING(0xAF8C2560, RepairBuildingMsg.class, RepairBuildingMsgHandler.class), REPAIRBUILDING(0xAF8C2560, RepairBuildingMsg.class, RepairBuildingMsgHandler.class),
REPAIROBJECT(0x782219CE, RepairMsg.class, null), //Repair Window Req/Ack, RepairObject item Req/Ack REPAIROBJECT(0x782219CE, RepairMsg.class, null), //Repair Window Req/Ack, RepairObject item Req/Ack
REQUESTCONTENTS(0xA786B0A2, LootWindowRequestMsg.class, null), // MoveObjectToContainer Window Request REQUESTCONTENTS(0xA786B0A2, LootWindowRequestMsg.class, null), // MoveObjectToContainer Window Request
@ -179,7 +179,7 @@ public enum Protocol {
REQUESTTOTRADE(0x4D84259B, TradeRequestMsg.class, null), // Trade Request REQUESTTOTRADE(0x4D84259B, TradeRequestMsg.class, null), // Trade Request
REQUESTTRADECANCEL(0xCB0C5735, RejectTradeRequestMsg.class, null), // Reject RequestToTrade REQUESTTRADECANCEL(0xCB0C5735, RejectTradeRequestMsg.class, null), // Reject RequestToTrade
REQUESTTRADEOK(0xFFD29841, AcceptTradeRequestMsg.class, null), // Accept Trade Request REQUESTTRADEOK(0xFFD29841, AcceptTradeRequestMsg.class, null), // Accept Trade Request
RESETAFTERDEATH(0xFDCBB98F,RespawnMsg.class, null), //Respawn Request/Response RESETAFTERDEATH(0xFDCBB98F, RespawnMsg.class, null), //Respawn Request/Response
ROTATEMSG(0x57F2088E, RotateObjectMsg.class, null), ROTATEMSG(0x57F2088E, RotateObjectMsg.class, null),
SAFEMODE(0x9CF3922A, SafeModeMsg.class, null), //Tell client they're in safe mode SAFEMODE(0x9CF3922A, SafeModeMsg.class, null), //Tell client they're in safe mode
SCALEOBJECT(0xE2B392D9, null, null), // Adjust scale of object SCALEOBJECT(0xE2B392D9, null, null), // Adjust scale of object
@ -210,7 +210,7 @@ public enum Protocol {
TAXCITY(0xCD41EAA6, TaxCityMsg.class, TaxCityMsgHandler.class), TAXCITY(0xCD41EAA6, TaxCityMsg.class, TaxCityMsgHandler.class),
TAXRESOURCES(0x4AD458AF, TaxResourcesMsg.class, TaxResourcesMsgHandler.class), TAXRESOURCES(0x4AD458AF, TaxResourcesMsg.class, TaxResourcesMsgHandler.class),
TELEPORT(0x23E726EA, TeleportToPointMsg.class, null), // Teleport to point TELEPORT(0x23E726EA, TeleportToPointMsg.class, null), // Teleport to point
TERRITORYCHANGE(0x6B388C8C,TerritoryChangeMessage.class, null), //Hey rich, look what I found? :) TERRITORYCHANGE(0x6B388C8C, TerritoryChangeMessage.class, null), //Hey rich, look what I found? :)
TOGGLESITSTAND(0x624F3C0F, ToggleSitStandMsg.class, null), //Toggle Sit/Stand TOGGLESITSTAND(0x624F3C0F, ToggleSitStandMsg.class, null), //Toggle Sit/Stand
TRADEADDGOLD(0x654ACB45, AddGoldToTradeWindowMsg.class, null), // Add Gold to Trade Window TRADEADDGOLD(0x654ACB45, AddGoldToTradeWindowMsg.class, null), // Add Gold to Trade Window
TRADEADDOBJECT(0x55D363E9, AddItemToTradeWindowMsg.class, null), // Add an Item to the Trade Window TRADEADDOBJECT(0x55D363E9, AddItemToTradeWindowMsg.class, null), // Add an Item to the Trade Window
@ -227,7 +227,7 @@ public enum Protocol {
TRANSFERITEMFROMVAULTTOINVENTORY(0x0119A64D, TransferItemFromVaultToInventoryMsg.class, null), // Transfer Item from Vault to Inventory TRANSFERITEMFROMVAULTTOINVENTORY(0x0119A64D, TransferItemFromVaultToInventoryMsg.class, null), // Transfer Item from Vault to Inventory
TRANSFERITEMTOBANK(0xD48C46FA, TransferItemFromInventoryToBankMsg.class, null), // Transfer Item from Inventory to Bank TRANSFERITEMTOBANK(0xD48C46FA, TransferItemFromInventoryToBankMsg.class, null), // Transfer Item from Inventory to Bank
UNEQUIP(0xC6BFB907, TransferItemFromEquipToInventoryMsg.class, null), // Transfer Item from Equip to Inventory UNEQUIP(0xC6BFB907, TransferItemFromEquipToInventoryMsg.class, null), // Transfer Item from Equip to Inventory
UNKNOWN(0x238C9259, UnknownMsg.class,null), UNKNOWN(0x238C9259, UnknownMsg.class, null),
UPDATECHARORMOB(0xB6D78961, null, null), UPDATECHARORMOB(0xB6D78961, null, null),
UPDATECLIENTALLIANCES(0xF3FEB5D4, null, GuildUnknownHandler.class), //AlliancesMsg UPDATECLIENTALLIANCES(0xF3FEB5D4, null, GuildUnknownHandler.class), //AlliancesMsg
UPDATECLIENTINVENTORIES(0xE66F533D, UpdateInventoryMsg.class, null), //Update player inventory UPDATECLIENTINVENTORIES(0xE66F533D, UpdateInventoryMsg.class, null), //Update player inventory
@ -247,14 +247,14 @@ public enum Protocol {
WEIGHTINVENTORY(0xF1B6A85C, LootWindowResponseMsg.class, null), // MoveObjectToContainer Window Response WEIGHTINVENTORY(0xF1B6A85C, LootWindowResponseMsg.class, null), // MoveObjectToContainer Window Response
WHOREQUEST(0xF431CCE9, WhoRequestMsg.class, null), // Request /who WHOREQUEST(0xF431CCE9, WhoRequestMsg.class, null), // Request /who
WHORESPONSE(0xD7C36568, WhoResponseMsg.class, null), // Response /who WHORESPONSE(0xD7C36568, WhoResponseMsg.class, null), // Response /who
REQUESTBALLLIST(0xE366FF64,RequestBallListMessage.class,RequestBallListHandler.class), REQUESTBALLLIST(0xE366FF64, RequestBallListMessage.class, RequestBallListHandler.class),
SENDBALLENTRY(0xAC2B5EDC,SendBallEntryMessage.class,SendBallEntryHandler.class), SENDBALLENTRY(0xAC2B5EDC, SendBallEntryMessage.class, SendBallEntryHandler.class),
UNKNOWN1(-263523523, Unknown1Msg.class,null), UNKNOWN1(-263523523, Unknown1Msg.class, null),
DROPGOLD(1461654160,DropGoldMsg.class,null); DROPGOLD(1461654160, DropGoldMsg.class, null);
public int opcode; public int opcode;
private Class message; private final Class message;
private Class handlerClass; private final Class handlerClass;
public Constructor constructor; public Constructor constructor;
public AbstractClientMsgHandler handler; public AbstractClientMsgHandler handler;
@ -286,7 +286,7 @@ public enum Protocol {
} }
} }
private static HashMap<Integer, Protocol> _protocolMsgByOpcode = new HashMap<>(); private static final HashMap<Integer, Protocol> _protocolMsgByOpcode = new HashMap<>();
public static Protocol getByOpcode(int opcode) { public static Protocol getByOpcode(int opcode) {
@ -302,7 +302,7 @@ public enum Protocol {
for (Protocol protocol : Protocol.values()) { for (Protocol protocol : Protocol.values()) {
if (_protocolMsgByOpcode.containsKey(protocol.opcode)){ if (_protocolMsgByOpcode.containsKey(protocol.opcode)) {
Logger.error("Duplicate opcodes for " + protocol.name() + " and " + _protocolMsgByOpcode.get(protocol.opcode).name()); Logger.error("Duplicate opcodes for " + protocol.name() + " and " + _protocolMsgByOpcode.get(protocol.opcode).name());
} }
_protocolMsgByOpcode.put(protocol.opcode, protocol); _protocolMsgByOpcode.put(protocol.opcode, protocol);
@ -310,21 +310,21 @@ public enum Protocol {
} }
public static int FindNextValidOpcode(ByteBufferReader reader){ public static int FindNextValidOpcode(ByteBufferReader reader) {
int startPos = reader.position(); int startPos = reader.position();
int bytesLeft = reader.remaining(); int bytesLeft = reader.remaining();
if (bytesLeft < 4) if (bytesLeft < 4)
return startPos; return startPos;
int nextPos = startPos; int nextPos = startPos;
for (int i = 1; i< bytesLeft; i++ ){ for (int i = 1; i < bytesLeft; i++) {
reader.position(nextPos); reader.position(nextPos);
if (reader.remaining() < 4) if (reader.remaining() < 4)
return reader.position(); return reader.position();
int newOpcode = reader.getInt(); int newOpcode = reader.getInt();
Protocol foundProtocol = Protocol.getByOpcode(newOpcode); Protocol foundProtocol = Protocol.getByOpcode(newOpcode);
if (foundProtocol.equals(Protocol.NONE)){ if (foundProtocol.equals(Protocol.NONE)) {
nextPos += 1; nextPos += 1;
continue; continue;
} }
@ -334,5 +334,5 @@ public static int FindNextValidOpcode(ByteBufferReader reader){
} }
return startPos; return startPos;
} }
} }

6
src/engine/net/client/handlers/ArcLoginNotifyMsgHandler.java

@ -1,5 +1,6 @@
package engine.net.client.handlers; package engine.net.client.handlers;
import engine.Enum;
import engine.Enum.DispatchChannel; import engine.Enum.DispatchChannel;
import engine.exception.MsgSendException; import engine.exception.MsgSendException;
import engine.gameManager.*; import engine.gameManager.*;
@ -125,10 +126,9 @@ public class ArcLoginNotifyMsgHandler extends AbstractClientMsgHandler {
} }
//Send current hotzone //Send current hotzone
Zone hotzone = ZoneManager.getHotZone();
if (hotzone != null) { if (ZoneManager.hotZone != null) {
HotzoneChangeMsg hcm = new HotzoneChangeMsg(hotzone.getObjectType().ordinal(), hotzone.getObjectUUID()); HotzoneChangeMsg hcm = new HotzoneChangeMsg(Enum.GameObjectType.Zone.ordinal(), ZoneManager.hotZone.getObjectUUID());
Dispatch dispatch = Dispatch.borrow(player, hcm); Dispatch dispatch = Dispatch.borrow(player, hcm);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
} }

2
src/engine/net/client/handlers/ArcMineChangeProductionMsgHandler.java

@ -7,7 +7,6 @@ import engine.net.DispatchMessage;
import engine.net.client.ClientConnection; import engine.net.client.ClientConnection;
import engine.net.client.msg.ArcMineChangeProductionMsg; import engine.net.client.msg.ArcMineChangeProductionMsg;
import engine.net.client.msg.ClientNetMsg; import engine.net.client.msg.ClientNetMsg;
import engine.net.client.msg.KeepAliveServerClientMsg;
import engine.objects.GuildStatusController; import engine.objects.GuildStatusController;
import engine.objects.Mine; import engine.objects.Mine;
import engine.objects.PlayerCharacter; import engine.objects.PlayerCharacter;
@ -60,7 +59,6 @@ public class ArcMineChangeProductionMsgHandler extends AbstractClientMsgHandler
//update resource //update resource
mine.changeProductionType(resource); mine.changeProductionType(resource);
Mine.setLastChange(System.currentTimeMillis());
Dispatch dispatch = Dispatch.borrow(playerCharacter, changeProductionMsg); Dispatch dispatch = Dispatch.borrow(playerCharacter, changeProductionMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return true; return true;

82
src/engine/net/client/handlers/CityDataHandler.java

@ -0,0 +1,82 @@
package engine.net.client.handlers;
import engine.Enum;
import engine.Enum.DispatchChannel;
import engine.exception.MsgSendException;
import engine.gameManager.SessionManager;
import engine.gameManager.ZoneManager;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.client.ClientConnection;
import engine.net.client.msg.*;
import engine.objects.City;
import engine.objects.PlayerCharacter;
import engine.session.Session;
/*
* @Author:
* @Summary: Processes application protocol message which displays
* the map interface. (Zones, Cities, Realms, Hot-zones)
*/
public class CityDataHandler extends AbstractClientMsgHandler {
public CityDataHandler() {
super(KeepAliveServerClientMsg.class);
}
@Override
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
boolean updateCities = false;
Session playerSession;
PlayerCharacter playerCharacter;
Dispatch dispatch;
playerCharacter = origin.getPlayerCharacter();
if (playerCharacter == null)
return true;
// Session is needed as param for worldObjectMsg.
playerSession = SessionManager.getSession(playerCharacter);
if (playerSession == null)
return true;
// No reason to serialize cities everytime map is
// opened. Wait until something has changed.
// This does not work for mines.
if (playerCharacter.getTimeStamp("cityUpdate") <= City.lastCityUpdate) {
playerCharacter.setTimeStamp("cityUpdate", System.currentTimeMillis());
updateCities = true;
}
CityDataMsg cityDataMsg = new CityDataMsg(SessionManager.getSession(playerCharacter), false);
cityDataMsg.updateMines(true);
cityDataMsg.updateCities(updateCities);
dispatch = Dispatch.borrow(playerCharacter, cityDataMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
// If the hotZone has changed then update the client's map accordingly.
if (playerCharacter.getTimeStamp("hotzoneupdate") <= ZoneManager.hotZoneLastUpdate.toEpochMilli() && ZoneManager.hotZone != null) {
HotzoneChangeMsg hotzoneChangeMsg = new HotzoneChangeMsg(Enum.GameObjectType.Zone.ordinal(), ZoneManager.hotZone.getObjectUUID());
dispatch = Dispatch.borrow(playerCharacter, hotzoneChangeMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
playerCharacter.setTimeStamp("hotzoneupdate", System.currentTimeMillis() - 100);
}
// Serialize the realms for this map
WorldRealmMsg worldRealmMsg = new WorldRealmMsg();
dispatch = Dispatch.borrow(playerCharacter, worldRealmMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
return true;
}
}

19
src/engine/net/client/handlers/GuildCreationFinalizeHandler.java

@ -54,6 +54,7 @@ public class GuildCreationFinalizeHandler extends AbstractClientMsgHandler {
GuildCreationFinalizeMsg msg; GuildCreationFinalizeMsg msg;
Enum.GuildType charterType; Enum.GuildType charterType;
Guild newGuild; Guild newGuild;
Guild playerGuild;
ItemBase itemBase; ItemBase itemBase;
Item charter; Item charter;
Dispatch dispatch; Dispatch dispatch;
@ -61,9 +62,9 @@ public class GuildCreationFinalizeHandler extends AbstractClientMsgHandler {
msg = (GuildCreationFinalizeMsg) baseMsg; msg = (GuildCreationFinalizeMsg) baseMsg;
player = SessionManager.getPlayerCharacter(origin); player = SessionManager.getPlayerCharacter(origin);
playerGuild = player.getGuild();
boolean isGuildLeader = GuildStatusController.isGuildLeader(player.getGuildStatus()); if (playerGuild.isEmptyGuild() == false && player.getGuild().getGuildLeaderUUID() == player.getObjectUUID()) {
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) || player.getGuild() != null && player.getGuild().getGuildLeaderUUID() == player.getObjectUUID()) {
ErrorPopupMsg.sendErrorPopup(player, GuildManager.MUST_LEAVE_GUILD); ErrorPopupMsg.sendErrorPopup(player, GuildManager.MUST_LEAVE_GUILD);
return true; return true;
} }
@ -77,30 +78,22 @@ public class GuildCreationFinalizeHandler extends AbstractClientMsgHandler {
return true; return true;
} }
itemBase = charter.getItemBase(); itemBase = charter.getItemBase();
// Item must be a valid charterType (type 10 in db) // Item must be a valid charterType (type 10 in db)
if (itemBase == null || (itemBase.getType().equals(ItemType.GUILDCHARTER) == false)) { if (itemBase == null || (itemBase.getType().equals(ItemType.GUILDCHARTER) == false)) {
ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND); ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND);
return true; return true;
} }
charterType = Enum.GuildType.getGuildTypeFromCharter(itemBase);
charterType = Enum.GuildType.getGuildTypeFromCharter(itemBase);
if (charterType == null){ if (charterType == null){
ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND); ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND);
return true; return true;
} }
//Validate Guild Tags //Validate Guild Tags
if (!msg.getGuildTag().isValid()) { if (!msg.getGuildTag().isValid()) {
@ -110,11 +103,9 @@ public class GuildCreationFinalizeHandler extends AbstractClientMsgHandler {
// Validation passes. Leave current guild and create new one. // Validation passes. Leave current guild and create new one.
if (player.getGuild() != null && player.getGuild().getObjectUUID() != 0) if (player.getGuild() != null && player.getGuild().isEmptyGuild() == false)
player.getGuild().removePlayer(player,GuildHistoryType.LEAVE); player.getGuild().removePlayer(player,GuildHistoryType.LEAVE);
int leadershipType = ((msg.getICVoteFlag() << 1) | msg.getMemberVoteFlag()); int leadershipType = ((msg.getICVoteFlag() << 1) | msg.getMemberVoteFlag());
newGuild = new Guild( msg.getName(),null, charterType.ordinal(), newGuild = new Guild( msg.getName(),null, charterType.ordinal(),

20
src/engine/net/client/handlers/PlaceAssetMsgHandler.java

@ -436,7 +436,9 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild())) if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
continue; continue;
if (building.getRank() < 0) {
continue;
}
if (building.getGuild().equals(serverCity.getGuild())) if (building.getGuild().equals(serverCity.getGuild()))
defenderBuildings.add(building); defenderBuildings.add(building);
@ -982,11 +984,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
return false; return false;
} }
RealmType realmType = RealmType.getRealmTypeByUUID(serverRealm.getRealmID()); if (serverRealm == null || serverRealm.getCanPlaceCities() == false) {
if (
(realmType.equals(RealmType.MAELSTROM)) ||
(realmType.equals(RealmType.OBLIVION))) {
PlaceAssetMsg.sendPlaceAssetError(origin, 57, playerCharacter.getName()); // No building may be placed within this territory PlaceAssetMsg.sendPlaceAssetError(origin, 57, playerCharacter.getName()); // No building may be placed within this territory
return false; return false;
} }
@ -1238,8 +1236,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
private static boolean validateBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo placementInfo) { private static boolean validateBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo placementInfo) {
RealmType currentRealm;
if (serverZone.isPlayerCity() == false) { if (serverZone.isPlayerCity() == false) {
PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName()); PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName());
return false; return false;
@ -1293,11 +1289,11 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
return false; return false;
} }
currentRealm = RealmType.getRealmTypeByUUID(RealmMap.getRealmIDAtLocation(player.getLoc())); Realm serverRealm = RealmMap.getRealmAtLocation(player.getLoc());
// Cannot place buildings on seafloor or other restricted realms
if ( if (serverRealm == null || serverRealm.getCanPlaceCities() == false) {
(currentRealm.equals(RealmType.MAELSTROM)) ||
(currentRealm.equals(RealmType.OBLIVION))) {
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName()); // No building may be placed within this territory PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName()); // No building may be placed within this territory
return false; return false;
} }

2
src/engine/net/client/handlers/RequestEnterWorldHandler.java

@ -99,7 +99,7 @@ public class RequestEnterWorldHandler extends AbstractClientMsgHandler {
} }
// Object Data // Object Data
WorldObjectMsg wom = new WorldObjectMsg(session, true); CityDataMsg wom = new CityDataMsg(session, true);
dispatch = Dispatch.borrow(player, wom); dispatch = Dispatch.borrow(player, wom);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);

274
src/engine/net/client/msg/CityDataMsg.java

@ -0,0 +1,274 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.net.client.msg;
import engine.Enum;
import engine.gameManager.DbManager;
import engine.net.AbstractConnection;
import engine.net.ByteBufferReader;
import engine.net.ByteBufferWriter;
import engine.net.Network;
import engine.net.client.Protocol;
import engine.objects.AbstractGameObject;
import engine.objects.City;
import engine.objects.Mine;
import engine.objects.Runegate;
import engine.session.Session;
import org.pmw.tinylog.Logger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
public class CityDataMsg extends ClientNetMsg {
private Session s;
private final boolean forEnterWorld;
private static ByteBuffer cachedEnterWorld;
private static long cachedExpireTime;
public static final long wdComp = 0xFF00FF0000000003L;
private static final byte ver = 1;
private boolean updateCities = false;
private boolean updateRunegates = false;
private boolean updateMines = false;
/**
* This is the general purpose constructor.
*
* @param s Session
* @param forEnterWorld boolean flag
*/
public CityDataMsg(Session s, boolean forEnterWorld) {
super(Protocol.CITYDATA);
this.s = s;
this.forEnterWorld = forEnterWorld;
}
public CityDataMsg(boolean updateCities, boolean updateRunegates, boolean updateMines) {
super(Protocol.CITYDATA);
this.s = null;
this.forEnterWorld = false;
this.updateCities = updateCities;
this.updateRunegates = updateRunegates;
this.updateMines = updateMines;
}
/**
* This constructor is used by NetMsgFactory. It attempts to deserialize the
* ByteBuffer into a message. If a BufferUnderflow occurs (based on reading
* past the limit) then this constructor Throws that Exception to the
* caller.
*/
public CityDataMsg(AbstractConnection origin, ByteBufferReader reader) {
super(Protocol.CITYDATA, origin, reader);
this.forEnterWorld = false;
}
@Override
protected int getPowerOfTwoBufferSize() {
return (18); // 2^14 == 16384
}
/**
* Serializes the subclass specific items to the supplied NetMsgWriter.
*/
@Override
protected void _serialize(ByteBufferWriter writer) {
if (this.forEnterWorld)
serializeForEnterWorld(writer);
else
serializeForMapUpdate(writer);
}
/**
* Specific use serializer
*
* @param writer
*/
private void serializeForMapUpdate(ByteBufferWriter writer) {
//Handle City updates
if (this.updateCities) {
writer.put((byte) 0);
ArrayList<City> cityList = new ArrayList<>();
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
if (map != null) {
for (AbstractGameObject ago : map.values())
if (ago.getObjectType().equals(Enum.GameObjectType.City))
cityList.add((City) ago);
writer.putInt(cityList.size());
for (City city : cityList) {
City.serializeForClientMsg(city, writer);
}
} else {
Logger.error("missing city map");
writer.putInt(0);
}
} else
writer.put((byte) 1);
//Handle Runegate updates
if (this.updateRunegates) {
writer.put((byte) 0);
writer.putInt(Runegate._runegates.values().size());
for (Runegate runegate : Runegate._runegates.values()) {
runegate._serializeForEnterWorld(writer);
}
} else
writer.put((byte) 1);
//Handle Mine updates
try {
if (this.updateMines) {
ArrayList<Mine> mineList = new ArrayList<>();
for (Mine toAdd : Mine.mineMap.keySet()) {
mineList.add(toAdd);
}
writer.putInt(mineList.size());
for (Mine mine : mineList)
Mine.serializeForClientMsg(mine, writer);
} else
writer.putInt(0);
} catch (Exception e) {
Logger.error(e);
}
writer.put((byte) 0); // PAD
}
/**
* Specific use serializer
*
* @param writer
*/
private void serializeForEnterWorld(ByteBufferWriter writer) {
if (s == null || s.getPlayerCharacter() == null)
return;
long startT = System.currentTimeMillis();
if (cachedEnterWorld == null) {
// Never before been cached, so init stuff
cachedEnterWorld = Network.byteBufferPool.getBuffer(19);
cachedExpireTime = 0L;
}
//Check to see if its time to renew cache.
if (cachedExpireTime < System.currentTimeMillis()) {
synchronized (cachedEnterWorld) {
CityDataMsg.attemptSerializeForEnterWorld(cachedEnterWorld);
}
cachedExpireTime = startT + 60000;
}
writer.putBB(cachedEnterWorld);
}
private static void attemptSerializeForEnterWorld(ByteBuffer bb) {
bb.clear();
ByteBufferWriter temp = new ByteBufferWriter(bb);
temp.put((byte) 0); // PAD
ArrayList<City> cityList = new ArrayList<>();
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
for (AbstractGameObject ago : map.values())
if (ago.getObjectType().equals(Enum.GameObjectType.City))
cityList.add((City) ago);
temp.putInt(cityList.size());
for (City city : cityList)
City.serializeForClientMsg(city, temp);
temp.put((byte) 0); // PAD
// Serialize runegates
temp.putInt(Runegate._runegates.values().size());
for (Runegate runegate : Runegate._runegates.values()) {
runegate._serializeForEnterWorld(temp);
}
ArrayList<Mine> mineList = new ArrayList<>();
for (Mine toAdd : Mine.mineMap.keySet()) {
mineList.add(toAdd);
}
temp.putInt(mineList.size());
for (Mine mine : mineList)
Mine.serializeForClientMsg(mine, temp);
temp.put((byte) 0); // PAD
}
/**
* Deserializes the subclass specific items from the supplied NetMsgReader.
*/
@Override
protected void _deserialize(ByteBufferReader reader) {
// Client only sends 11 bytes.
byte type = reader.get();
if (type == 1) {
reader.get();
reader.get();
reader.getInt();
} else {
reader.get();
reader.getInt();
reader.get();
reader.getInt();
}
}
/**
* @return the s
*/
public Session getS() {
return s;
}
/**
* @return the forEnterWorld
*/
public boolean isForEnterWorld() {
return forEnterWorld;
}
public void updateCities(boolean value) {
this.updateCities = value;
}
public void updateRunegates(boolean value) {
this.updateRunegates = value;
}
public void updateMines(boolean value) {
this.updateMines = value;
}
}

16
src/engine/net/client/msg/HotzoneChangeMsg.java

@ -10,17 +10,24 @@
package engine.net.client.msg; package engine.net.client.msg;
import engine.math.FastMath; import engine.gameManager.ConfigManager;
import engine.gameManager.ZoneManager;
import engine.net.AbstractConnection; import engine.net.AbstractConnection;
import engine.net.ByteBufferReader; import engine.net.ByteBufferReader;
import engine.net.ByteBufferWriter; import engine.net.ByteBufferWriter;
import engine.net.client.Protocol; import engine.net.client.Protocol;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
public class HotzoneChangeMsg extends ClientNetMsg { public class HotzoneChangeMsg extends ClientNetMsg {
private int zoneType; private int zoneType;
private int zoneID; private int zoneID;
private int secondsRemaining;
/** /**
* This is the general purpose constructor. * This is the general purpose constructor.
@ -29,6 +36,11 @@ public class HotzoneChangeMsg extends ClientNetMsg {
super(Protocol.ARCHOTZONECHANGE); super(Protocol.ARCHOTZONECHANGE);
this.zoneType = zoneType; this.zoneType = zoneType;
this.zoneID = zoneID; this.zoneID = zoneID;
int hotZoneDuration = Integer.parseInt(ConfigManager.MB_HOTZONE_DURATION.getValue());
Instant currentInstant = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
secondsRemaining = (int) Duration.between(currentInstant, ZoneManager.hotZoneLastUpdate.plusSeconds(hotZoneDuration * 3600)).getSeconds();
} }
/** /**
@ -49,7 +61,7 @@ public class HotzoneChangeMsg extends ClientNetMsg {
protected void _serialize(ByteBufferWriter writer) { protected void _serialize(ByteBufferWriter writer) {
writer.putInt(this.zoneType); writer.putInt(this.zoneType);
writer.putInt(this.zoneID); writer.putInt(this.zoneID);
writer.putInt(FastMath.secondsUntilNextHour()); writer.putInt(secondsRemaining);
} }
/** /**

2
src/engine/net/client/msg/WorldDataMsg.java

@ -80,7 +80,7 @@ public class WorldDataMsg extends ClientNetMsg {
writer.putInt(getTotalMapSize(root) + 1); writer.putInt(getTotalMapSize(root) + 1);
Zone.serializeForClientMsg(root,writer); Zone.serializeForClientMsg(root,writer);
Zone hotzone = ZoneManager.getHotZone(); Zone hotzone = ZoneManager.hotZone;;
if (hotzone == null) if (hotzone == null)
writer.putLong(0L); writer.putLong(0L);

282
src/engine/net/client/msg/WorldObjectMsg.java

@ -1,282 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.net.client.msg;
import engine.Enum;
import engine.Enum.RunegateType;
import engine.gameManager.DbManager;
import engine.net.AbstractConnection;
import engine.net.ByteBufferReader;
import engine.net.ByteBufferWriter;
import engine.net.Network;
import engine.net.client.Protocol;
import engine.objects.AbstractGameObject;
import engine.objects.City;
import engine.objects.Mine;
import engine.objects.Runegate;
import engine.session.Session;
import org.pmw.tinylog.Logger;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
public class WorldObjectMsg extends ClientNetMsg {
private Session s;
private boolean forEnterWorld;
private static ByteBuffer cachedEnterWorld;
private static long cachedExpireTime;
public static final long wdComp = 0xFF00FF0000000003L;
private static byte ver = 1;
private boolean updateCities = false;
private boolean updateRunegates = false;
private boolean updateMines = false;
/**
* This is the general purpose constructor.
*
* @param s
* Session
* @param forEnterWorld
* boolean flag
*/
public WorldObjectMsg(Session s, boolean forEnterWorld) {
super(Protocol.CITYDATA);
this.s = s;
this.forEnterWorld = forEnterWorld;
}
public WorldObjectMsg(boolean updateCities, boolean updateRunegates, boolean updateMines) {
super(Protocol.CITYDATA);
this.s = null;
this.forEnterWorld = false;
this.updateCities = updateCities;
this.updateRunegates = updateRunegates;
this.updateMines = updateMines;
}
/**
* This constructor is used by NetMsgFactory. It attempts to deserialize the
* ByteBuffer into a message. If a BufferUnderflow occurs (based on reading
* past the limit) then this constructor Throws that Exception to the
* caller.
*/
public WorldObjectMsg(AbstractConnection origin, ByteBufferReader reader)
{
super(Protocol.CITYDATA, origin, reader);
this.forEnterWorld = false;
}
@Override
protected int getPowerOfTwoBufferSize() {
return (18); // 2^14 == 16384
}
/**
* Serializes the subclass specific items to the supplied NetMsgWriter.
*/
@Override
protected void _serialize(ByteBufferWriter writer) {
if (this.forEnterWorld)
serializeForEnterWorld(writer);
else
serializeForMapUpdate(writer);
}
/**
* Specific use serializer
*
* @param writer
*/
private void serializeForMapUpdate(ByteBufferWriter writer) {
//Handle City updates
if (this.updateCities) {
writer.put((byte) 0);
ArrayList<City> cityList = new ArrayList<>();
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
if (map != null) {
for (AbstractGameObject ago : map.values())
if (ago.getObjectType().equals(Enum.GameObjectType.City))
cityList.add((City)ago);
writer.putInt(cityList.size());
for (City city: cityList){
City.serializeForClientMsg(city, writer);
}
} else {
Logger.error("missing city map");
writer.putInt(0);
}
} else
writer.put((byte) 1);
//Handle Runegate updates
if (this.updateRunegates) {
writer.put((byte) 0);
writer.putInt(RunegateType.values().length);
for(RunegateType gateType : engine.Enum.RunegateType.values()) {
Runegate.getRunegates()[gateType.ordinal()]._serializeForEnterWorld(writer);
}
} else
writer.put((byte) 1);
//Handle Mine updates
try{
if (this.updateMines) {
ArrayList<Mine> mineList = new ArrayList<>();
for (Mine toAdd: Mine.mineMap.keySet()){
mineList.add(toAdd);
}
writer.putInt(mineList.size());
for (Mine mine: mineList)
Mine.serializeForClientMsg(mine, writer);
} else
writer.putInt(0);
}catch(Exception e){
Logger.error(e);
}
writer.put((byte) 0); // PAD
}
/**
* Specific use serializer
*
* @param writer
*/
private void serializeForEnterWorld(ByteBufferWriter writer) {
if (s == null || s.getPlayerCharacter() == null)
return;
long startT = System.currentTimeMillis();
if (cachedEnterWorld == null) {
// Never before been cached, so init stuff
cachedEnterWorld = Network.byteBufferPool.getBuffer(19);
cachedExpireTime = 0L;
}
//Check to see if its time to renew cache.
if (cachedExpireTime < System.currentTimeMillis()) {
synchronized (cachedEnterWorld) {
WorldObjectMsg.attemptSerializeForEnterWorld(cachedEnterWorld);
}
cachedExpireTime = startT + 60000;
}
writer.putBB(cachedEnterWorld);
}
private static void attemptSerializeForEnterWorld(ByteBuffer bb) {
bb.clear();
ByteBufferWriter temp = new ByteBufferWriter(bb);
temp.put((byte) 0); // PAD
ArrayList<City> cityList = new ArrayList<>();
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
for (AbstractGameObject ago : map.values())
if (ago.getObjectType().equals(Enum.GameObjectType.City))
cityList.add((City)ago);
temp.putInt(cityList.size());
for (City city: cityList)
City.serializeForClientMsg(city, temp);
temp.put((byte) 0); // PAD
// Serialize runegates
temp.putInt(RunegateType.values().length);
for(RunegateType gateType : engine.Enum.RunegateType.values()) {
Runegate.getRunegates()[gateType.ordinal()]._serializeForEnterWorld(temp);
}
ArrayList<Mine> mineList = new ArrayList<>();
for (Mine toAdd : Mine.mineMap.keySet()){
mineList.add(toAdd);
}
temp.putInt(mineList.size());
for (Mine mine: mineList)
Mine.serializeForClientMsg(mine, temp);
temp.put((byte) 0); // PAD
}
/**
* Deserializes the subclass specific items from the supplied NetMsgReader.
*/
@Override
protected void _deserialize(ByteBufferReader reader)
{
// Client only sends 11 bytes.
byte type = reader.get();
if (type == 1){
reader.get();
reader.get();
reader.getInt();
}else{
reader.get();
reader.getInt();
reader.get();
reader.getInt();
}
}
/**
* @return the s
*/
public Session getS() {
return s;
}
/**
* @return the forEnterWorld
*/
public boolean isForEnterWorld() {
return forEnterWorld;
}
public void updateCities(boolean value) {
this.updateCities = value;
}
public void updateRunegates(boolean value) {
this.updateRunegates = value;
}
public void updateMines(boolean value) {
this.updateMines = value;
}
}

18
src/engine/net/client/msg/WorldRealmMsg.java

@ -21,7 +21,6 @@
package engine.net.client.msg; package engine.net.client.msg;
import engine.Enum.RealmType;
import engine.net.AbstractConnection; import engine.net.AbstractConnection;
import engine.net.ByteBufferReader; import engine.net.ByteBufferReader;
import engine.net.ByteBufferWriter; import engine.net.ByteBufferWriter;
@ -67,23 +66,12 @@ public class WorldRealmMsg extends ClientNetMsg {
Realm serverRealm; Realm serverRealm;
realmCount = RealmType.values().length - 1; realmCount = Realm._realms.size();
// Realm count without seafloor
writer.putInt(realmCount); writer.putInt(realmCount);
for (RealmType realmType : RealmType.values()) { for (Realm realm : Realm._realms.values())
realm.serializeForClientMsg(writer);
realmID = realmType.getRealmID();
// Don't serialize seafloor
if (realmID == 0)
continue;
serverRealm = Realm.getRealm(realmID);
serverRealm.serializeForClientMsg(writer);
}
writer.putInt(0x0); writer.putInt(0x0);
writer.putInt(3000000); writer.putInt(3000000);

2
src/engine/objects/City.java

@ -872,7 +872,7 @@ public class City extends AbstractWorldObject {
if (playerObject == null) if (playerObject == null)
continue; continue;
if (!this.isLocationOnCityZone(playerObject.getLoc())) if (!this.isLocationWithinSiegeBounds(playerObject.getLoc()))
continue; continue;
player = (PlayerCharacter) playerObject; player = (PlayerCharacter) playerObject;

52
src/engine/objects/Experience.java

@ -9,10 +9,13 @@
package engine.objects; package engine.objects;
import engine.Enum;
import engine.Enum.TargetColor; import engine.Enum.TargetColor;
import engine.gameManager.ConfigManager;
import engine.gameManager.ZoneManager; import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import engine.server.world.WorldServer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.TreeMap; import java.util.TreeMap;
@ -330,12 +333,7 @@ public class Experience {
if (killer == null || mob == null) if (killer == null || mob == null)
return; return;
double xp = 0.0; double grantedExperience = 0.0;
//Get the xp modifier for the world
float xpMod = MBServerStatics.EXP_RATE_MOD;
if (g != null) { // Do group EXP stuff if (g != null) { // Do group EXP stuff
@ -372,18 +370,18 @@ public class Experience {
} }
// Process every player in the group getting XP // Process every player in the group getting XP
for (PlayerCharacter pc : giveEXPTo) { for (PlayerCharacter playerCharacter : giveEXPTo) {
if (pc.getLevel() >= MBServerStatics.LEVELCAP) if (playerCharacter.getLevel() >= MBServerStatics.LEVELCAP)
continue; continue;
// Sets Max XP with server exp mod taken into account. // Sets Max XP with server exp mod taken into account.
xp = (double) xpMod * maxXPPerKill(pc.getLevel()); grantedExperience = (double) Float.parseFloat(ConfigManager.MB_NORMAL_EXP_RATE.getValue()) * maxXPPerKill(playerCharacter.getLevel());
// Adjust XP for Mob Level // Adjust XP for Mob Level
xp *= getConMod(pc, mob); grantedExperience *= getConMod(playerCharacter, mob);
// Process XP for this member // Process XP for this member
penalty = getGroupMemberPenalty(leadership, pc, giveEXPTo, penalty = getGroupMemberPenalty(leadership, playerCharacter, giveEXPTo,
highestLevel); highestLevel);
// Leadership Penalty Reduction // Leadership Penalty Reduction
@ -391,27 +389,27 @@ public class Experience {
penalty -= ((leadership) * 0.01) * penalty; penalty -= ((leadership) * 0.01) * penalty;
// Modify for hotzone // Modify for hotzone
if (xp != 0) if (grantedExperience != 0)
if (ZoneManager.inHotZone(mob.getLoc())) if (ZoneManager.inHotZone(mob.getLoc()))
xp *= MBServerStatics.HOT_EXP_RATE_MOD; grantedExperience *= Float.parseFloat(ConfigManager.MB_HOTZONE_EXP_RATE.getValue());
// Check for 0 XP due to white mob, otherwise subtract penalty // Check for 0 XP due to white mob, otherwise subtract penalty
// xp // xp
if (xp == 0) { if (grantedExperience == 0) {
xp = 1; grantedExperience = 1;
} else { } else {
xp -= (penalty * 0.01) * xp; grantedExperience -= (penalty * 0.01) * grantedExperience;
// Errant Penalty Calculation // Errant Penalty Calculation
if (pc.getGuild().isEmptyGuild()) if (playerCharacter.getGuild().isEmptyGuild())
xp *= 0.6; grantedExperience *= 0.6;
} }
if (xp == 0) if (grantedExperience == 0)
xp = 1; grantedExperience = 1;
// Grant the player the EXP // Grant the player the EXP
pc.grantXP((int) Math.floor(xp)); playerCharacter.grantXP((int) Math.floor(grantedExperience));
} }
} else { // Give EXP to a single character } else { // Give EXP to a single character
@ -422,20 +420,20 @@ public class Experience {
return; return;
// Get XP and adjust for Mob Level with world xp modifier taken into account // Get XP and adjust for Mob Level with world xp modifier taken into account
xp = (double) xpMod * maxXPPerKill(killer.getLevel()); grantedExperience = (double) Float.parseFloat(ConfigManager.MB_NORMAL_EXP_RATE.getValue()) * maxXPPerKill(killer.getLevel());
xp *= getConMod(killer, mob); grantedExperience *= getConMod(killer, mob);
// Modify for hotzone // Modify for hotzone
if (ZoneManager.inHotZone(mob.getLoc())) if (ZoneManager.inHotZone(mob.getLoc()))
xp *= MBServerStatics.HOT_EXP_RATE_MOD; grantedExperience *= Float.parseFloat(ConfigManager.MB_HOTZONE_EXP_RATE.getValue());
// Errant penalty // Errant penalty
if (xp != 1) if (grantedExperience != 1)
if (killer.getGuild().isEmptyGuild()) if (killer.getGuild().isEmptyGuild())
xp *= .6; grantedExperience *= .6;
// Grant XP // Grant XP
killer.grantXP((int) Math.floor(xp)); killer.grantXP((int) Math.floor(grantedExperience));
} }
} }
} }

17
src/engine/objects/ItemFactory.java

@ -13,10 +13,7 @@ import engine.Enum;
import engine.Enum.ItemContainerType; import engine.Enum.ItemContainerType;
import engine.Enum.ItemType; import engine.Enum.ItemType;
import engine.Enum.OwnerType; import engine.Enum.OwnerType;
import engine.gameManager.BuildingManager; import engine.gameManager.*;
import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.gameManager.PowersManager;
import engine.net.ItemProductionManager; import engine.net.ItemProductionManager;
import engine.net.ItemQueue; import engine.net.ItemQueue;
import engine.net.client.ClientConnection; import engine.net.client.ClientConnection;
@ -202,7 +199,7 @@ public class ItemFactory {
// is used to determin whether or not an object has // is used to determin whether or not an object has
// compelted rolling. The game object exists previously // compelted rolling. The game object exists previously
// to this, not when 'compelte' is pressed. // to this, not when 'compelte' is pressed.
long upgradeTime = System.currentTimeMillis() + (long)(time * MBServerStatics.PRODUCTION_TIME_MULTIPLIER) ; long upgradeTime = System.currentTimeMillis() + (long)(time * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue()));
DateTime dateTime = new DateTime(); DateTime dateTime = new DateTime();
dateTime = dateTime.withMillis(upgradeTime); dateTime = dateTime.withMillis(upgradeTime);
@ -220,7 +217,7 @@ public class ItemFactory {
pi.setAmount(itemsToRoll); pi.setAmount(itemsToRoll);
pi.setRandom(false); pi.setRandom(false);
ItemQueue produced = ItemQueue.borrow(pi, (long) (time * MBServerStatics.PRODUCTION_TIME_MULTIPLIER)); ItemQueue produced = ItemQueue.borrow(pi, (long) (time * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue())));
ItemProductionManager.send(produced); ItemProductionManager.send(produced);
return ml; return ml;
@ -620,7 +617,7 @@ public class ItemFactory {
// is used to determin whether or not an object has // is used to determin whether or not an object has
// compelted rolling. The game object exists previously // compelted rolling. The game object exists previously
// to this, not when 'compelte' is pressed. // to this, not when 'compelte' is pressed.
long upgradeTime = System.currentTimeMillis() + (long)(time * MBServerStatics.PRODUCTION_TIME_MULTIPLIER) ; long upgradeTime = System.currentTimeMillis() + (long)(time * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue())) ;
DateTime dateTime = new DateTime(); DateTime dateTime = new DateTime();
dateTime = dateTime.withMillis(upgradeTime); dateTime = dateTime.withMillis(upgradeTime);
@ -637,7 +634,7 @@ public class ItemFactory {
pi.setProducedItemID(ml.getObjectUUID()); pi.setProducedItemID(ml.getObjectUUID());
pi.setAmount(itemsToRoll); pi.setAmount(itemsToRoll);
ItemQueue produced = ItemQueue.borrow(pi, (long) (time * MBServerStatics.PRODUCTION_TIME_MULTIPLIER)); ItemQueue produced = ItemQueue.borrow(pi, (long) (time * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue())));
ItemProductionManager.send(produced); ItemProductionManager.send(produced);
}catch(Exception e){ }catch(Exception e){
Logger.error(e); Logger.error(e);
@ -906,7 +903,7 @@ public class ItemFactory {
// is used to determin whether or not an object has // is used to determin whether or not an object has
// compelted rolling. The game object exists previously // compelted rolling. The game object exists previously
// to this, not when 'compelte' is pressed. // to this, not when 'compelte' is pressed.
long upgradeTime = System.currentTimeMillis() + (long)(time * MBServerStatics.PRODUCTION_TIME_MULTIPLIER) ; long upgradeTime = System.currentTimeMillis() + (long)(time * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue())) ;
DateTime dateTime = new DateTime(); DateTime dateTime = new DateTime();
dateTime = dateTime.withMillis(upgradeTime); dateTime = dateTime.withMillis(upgradeTime);
@ -920,7 +917,7 @@ public class ItemFactory {
ProducedItem pi = new ProducedItem(toRoll.getObjectUUID(),vendor.getObjectUUID(),toRoll.getItemBaseID(),dateTime,true,prefix, suffix, toRoll.getCustomName(),playerID); ProducedItem pi = new ProducedItem(toRoll.getObjectUUID(),vendor.getObjectUUID(),toRoll.getItemBaseID(),dateTime,true,prefix, suffix, toRoll.getCustomName(),playerID);
pi.setProducedItemID(toRoll.getObjectUUID()); pi.setProducedItemID(toRoll.getObjectUUID());
pi.setAmount(itemsToRoll); pi.setAmount(itemsToRoll);
ItemQueue produced = ItemQueue.borrow(pi, (long) (time * MBServerStatics.PRODUCTION_TIME_MULTIPLIER)); ItemQueue produced = ItemQueue.borrow(pi, (long) (time * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue())));
ItemProductionManager.send(produced); ItemProductionManager.send(produced);
return toRoll; return toRoll;
} }

5
src/engine/objects/LootTable.java

@ -9,12 +9,15 @@
package engine.objects; package engine.objects;
import engine.Enum;
import engine.Enum.ItemContainerType; import engine.Enum.ItemContainerType;
import engine.Enum.ItemType; import engine.Enum.ItemType;
import engine.Enum.OwnerType; import engine.Enum.OwnerType;
import engine.gameManager.ConfigManager;
import engine.gameManager.DbManager; import engine.gameManager.DbManager;
import engine.gameManager.ZoneManager; import engine.gameManager.ZoneManager;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.util.ArrayList; import java.util.ArrayList;
@ -208,7 +211,7 @@ public class LootTable {
float chance = mlb.getChance() *.01f; float chance = mlb.getChance() *.01f;
chance *= MBServerStatics.DROP_RATE_MOD; chance *= Float.parseFloat(ConfigManager.MB_NORMAL_DROP_RATE.getValue());
calculatedLootTable = mlb.getLootTableID(); calculatedLootTable = mlb.getLootTableID();

266
src/engine/objects/Mine.java

@ -20,7 +20,10 @@ package engine.objects;
import engine.Enum; import engine.Enum;
import engine.InterestManagement.WorldGrid; import engine.InterestManagement.WorldGrid;
import engine.gameManager.*; import engine.gameManager.BuildingManager;
import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.gameManager.ZoneManager;
import engine.net.ByteBufferWriter; import engine.net.ByteBufferWriter;
import engine.net.client.msg.ErrorPopupMsg; import engine.net.client.msg.ErrorPopupMsg;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
@ -33,38 +36,34 @@ import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static engine.gameManager.DbManager.*; import static engine.gameManager.DbManager.MineQueries;
import static engine.gameManager.DbManager.getObject;
import static engine.math.FastMath.sqr; import static engine.math.FastMath.sqr;
public class Mine extends AbstractGameObject { public class Mine extends AbstractGameObject {
private String zoneName; public static ConcurrentHashMap<Mine, Integer> mineMap = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
private Resource production; public static ConcurrentHashMap<Integer, Mine> towerMap = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
public boolean isActive = false; public boolean isActive = false;
private float latitude;
private float longitude;
private float altitude;
private Guild owningGuild;
public PlayerCharacter lastClaimer; public PlayerCharacter lastClaimer;
public boolean wasClaimed = false; public boolean wasClaimed = false;
private int flags;
private int buildingID;
private Zone parentZone;
private MineProduction mineType;
//flags 1: never been claimed (make active).
// Not persisted to DB // Not persisted to DB
public String guildName; public String guildName;
public GuildTag guildTag; public GuildTag guildTag;
public String nationName; public String nationName;
public GuildTag nationTag; public GuildTag nationTag;
public static ConcurrentHashMap<Mine, Integer> mineMap = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private final String zoneName;
public static ConcurrentHashMap<Integer, Mine> towerMap = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); private Resource production;
private final float latitude;
private final float longitude;
private static long lastChange = System.currentTimeMillis(); //flags 1: never been claimed (make active).
private final float altitude;
private Guild owningGuild;
private int flags;
private int buildingID;
private final Zone parentZone;
private MineProduction mineType;
/** /**
* ResultSet Constructor * ResultSet Constructor
@ -139,6 +138,7 @@ public class Mine extends AbstractGameObject {
} }
} }
public static void SendMineAttackMessage(Building mine) { public static void SendMineAttackMessage(Building mine) {
if (mine.getBlueprint() == null) if (mine.getBlueprint() == null)
@ -186,90 +186,10 @@ public class Mine extends AbstractGameObject {
* Getters * Getters
*/ */
public boolean changeProductionType(Resource resource) {
if (!this.validForMine(resource))
return false;
//update resource in database;
if (!MineQueries.CHANGE_RESOURCE(this, resource))
return false;
this.production = resource;
return true;
}
public MineProduction getMineType() {
return this.mineType;
}
public String getZoneName() {
return this.zoneName;
}
public Resource getProduction() {
return this.production;
}
public boolean getIsActive() {
return this.isActive;
}
public float getAltitude() {
return this.altitude;
}
public Guild getOwningGuild() {
if (this.owningGuild == null)
return Guild.getErrantGuild();
else
return this.owningGuild;
}
public int getFlags() {
return flags;
}
public void setFlags(int flags) {
this.flags = flags;
}
public Zone getParentZone() {
return parentZone;
}
public GuildTag getGuildTag() {
return guildTag;
}
public void setMineType(String type) {
this.mineType = MineProduction.getByName(type);
}
public void setActive(boolean isAc) {
this.isActive = isAc;
Building building = BuildingManager.getBuildingFromCache(this.buildingID);
if (building != null && !this.isActive)
building.isDeranking.compareAndSet(true, false);
}
public void setOwningGuild(Guild owningGuild) {
this.owningGuild = owningGuild;
}
public static Mine getMineFromTower(int towerID) { public static Mine getMineFromTower(int towerID) {
return Mine.towerMap.get(towerID); return Mine.towerMap.get(towerID);
} }
public boolean validForMine(Resource r) {
if (this.mineType == null)
return false;
return this.mineType.validForMine(r, this.isExpansion());
}
/*
* Serialization
*/
public static void serializeForClientMsg(Mine mine, ByteBufferWriter writer) { public static void serializeForClientMsg(Mine mine, ByteBufferWriter writer) {
writer.putInt(mine.getObjectType().ordinal()); writer.putInt(mine.getObjectType().ordinal());
writer.putInt(mine.getObjectUUID()); writer.putInt(mine.getObjectUUID());
@ -321,20 +241,6 @@ public class Mine extends AbstractGameObject {
GuildTag._serializeForDisplay(mine.nationTag, writer); GuildTag._serializeForDisplay(mine.nationTag, writer);
} }
public void serializeForMineProduction(ByteBufferWriter writer) {
writer.putInt(this.getObjectType().ordinal());
writer.putInt(this.getObjectUUID());
writer.putInt(this.getObjectUUID()); //actually a hash of mine
// writer.putInt(0x215C92BB); //this.unknown1);
writer.putString(this.mineType.name);
writer.putString(this.zoneName);
writer.putInt(this.production.hash);
writer.putInt(this.production.baseProduction);
writer.putInt(this.getModifiedProductionAmount()); //TODO calculate range penalty here
writer.putInt(3600); //window in seconds
writer.putInt(this.isExpansion() ? this.mineType.xpacHash : this.mineType.hash);
}
public static ArrayList<Mine> getMinesForGuild(int guildID) { public static ArrayList<Mine> getMinesForGuild(int guildID) {
ArrayList<Mine> mineList = new ArrayList<>(); ArrayList<Mine> mineList = new ArrayList<>();
@ -349,14 +255,6 @@ public class Mine extends AbstractGameObject {
return mineList; return mineList;
} }
public static long getLastChange() {
return lastChange;
}
public static void setLastChange(long lastChange) {
Mine.lastChange = lastChange;
}
/* /*
* Database * Database
*/ */
@ -369,19 +267,6 @@ public class Mine extends AbstractGameObject {
return new ArrayList<>(mineMap.keySet()); return new ArrayList<>(mineMap.keySet());
} }
@Override
public void updateDatabase() {
// TODO Create update logic.
}
public int getBuildingID() {
return buildingID;
}
public void setBuildingID(int buildingID) {
this.buildingID = buildingID;
}
public static boolean validateClaimer(PlayerCharacter playerCharacter) { public static boolean validateClaimer(PlayerCharacter playerCharacter) {
// Method validates that the claimer meets // Method validates that the claimer meets
@ -433,7 +318,7 @@ public class Mine extends AbstractGameObject {
if (treeRank < 1) if (treeRank < 1)
return false; return false;
if (guildUnderMineLimit(playerGuild.getNation(), treeRank) == false){ if (guildUnderMineLimit(playerGuild.getNation(), treeRank) == false) {
ErrorPopupMsg.sendErrorMsg(playerCharacter, "Your nation cannot support another mine."); ErrorPopupMsg.sendErrorMsg(playerCharacter, "Your nation cannot support another mine.");
return false; return false;
} }
@ -450,11 +335,116 @@ public class Mine extends AbstractGameObject {
for (Guild guild : playerGuild.getSubGuildList()) for (Guild guild : playerGuild.getSubGuildList())
mineCnt += Mine.getMinesForGuild(guild.getObjectUUID()).size(); mineCnt += Mine.getMinesForGuild(guild.getObjectUUID()).size();
if (mineCnt > tolRank) return mineCnt <= tolRank;
}
public boolean changeProductionType(Resource resource) {
if (!this.validForMine(resource))
return false;
//update resource in database;
if (!MineQueries.CHANGE_RESOURCE(this, resource))
return false; return false;
this.production = resource;
return true; return true;
} }
public MineProduction getMineType() {
return this.mineType;
}
public void setMineType(String type) {
this.mineType = MineProduction.getByName(type);
}
public String getZoneName() {
return this.zoneName;
}
public Resource getProduction() {
return this.production;
}
public boolean getIsActive() {
return this.isActive;
}
public float getAltitude() {
return this.altitude;
}
public Guild getOwningGuild() {
if (this.owningGuild == null)
return Guild.getErrantGuild();
else
return this.owningGuild;
}
public void setOwningGuild(Guild owningGuild) {
this.owningGuild = owningGuild;
}
/*
* Serialization
*/
public int getFlags() {
return flags;
}
public void setFlags(int flags) {
this.flags = flags;
}
public Zone getParentZone() {
return parentZone;
}
public GuildTag getGuildTag() {
return guildTag;
}
public void setActive(boolean isAc) {
this.isActive = isAc;
Building building = BuildingManager.getBuildingFromCache(this.buildingID);
if (building != null && !this.isActive)
building.isDeranking.compareAndSet(true, false);
}
public boolean validForMine(Resource r) {
if (this.mineType == null)
return false;
return this.mineType.validForMine(r, this.isExpansion());
}
public void serializeForMineProduction(ByteBufferWriter writer) {
writer.putInt(this.getObjectType().ordinal());
writer.putInt(this.getObjectUUID());
writer.putInt(this.getObjectUUID()); //actually a hash of mine
// writer.putInt(0x215C92BB); //this.unknown1);
writer.putString(this.mineType.name);
writer.putString(this.zoneName);
writer.putInt(this.production.hash);
writer.putInt(this.production.baseProduction);
writer.putInt(this.getModifiedProductionAmount()); //TODO calculate range penalty here
writer.putInt(3600); //window in seconds
writer.putInt(this.isExpansion() ? this.mineType.xpacHash : this.mineType.hash);
}
@Override
public void updateDatabase() {
// TODO Create update logic.
}
public int getBuildingID() {
return buildingID;
}
public void setBuildingID(int buildingID) {
this.buildingID = buildingID;
}
public void handleDestroyMine() { public void handleDestroyMine() {
if (!this.isActive) if (!this.isActive)
@ -465,7 +455,6 @@ public class Mine extends AbstractGameObject {
this.guildName = ""; this.guildName = "";
this.nationName = ""; this.nationName = "";
this.owningGuild = Guild.getErrantGuild(); this.owningGuild = Guild.getErrantGuild();
Mine.setLastChange(System.currentTimeMillis());
this.lastClaimer = null; this.lastClaimer = null;
this.wasClaimed = false; this.wasClaimed = false;
@ -513,6 +502,7 @@ public class Mine extends AbstractGameObject {
return true; return true;
} }
public boolean depositMineResources() { public boolean depositMineResources() {
if (this.owningGuild.isEmptyGuild()) if (this.owningGuild.isEmptyGuild())

9
src/engine/objects/Mob.java

@ -1508,17 +1508,14 @@ public class Mob extends AbstractIntelligenceAgent {
double gold = (ThreadLocalRandom.current().nextDouble() * (maxGold - minGold) + minGold); double gold = (ThreadLocalRandom.current().nextDouble() * (maxGold - minGold) + minGold);
//server specific gold multiplier //server specific gold multiplier
double goldMod = MBServerStatics.GOLD_RATE_MOD;
gold *= goldMod; gold *= Float.parseFloat(ConfigManager.MB_NORMAL_DROP_RATE.getValue());
//modify for hotzone //modify for hotzone
if (ZoneManager.inHotZone(mob.getLoc())) if (ZoneManager.inHotZone(mob.getLoc()))
gold *= MBServerStatics.HOT_GOLD_RATE_MOD; gold *= Float.parseFloat(ConfigManager.MB_HOTZONE_DROP_RATE.getValue());
gold *= MBServerStatics.GOLD_RATE_MOD;
return (int) gold; return (int) gold;
} }

2
src/engine/objects/PlayerCharacter.java

@ -2213,7 +2213,7 @@ public void dismissNecroPets() {
for (Effect eff : playerCharacter.getEffects().values()) { for (Effect eff : playerCharacter.getEffects().values()) {
if (eff.getPower() == null && otherPlayer) if (eff.getPower() == null && otherPlayer)
continue; continue;
if (eff.getPower().token == 429506619) // Oblivion's Caress if (eff.getPower() != null && eff.getPower().token == 429506619) // Oblivion's Caress
continue; continue;
if ( !eff.serializeForLoad(writer)) if ( !eff.serializeForLoad(writer))
continue; continue;

92
src/engine/objects/Portal.java

@ -1,13 +1,13 @@
package engine.objects; package engine.objects;
import engine.Enum.RunegateType; import engine.Enum;
import engine.Enum.PortalType;
import engine.InterestManagement.WorldGrid; import engine.InterestManagement.WorldGrid;
import engine.gameManager.ConfigManager; import engine.gameManager.ConfigManager;
import engine.job.JobScheduler; import engine.job.JobScheduler;
import engine.jobs.CloseGateJob; import engine.jobs.CloseGateJob;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.util.HashSet; import java.util.HashSet;
@ -19,28 +19,20 @@ import java.util.HashSet;
public class Portal { public class Portal {
private boolean active; private boolean active;
private RunegateType sourceGateType; public Enum.PortalType portalType;
private RunegateType portalType; public Building sourceGate;
private RunegateType destinationGateType; public Building targetGate;
private final Vector3fImmutable portalLocation; public final Vector3fImmutable portalLocation;
private long lastActive = 0; private long lastActive = 0;
public Portal(RunegateType gateType, RunegateType portalType, RunegateType destinationGate) { public Portal(Building sourceGate, PortalType portalType, Building targetGate) {
Building gateBuilding;
this.active = false; this.active = false;
this.sourceGateType = gateType; this.sourceGate = sourceGate;
this.destinationGateType = destinationGate; this.targetGate = targetGate;
this.portalType = portalType; this.portalType = portalType;
gateBuilding = this.sourceGateType.getGateBuilding(); this.portalLocation = sourceGate.getLoc().add(new Vector3fImmutable(portalType.offset.x, 6, portalType.offset.y));
if (gateBuilding == null) {
Logger.error("Gate building " + this.sourceGateType.getGateUUID() + " for " + this.sourceGateType.name() + " missing");
}
this.portalLocation = gateBuilding.getLoc().add(new Vector3fImmutable(portalType.getOffset().x, 6, portalType.getOffset().y));
} }
public boolean isActive() { public boolean isActive() {
@ -51,15 +43,12 @@ public class Portal {
public void deactivate() { public void deactivate() {
Building sourceBuilding;
// Remove effect bit from the runegate building, which turns off this // Remove effect bit from the runegate building, which turns off this
// portal type's particle effect // portal type's particle effect
sourceBuilding = this.sourceGateType.getGateBuilding(); sourceGate.removeEffectBit(portalType.effectFlag);
sourceBuilding.removeEffectBit(portalType.getEffectFlag());
this.active = false; this.active = false;
sourceBuilding.updateEffects(); sourceGate.updateEffects();
} }
public void activate(boolean autoClose) { public void activate(boolean autoClose) {
@ -70,8 +59,8 @@ public class Portal {
// Apply effect bit to the runegate building, which turns on this // Apply effect bit to the runegate building, which turns on this
// portal type's particle effect // portal type's particle effect
sourceBuilding = this.sourceGateType.getGateBuilding();
sourceBuilding.addEffectBit(portalType.getEffectFlag()); sourceGate.addEffectBit(portalType.effectFlag);
this.lastActive = System.currentTimeMillis(); this.lastActive = System.currentTimeMillis();
this.active = true; this.active = true;
@ -79,10 +68,10 @@ public class Portal {
// tries to send a dispatch. // tries to send a dispatch.
if (ConfigManager.worldServer.isRunning == true) if (ConfigManager.worldServer.isRunning == true)
sourceBuilding.updateEffects(); sourceGate.updateEffects();
if (autoClose == true) { if (autoClose == true) {
CloseGateJob cgj = new CloseGateJob(sourceBuilding, portalType); CloseGateJob cgj = new CloseGateJob(sourceGate, portalType);
JobScheduler.getInstance().scheduleJob(cgj, MBServerStatics.RUNEGATE_CLOSE_TIME); JobScheduler.getInstance().scheduleJob(cgj, MBServerStatics.RUNEGATE_CLOSE_TIME);
} }
} }
@ -107,57 +96,10 @@ public class Portal {
if (player.getTimeStamp("lastMoveGate") < this.lastActive) if (player.getTimeStamp("lastMoveGate") < this.lastActive)
return; return;
Building gateBuilding;
gateBuilding = destinationGateType.getGateBuilding(); player.teleport(targetGate.getLoc());
if (gateBuilding != null){
player.teleport(gateBuilding.getLoc());
player.setSafeMode(); player.setSafeMode();
}
}
/**
* @return the sourceGateType
*/
public RunegateType getSourceGateType() {
return sourceGateType;
}
/**
* @param sourceGateType the sourceGateType to set
*/
public void setSourceGateType(RunegateType sourceGateType) {
this.sourceGateType = sourceGateType;
}
/**
* @return the portalType
*/
public RunegateType getPortalType() {
return portalType;
}
/**
* @param portalType the portalType to set
*/
public void setPortalType(RunegateType portalType) {
this.portalType = portalType;
}
/**
* @return the destinationGateType
*/
public RunegateType getDestinationGateType() {
return destinationGateType;
}
/**
* @param destinationGateType the destinationGateType to set
*/
public void setDestinationGateType(RunegateType destinationGateType) {
this.destinationGateType = destinationGateType;
} }
/** /**

23
src/engine/objects/Realm.java

@ -21,6 +21,7 @@ import engine.powers.PowersBase;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.awt.*;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -36,8 +37,9 @@ public class Realm {
// Internal class cache // Internal class cache
private static ConcurrentHashMap<Integer, Realm> _realms = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); public static ConcurrentHashMap<Integer, Realm> _realms = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
public Color mapColor;
private final float mapR; //Red color private final float mapR; //Red color
private final float mapG; //Green color private final float mapG; //Green color
private final float mapB; //Blue color private final float mapB; //Blue color
@ -63,7 +65,7 @@ public class Realm {
private final int stretchY; private final int stretchY;
private final int locX; private final int locX;
private final int locY; private final int locY;
private final int realmID; public final int realmID;
private final HashSet<Integer> cities = new HashSet<>(); private final HashSet<Integer> cities = new HashSet<>();
private String hash; private String hash;
@ -72,6 +74,7 @@ public class Realm {
*/ */
public Realm(ResultSet rs) throws SQLException, UnknownHostException { public Realm(ResultSet rs) throws SQLException, UnknownHostException {
this.mapColor = new Color(rs.getInt("mapColor"));
this.mapR = rs.getFloat("mapR"); this.mapR = rs.getFloat("mapR");
this.mapG = rs.getFloat("mapG"); this.mapG = rs.getFloat("mapG");
this.mapB = rs.getFloat("mapB"); this.mapB = rs.getFloat("mapB");
@ -200,20 +203,8 @@ public class Realm {
public static void configureAllRealms() { public static void configureAllRealms() {
Realm serverRealm; for (Realm realm : Realm._realms.values()) {
int realmID; realm.configure();
for (Enum.RealmType realmType : Enum.RealmType.values()) {
realmID = realmType.getRealmID();
// Don't serialize seafloor
if (realmID == 0)
continue;
serverRealm = Realm.getRealm(realmID);
serverRealm.configure();
} }
} }

180
src/engine/objects/Runegate.java

@ -1,61 +1,56 @@
package engine.objects; package engine.objects;
import engine.Enum.RunegateType; import engine.Enum;
import engine.gameManager.BuildingManager; import engine.Enum.PortalType;
import engine.gameManager.DbManager;
import engine.net.ByteBufferWriter; import engine.net.ByteBufferWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
/* Runegates are tied to particular buildings at /* Runegates are tied to particular buildings at
* bootstrap. They aren't tighly coupled, with * bootstrap derived from the Portal creation.
* the Runegate merely toggling effect bits on it's * This is only to enable the toggling of effect
* parent building. * bits when traveler is used.
*/ */
public class Runegate { public class Runegate {
// Runegate class Instance variables // Runegate class Instance variables
private static final Runegate[] _runegates = new Runegate[9]; public static HashMap<Integer, Runegate> _runegates = new HashMap<>();
private final Portal[] _portals; public Portal[] _portals;
private final RunegateType gateType; public Building gateBuilding;
private Runegate(RunegateType gateType) { private Runegate(Building gateBuilding) {
this._portals = new Portal[8]; this._portals = new Portal[8];
this.gateType = gateType; this.gateBuilding = gateBuilding;
// Each Runegate has a different destination // Load portals for this runegate portals from the database
// for each portal opened.
configureGatePortals(); configurePortals();
// Chaos, Khar and Oblivion are on by default // Chaos, Khar and Oblivion are on by default
_portals[RunegateType.CHAOS.ordinal()].activate(false); _portals[Enum.PortalType.CHAOS.ordinal()].activate(false);
_portals[RunegateType.OBLIV.ordinal()].activate(false); _portals[Enum.PortalType.OBLIV.ordinal()].activate(false);
_portals[RunegateType.MERCHANT.ordinal()].activate(false); _portals[Enum.PortalType.MERCHANT.ordinal()].activate(false);
} }
public void activatePortal(RunegateType gateType) { public void activatePortal(Enum.PortalType portalType) {
this._portals[gateType.ordinal()].activate(true); this._portals[portalType.ordinal()].activate(true);
} }
public void deactivatePortal(RunegateType gateType) { public void deactivatePortal(Enum.PortalType portalType) {
this._portals[gateType.ordinal()].deactivate(); this._portals[portalType.ordinal()].deactivate();
} }
public RunegateType getGateType() {
return this.gateType;
}
public static Runegate[] getRunegates() {
return Runegate._runegates;
}
public Portal[] getPortals() { public Portal[] getPortals() {
@ -74,17 +69,30 @@ public class Runegate {
public static void loadAllRunegates() { public static void loadAllRunegates() {
for (RunegateType runegateType : RunegateType.values()) { ArrayList<Integer> gateList;
_runegates[runegateType.ordinal()] = new Runegate(runegateType);
gateList = DbManager.RunegateQueries.GET_RUNEGATE_LIST();
for (int gateID : gateList) {
Building gateBuilding = (Building) DbManager.getObject(Enum.GameObjectType.Building, gateID);
Runegate runegate = new Runegate(gateBuilding);
_runegates.put(gateID, runegate);
} }
} }
public void _serializeForEnterWorld(ByteBufferWriter writer) { public void configurePortals() {
Building gateBuilding; ArrayList<Portal> portalList = DbManager.RunegateQueries.GET_PORTAL_LIST(this.gateBuilding.getObjectUUID());
gateBuilding = BuildingManager.getBuilding(this.gateType.getGateUUID()); for (Portal portal : portalList) {
this._portals[portal.portalType.ordinal()] = portal;
}
}
public void _serializeForEnterWorld(ByteBufferWriter writer) {
writer.putInt(gateBuilding.getObjectType().ordinal()); writer.putInt(gateBuilding.getObjectType().ordinal());
writer.putInt(gateBuilding.getObjectUUID()); writer.putInt(gateBuilding.getObjectUUID());
@ -94,114 +102,6 @@ public class Runegate {
writer.putFloat(gateBuilding.getLoc().getLong()); writer.putFloat(gateBuilding.getLoc().getLong());
} }
private void configureGatePortals() {
// Source gate type, portal type and destination gate type;
switch (this.gateType) {
case EARTH:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.EARTH, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.EARTH, RunegateType.AIR, RunegateType.AIR);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.EARTH, RunegateType.FIRE, RunegateType.FORBID);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.EARTH, RunegateType.WATER, RunegateType.WATER);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.EARTH, RunegateType.SPIRIT, RunegateType.SPIRIT);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.EARTH, RunegateType.CHAOS, RunegateType.CHAOS);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.EARTH, RunegateType.OBLIV, RunegateType.OBLIV);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.EARTH, RunegateType.MERCHANT, RunegateType.MERCHANT);
break;
case AIR:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.AIR, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.AIR, RunegateType.AIR, RunegateType.FORBID);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.AIR, RunegateType.FIRE, RunegateType.FIRE);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.AIR, RunegateType.WATER, RunegateType.WATER);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.AIR, RunegateType.SPIRIT, RunegateType.SPIRIT);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.AIR, RunegateType.CHAOS, RunegateType.CHAOS);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.AIR, RunegateType.OBLIV, RunegateType.OBLIV);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.AIR, RunegateType.MERCHANT, RunegateType.MERCHANT);
break;
case FIRE:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.FIRE, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.FIRE, RunegateType.AIR, RunegateType.AIR);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.FIRE, RunegateType.FIRE, RunegateType.FORBID);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.FIRE, RunegateType.WATER, RunegateType.WATER);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.FIRE, RunegateType.SPIRIT, RunegateType.SPIRIT);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.FIRE, RunegateType.CHAOS, RunegateType.CHAOS);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.FIRE, RunegateType.OBLIV, RunegateType.OBLIV);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.FIRE, RunegateType.MERCHANT, RunegateType.MERCHANT);
break;
case WATER:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.WATER, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.WATER, RunegateType.AIR, RunegateType.AIR);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.WATER, RunegateType.FIRE, RunegateType.FIRE);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.WATER, RunegateType.WATER, RunegateType.FORBID);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.WATER, RunegateType.SPIRIT, RunegateType.SPIRIT);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.WATER, RunegateType.CHAOS, RunegateType.CHAOS);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.WATER, RunegateType.OBLIV, RunegateType.OBLIV);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.WATER, RunegateType.MERCHANT, RunegateType.MERCHANT);
break;
case SPIRIT:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.SPIRIT, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.SPIRIT, RunegateType.AIR, RunegateType.AIR);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.SPIRIT, RunegateType.FIRE, RunegateType.FIRE);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.SPIRIT, RunegateType.WATER, RunegateType.WATER);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.SPIRIT, RunegateType.SPIRIT, RunegateType.FORBID);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.SPIRIT, RunegateType.CHAOS, RunegateType.CHAOS);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.SPIRIT, RunegateType.OBLIV, RunegateType.OBLIV);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.SPIRIT, RunegateType.MERCHANT, RunegateType.MERCHANT);
break;
case CHAOS:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.CHAOS, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.CHAOS, RunegateType.AIR, RunegateType.AIR);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.CHAOS, RunegateType.FIRE, RunegateType.FIRE);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.CHAOS, RunegateType.WATER, RunegateType.WATER);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.CHAOS, RunegateType.SPIRIT, RunegateType.SPIRIT);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.CHAOS, RunegateType.CHAOS, RunegateType.MERCHANT);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.CHAOS, RunegateType.OBLIV, RunegateType.OBLIV);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.CHAOS, RunegateType.MERCHANT, RunegateType.MERCHANT);
break;
case OBLIV:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.OBLIV, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.OBLIV, RunegateType.AIR, RunegateType.AIR);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.OBLIV, RunegateType.FIRE, RunegateType.FIRE);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.OBLIV, RunegateType.WATER, RunegateType.WATER);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.OBLIV, RunegateType.SPIRIT, RunegateType.SPIRIT);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.OBLIV, RunegateType.CHAOS, RunegateType.CHAOS);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.OBLIV, RunegateType.OBLIV, RunegateType.MERCHANT);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.OBLIV, RunegateType.MERCHANT, RunegateType.MERCHANT);
break;
case MERCHANT:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.MERCHANT, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.MERCHANT, RunegateType.AIR, RunegateType.AIR);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.MERCHANT, RunegateType.FIRE, RunegateType.FIRE);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.MERCHANT, RunegateType.WATER, RunegateType.WATER);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.MERCHANT, RunegateType.SPIRIT, RunegateType.SPIRIT);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.MERCHANT, RunegateType.CHAOS, RunegateType.CHAOS);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.MERCHANT, RunegateType.OBLIV, RunegateType.OBLIV);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.MERCHANT, RunegateType.MERCHANT, RunegateType.FORBID);
break;
case FORBID:
_portals[RunegateType.EARTH.ordinal()] = new Portal(RunegateType.FORBID, RunegateType.EARTH, RunegateType.EARTH);
_portals[RunegateType.AIR.ordinal()] = new Portal(RunegateType.FORBID, RunegateType.AIR, RunegateType.AIR);
_portals[RunegateType.FIRE.ordinal()] = new Portal(RunegateType.FORBID, RunegateType.FIRE, RunegateType.FIRE);
_portals[RunegateType.WATER.ordinal()] = new Portal(RunegateType.FORBID, RunegateType.WATER, RunegateType.WATER);
_portals[RunegateType.SPIRIT.ordinal()] = new Portal(RunegateType.FORBID, RunegateType.SPIRIT, RunegateType.SPIRIT);
_portals[RunegateType.CHAOS.ordinal()] = new Portal(RunegateType.FORBID, RunegateType.CHAOS, RunegateType.CHAOS);
_portals[RunegateType.OBLIV.ordinal()] = new Portal(RunegateType.FORBID, RunegateType.OBLIV, RunegateType.OBLIV);
_portals[RunegateType.MERCHANT.ordinal()] = new Portal(RunegateType.FORBID, RunegateType.MERCHANT, RunegateType.MERCHANT);
break;
}
}
public static ArrayList<String> GetAllOpenGateIDStrings(){ public static ArrayList<String> GetAllOpenGateIDStrings(){
ArrayList<String> openGateIDStrings = new ArrayList<>(); ArrayList<String> openGateIDStrings = new ArrayList<>();

7
src/engine/objects/Zone.java

@ -23,6 +23,7 @@ import org.pmw.tinylog.Logger;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
@ -50,8 +51,8 @@ public class Zone extends AbstractGameObject {
private boolean isNPCCity = false; private boolean isNPCCity = false;
private boolean isPlayerCity = false; private boolean isPlayerCity = false;
private String hash; private String hash;
private int minLvl; public int minLvl;
private int maxLvl; public int maxLvl;
private float worldAltitude = 0; private float worldAltitude = 0;
@ -59,7 +60,7 @@ public class Zone extends AbstractGameObject {
public final Set<Building> zoneBuildingSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); public final Set<Building> zoneBuildingSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
public final Set<NPC> zoneNPCSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); public final Set<NPC> zoneNPCSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
public final Set<Mob> zoneMobSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); public final Set<Mob> zoneMobSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
public boolean hasBeenHotzone = false;
/** /**
* ResultSet Constructor * ResultSet Constructor
*/ */

4
src/engine/powers/poweractions/ClaimMinePowerAction.java

@ -50,10 +50,6 @@ public class ClaimMinePowerAction extends AbstractPowerAction {
if (mine == null) if (mine == null)
return; return;
// Release prior claims
Mine.releaseMineClaims(playerCharacter);
if (mine.claimMine(playerCharacter) == true) if (mine.claimMine(playerCharacter) == true)
ChatManager.sendSystemMessage( (PlayerCharacter) source, "You successfully claimed this mine.."); ChatManager.sendSystemMessage( (PlayerCharacter) source, "You successfully claimed this mine..");
} }

28
src/engine/powers/poweractions/OpenGatePowerAction.java

@ -12,7 +12,7 @@ package engine.powers.poweractions;
import engine.Enum; import engine.Enum;
import engine.Enum.BuildingGroup; import engine.Enum.BuildingGroup;
import engine.Enum.GameObjectType; import engine.Enum.GameObjectType;
import engine.Enum.RunegateType; import engine.Enum.PortalType;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.objects.AbstractCharacter; import engine.objects.AbstractCharacter;
import engine.objects.AbstractWorldObject; import engine.objects.AbstractWorldObject;
@ -46,9 +46,6 @@ public class OpenGatePowerAction extends AbstractPowerAction {
return; return;
Building targetBuilding = (Building) awo; Building targetBuilding = (Building) awo;
Runegate runeGate;
RunegateType runegateType;
RunegateType portalType;
int token; int token;
// Sanity check. // Sanity check.
@ -69,39 +66,39 @@ public class OpenGatePowerAction extends AbstractPowerAction {
// Which portal was opened? // Which portal was opened?
token = pb.getToken(); token = pb.getToken();
portalType = RunegateType.AIR; PortalType portalType = PortalType.AIR;
switch (token) { switch (token) {
case 428937084: //Death Gate case 428937084: //Death Gate
portalType = RunegateType.OBLIV; portalType = PortalType.OBLIV;
break; break;
case 429756284: //Chaos Gate case 429756284: //Chaos Gate
portalType = RunegateType.CHAOS; portalType = PortalType.CHAOS;
break; break;
case 429723516: //Khar Gate case 429723516: //Khar Gate
portalType = RunegateType.MERCHANT; portalType = PortalType.MERCHANT;
break; break;
case 429559676: //Spirit Gate case 429559676: //Spirit Gate
portalType = RunegateType.SPIRIT; portalType = PortalType.SPIRIT;
break; break;
case 429592444: //Water Gate case 429592444: //Water Gate
portalType = RunegateType.WATER; portalType = PortalType.WATER;
break; break;
case 429428604: //Fire Gate case 429428604: //Fire Gate
portalType = RunegateType.FIRE; portalType = PortalType.FIRE;
break; break;
case 429526908: //Air Gate case 429526908: //Air Gate
portalType = RunegateType.AIR; portalType = PortalType.AIR;
break; break;
case 429625212: //Earth Gate case 429625212: //Earth Gate
portalType = RunegateType.EARTH; portalType = PortalType.EARTH;
break; break;
default: default:
@ -109,12 +106,9 @@ public class OpenGatePowerAction extends AbstractPowerAction {
// Which runegate was clicked on? // Which runegate was clicked on?
runegateType = RunegateType.getGateTypeFromUUID(targetBuilding.getObjectUUID()); Runegate runeGate = Runegate._runegates.get(targetBuilding.getObjectUUID());
runeGate = Runegate.getRunegates()[runegateType.ordinal()];
runeGate.activatePortal(portalType); runeGate.activatePortal(portalType);
} }
@Override @Override

15
src/engine/powers/poweractions/RunegateTeleportPowerAction.java

@ -10,7 +10,7 @@
package engine.powers.poweractions; package engine.powers.poweractions;
import engine.Enum; import engine.Enum;
import engine.Enum.RunegateType; import engine.Enum.PortalType;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.net.Dispatch; import engine.net.Dispatch;
import engine.net.DispatchMessage; import engine.net.DispatchMessage;
@ -45,22 +45,15 @@ public class RunegateTeleportPowerAction extends AbstractPowerAction {
Building rg = null; Building rg = null;
Vector3fImmutable rgLoc; Vector3fImmutable rgLoc;
for (Runegate runegate: Runegate.getRunegates()) { for (Runegate runegate: Runegate._runegates.values()) {
if ((runegate.getGateType() == RunegateType.OBLIV) || rgLoc = runegate.gateBuilding.getLoc();
(runegate.getGateType() == RunegateType.CHAOS))
continue;
for (Runegate thisGate : Runegate.getRunegates()) {
rgLoc = thisGate.getGateType().getGateBuilding().getLoc();
float distanceToRunegateSquared = source.getLoc().distanceSquared2D(rgLoc); float distanceToRunegateSquared = source.getLoc().distanceSquared2D(rgLoc);
if (distanceToRunegateSquared < sqr(dist)) { if (distanceToRunegateSquared < sqr(dist)) {
dist = sqrt(distanceToRunegateSquared); dist = sqrt(distanceToRunegateSquared);
rg = thisGate.getGateType().getGateBuilding(); rg = runegate.gateBuilding;
}
} }
} }

21
src/engine/server/MBServerStatics.java

@ -406,26 +406,6 @@ public class MBServerStatics {
public static int SPATIAL_HASH_BUCKETSY = 12288; public static int SPATIAL_HASH_BUCKETSY = 12288;
public static float MAX_PLAYER_X_LOC = 129999; public static float MAX_PLAYER_X_LOC = 129999;
public static float MAX_PLAYER_Y_LOC = -97000; public static float MAX_PLAYER_Y_LOC = -97000;
public static String NO_DELETE_COMBAT = "Can't delete items when in Combat with another player.";
/*
* Rates
*/
public static float EXP_RATE_MOD = 2f; // Probably don't want to declare
// as final.
public static float GOLD_RATE_MOD = 1.0f; // Probably don't want to declare
// as final.
public static float DROP_RATE_MOD = 1.0f; // Probably don't want to declare
// as final.
// Hotzones
public static float HOT_EXP_RATE_MOD = 2.0f; // Probably don't want to
// declare as final.
public static float HOT_GOLD_RATE_MOD = 1.5f; // Probably don't want to
// declare as final.
public static float HOT_DROP_RATE_MOD = 1.8f; // Probably don't want to
// declare as final.
/* /*
* Ranges * Ranges
@ -703,7 +683,6 @@ public class MBServerStatics {
public static final int DESPAWN_TIMER_ONCE_LOOTED = 5 * 1000; public static final int DESPAWN_TIMER_ONCE_LOOTED = 5 * 1000;
public static final int MAX_COMBAT_HITBOX_RADIUS = 80; public static final int MAX_COMBAT_HITBOX_RADIUS = 80;
public static final int PROC_CHANCE = 5; // %chance to proc public static final int PROC_CHANCE = 5; // %chance to proc
public static float PRODUCTION_TIME_MULTIPLIER = .5f;
/* /*
* Mob loot -- gold calculations * Mob loot -- gold calculations

21
src/engine/server/world/WorldServer.java

@ -70,7 +70,6 @@ import static java.lang.System.exit;
public class WorldServer { public class WorldServer {
private static LocalDateTime bootTime = LocalDateTime.now(); private static LocalDateTime bootTime = LocalDateTime.now();
private static long lastHZChange = System.currentTimeMillis();
public boolean isRunning = false; public boolean isRunning = false;
// Member variable declaration // Member variable declaration
@ -121,14 +120,6 @@ public class WorldServer {
} }
} }
public static long getLastHZChange() {
return lastHZChange;
}
public static void setLastHZChange(long lastChange) {
lastHZChange = lastChange;
}
public static void trainerInfo(TrainerInfoMsg msg, ClientConnection origin) { public static void trainerInfo(TrainerInfoMsg msg, ClientConnection origin) {
NPC npc = NPC.getFromCache(msg.getObjectID()); NPC npc = NPC.getFromCache(msg.getObjectID());
@ -326,6 +317,9 @@ public class WorldServer {
Logger.info("Loading Realms"); Logger.info("Loading Realms");
Realm.loadAllRealms(); Realm.loadAllRealms();
Logger.info("Loading RealmMap");
RealmMap.loadRealmImageMap();
Logger.info("Loading Kits"); Logger.info("Loading Kits");
DbManager.KitQueries.GET_ALL_KITS(); DbManager.KitQueries.GET_ALL_KITS();
@ -335,10 +329,6 @@ public class WorldServer {
Logger.info("Starting InterestManager."); Logger.info("Starting InterestManager.");
WorldGrid.startLoadJob(); WorldGrid.startLoadJob();
Logger.info("Loading Spaital Hash");
RealmMap.loadRealmImageMap();
DbManager.MobBaseQueries.SET_AI_DEFAULTS(); DbManager.MobBaseQueries.SET_AI_DEFAULTS();
Logger.info("Loading blueprint data."); Logger.info("Loading blueprint data.");
@ -431,13 +421,9 @@ public class WorldServer {
Logger.info("Running Heraldry Audit for Deleted Players"); Logger.info("Running Heraldry Audit for Deleted Players");
Heraldry.AuditHeraldry(); Heraldry.AuditHeraldry();
if (ZoneManager.getHotZone() != null)
WorldServer.setLastHZChange(System.currentTimeMillis());
Logger.info("Starting Mobile AI FSM"); Logger.info("Starting Mobile AI FSM");
MobileFSMManager.getInstance(); MobileFSMManager.getInstance();
for (Zone zone : ZoneManager.getAllZones()) { for (Zone zone : ZoneManager.getAllZones()) {
if (zone.getHeightMap() != null) { if (zone.getHeightMap() != null) {
if (zone.getHeightMap().getBucketWidthX() == 0) { if (zone.getHeightMap().getBucketWidthX() == 0) {
@ -483,6 +469,7 @@ public class WorldServer {
Logger.info("Running garbage collection..."); Logger.info("Running garbage collection...");
System.gc(); System.gc();
return true; return true;
} }

27
src/engine/util/MapLoader.java

@ -4,7 +4,7 @@
package engine.util; package engine.util;
import engine.Enum.RealmType; import engine.InterestManagement.RealmMap;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import engine.server.world.WorldServer; import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
@ -26,8 +26,7 @@ public enum MapLoader {
long timeToLoad = System.currentTimeMillis(); long timeToLoad = System.currentTimeMillis();
long bytesRead = 0; long bytesRead = 0;
long realmsWritten = 0; long realmsWritten = 0;
int realmUUID;
Integer realmUUID = null;
// Load image from disk // Load image from disk
@ -47,33 +46,21 @@ public enum MapLoader {
image = flipImage(image); image = flipImage(image);
// Initialize color lookup table
for (RealmType realm : RealmType.values()) {
realm.addToColorMap();
}
// Load spatial imageMap with color data from file // Load spatial imageMap with color data from file
for (int i = 0; i < MBServerStatics.SPATIAL_HASH_BUCKETSY; i++) { for (int i = 0; i < MBServerStatics.SPATIAL_HASH_BUCKETSY; i++) {
for (int j = 0; j < MBServerStatics.SPATIAL_HASH_BUCKETSX; j++) { for (int j = 0; j < MBServerStatics.SPATIAL_HASH_BUCKETSX; j++) {
try { try {
int rgb = image.getRGB(j, i); int rgb = image.getRGB(j, i);
realmUUID = RealmType.getRealmIDByRGB(rgb); realmUUID = RealmMap.getRealmIDByRGB(rgb);
if (realmUUID == null) {
Logger.error("Corrupted png: unknown color " + rgb);
WorldServer.shutdown();
}
realmMap[j][i] = realmUUID.intValue(); realmMap[j][i] = realmUUID;
bytesRead++; bytesRead++;
if (realmUUID.intValue() != 0) if (realmUUID != 0)
realmsWritten++; realmsWritten++;
}catch (Exception e){ }catch (Exception e){
// Logger.error("REALMEDIT ERROR", e.getMessage());
continue; continue;
} }
@ -82,9 +69,7 @@ public enum MapLoader {
} }
timeToLoad = System.currentTimeMillis() - timeToLoad; timeToLoad = System.currentTimeMillis() - timeToLoad;
Logger.info( bytesRead + " pixels processed in " + timeToLoad / 1000 + " seconds"); Logger.info( bytesRead + "Realm imageMNap pixels processed in " + timeToLoad / 1000 + " seconds");
Logger.info("Realm pixels written : " + realmsWritten);
image = null;
return realmMap; return realmMap;
} }

218
src/engine/workthreads/HourlyJobThread.java

@ -29,111 +29,10 @@ import static engine.server.MBServerStatics.MINE_LATE_WINDOW;
public class HourlyJobThread implements Runnable { public class HourlyJobThread implements Runnable {
private static final int hotzoneCount = 0;
public HourlyJobThread() { public HourlyJobThread() {
} }
public void run() {
// *** REFACTOR: TRY TRY TRY TRY {{{{{{{{{{{ OMG
Logger.info("Hourly job is now running.");
try {
ZoneManager.generateAndSetRandomHotzone();
Zone hotzone = ZoneManager.getHotZone();
if (hotzone == null) {
Logger.error("Null hotzone returned from mapmanager");
} else {
Logger.info("new hotzone: " + hotzone.getName());
WorldServer.setLastHZChange(System.currentTimeMillis());
}
} catch (Exception e) {
Logger.error(e.toString());
}
// Open or Close mines for the current mine window.
processMineWindow();
// Deposit mine resources to Guilds
for (Mine mine : Mine.getMines()) {
try {
mine.depositMineResources();
} catch (Exception e) {
Logger.info(e.getMessage() + " for Mine " + mine.getObjectUUID());
}
}
// Reset time-gated access to WOO slider.
// *** Do this after the mines open/close!
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW) {
Guild guild;
for (AbstractGameObject dbObject : DbManager.getList(Enum.GameObjectType.Guild)) {
guild = (Guild) dbObject;
if (guild != null)
guild.wooWasModified = false;
}
}
// Mines can only be claimed once per cycle.
// This will reset at 1am after the last mine
// window closes.
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW + 1) {
for (Mine mine : Mine.getMines()) {
if (mine.wasClaimed == true)
mine.wasClaimed = false;
}
}
// Decay Shrines at midnight every day
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW)
decayShrines();
// Update city population values
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
if (map != null) {
for (AbstractGameObject ago : map.values()) {
City city = (City) ago;
if (city != null)
if (city.getGuild() != null) {
ArrayList<PlayerCharacter> guildList = Guild.GuildRoster(city.getGuild());
city.setPopulation(guildList.size());
}
}
City.lastCityUpdate = System.currentTimeMillis();
} else {
Logger.error("missing city map");
}
// Log metrics to console
Logger.info(WorldServer.getUptimeString());
Logger.info(SimulationManager.getPopulationString());
Logger.info(MessageDispatcher.getNetstatString());
Logger.info(PurgeOprhans.recordsDeleted.toString() + "orphaned items deleted");
}
public static void decayShrines() { public static void decayShrines() {
ArrayList<Shrine> shrineList = new ArrayList<>(); ArrayList<Shrine> shrineList = new ArrayList<>();
@ -181,14 +80,15 @@ public class HourlyJobThread implements Runnable {
ArrayList<Mine> mines = Mine.getMines(); ArrayList<Mine> mines = Mine.getMines();
for (Mine mine : mines) { for (Mine mine : mines) {
if (LocalDateTime.now().getHour() == 1400) {
mine.wasClaimed = false;
}
try { try {
// Open Errant Mines // Open Errant Mines
if (mine.getOwningGuild().isEmptyGuild()) { if (mine.getOwningGuild().isEmptyGuild()) {
HourlyJobThread.mineWindowOpen(mine); HourlyJobThread.mineWindowOpen(mine);
Mine.setLastChange(System.currentTimeMillis());
continue; continue;
} }
@ -198,14 +98,12 @@ public class HourlyJobThread implements Runnable {
if (mine.getOwningGuild().getNation().getMineTime() == if (mine.getOwningGuild().getNation().getMineTime() ==
LocalDateTime.now().getHour() && mine.wasClaimed == false) { LocalDateTime.now().getHour() && mine.wasClaimed == false) {
HourlyJobThread.mineWindowOpen(mine); HourlyJobThread.mineWindowOpen(mine);
Mine.setLastChange(System.currentTimeMillis());
continue; continue;
} }
// Close all the remaining mines // Close the mine if it reaches this far
if (mineWindowClose(mine)) mineWindowClose(mine);
Mine.setLastChange(System.currentTimeMillis());
} catch (Exception e) { } catch (Exception e) {
Logger.error("mineID: " + mine.getObjectUUID(), e.toString()); Logger.error("mineID: " + mine.getObjectUUID(), e.toString());
@ -265,8 +163,6 @@ public class HourlyJobThread implements Runnable {
mine.nationName = nation.getName(); mine.nationName = nation.getName();
mine.nationTag = nation.getGuildTag(); mine.nationTag = nation.getGuildTag();
Mine.setLastChange(System.currentTimeMillis());
mineBuilding.rebuildMine(); mineBuilding.rebuildMine();
WorldGrid.updateObject(mineBuilding); WorldGrid.updateObject(mineBuilding);
@ -286,4 +182,108 @@ public class HourlyJobThread implements Runnable {
mine.wasClaimed = true; mine.wasClaimed = true;
return true; return true;
} }
public void run() {
// *** REFACTOR: TRY TRY TRY TRY {{{{{{{{{{{ OMG
Logger.info("Hourly job is now running.");
try {
// Use the same hotZone this hour up and until
// the HotZone_Duration from the ConfigManager
if (ZoneManager.hotZone == null)
ZoneManager.generateAndSetRandomHotzone();
else
ZoneManager.hotZoneCycle = ZoneManager.hotZoneCycle + 1;
if (ZoneManager.hotZoneCycle > Integer.parseInt(ConfigManager.MB_HOTZONE_DURATION.getValue()))
ZoneManager.generateAndSetRandomHotzone();
if (ZoneManager.hotZone == null) {
Logger.error("Null HotZone returned from ZoneManager");
} else {
Logger.info("HotZone switched to: " + ZoneManager.hotZone.getName());
}
} catch (Exception e) {
Logger.error(e.toString());
}
// Open or Close mines for the current mine window.
processMineWindow();
// Deposit mine resources to Guilds
for (Mine mine : Mine.getMines()) {
try {
mine.depositMineResources();
} catch (Exception e) {
Logger.info(e.getMessage() + " for Mine " + mine.getObjectUUID());
}
}
// Reset time-gated access to WOO slider.
// *** Do this after the mines open/close!
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW) {
Guild guild;
for (AbstractGameObject dbObject : DbManager.getList(Enum.GameObjectType.Guild)) {
guild = (Guild) dbObject;
if (guild != null)
guild.wooWasModified = false;
}
}
// Mines can only be claimed once per cycle.
// This will reset at 1am after the last mine
// window closes.
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW + 1) {
for (Mine mine : Mine.getMines()) {
if (mine.wasClaimed == true)
mine.wasClaimed = false;
}
}
// Decay Shrines at midnight every day
if (LocalDateTime.now().getHour() == MINE_LATE_WINDOW)
decayShrines();
// Update city population values
ConcurrentHashMap<Integer, AbstractGameObject> map = DbManager.getMap(Enum.GameObjectType.City);
if (map != null) {
for (AbstractGameObject ago : map.values()) {
City city = (City) ago;
if (city != null)
if (city.getGuild() != null) {
ArrayList<PlayerCharacter> guildList = Guild.GuildRoster(city.getGuild());
city.setPopulation(guildList.size());
}
}
City.lastCityUpdate = System.currentTimeMillis();
} else {
Logger.error("missing city map");
}
// Log metrics to console
Logger.info(WorldServer.getUptimeString());
Logger.info(SimulationManager.getPopulationString());
Logger.info(MessageDispatcher.getNetstatString());
Logger.info(PurgeOprhans.recordsDeleted.toString() + "orphaned items deleted");
}
} }

Loading…
Cancel
Save