Compare commits

..
Author SHA1 Message Date
SlaveOfMagicbot 86062cf712 fix: null-safe upgradeDateTime conversion in BuildingManager.setUpgradeDateTime
Placing a banestone (and other callers) pass null to clear a fresh
building's upgrade timer, but the inline .atZone(...).toInstant() NPE'd
on null. Convert only when non-null; the DB layer already handles null.
2026-10-12 16:47:26 -05:00
SlaveOfMagicbot 85cd4e0c14 fix: use LocalDateTime for mine late-window calc in ArcMineWindowAvailableTimeMsg
Instant has no hour-of-day field, so .with(HOUR_OF_DAY, ...) threw
UnsupportedTemporalTypeException. Switch lateTime to LocalDateTime so the
late-window (midnight) time can be set and the seconds-remaining computed.
2026-10-12 12:44:27 -05:00
SlaveOfMagicbot 8a136d84f4 refactor: migrate JodaTime to java.time (rebuild on subdate2 ab96cfc)
Complete the JodaTime -> java.time migration across 30 files on the
correct subdate2 base. No org.joda references remain.
2026-10-09 20:12:23 -05:00
105 changed files with 1414 additions and 4521 deletions

No files matched your search

@@ -468,12 +468,7 @@ public enum InterestManager implements Runnable {
continue;
awonpc.playerAgroMap.put(player.getObjectUUID(), 0f);
// siege engines keep firing at their target when a new player loads them
if (!awonpc.isSiege())
((Mob) awonpc).setCombatTarget(null);
((Mob) awonpc).setCombatTarget(null);
lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii());
} else if ((awo.getObjectTypeMask() & MBServerStatics.MASK_NPC) != 0) {
+10 -11
View File
@@ -14,7 +14,6 @@ import engine.mbEnums;
import engine.objects.Bane;
import engine.objects.City;
import engine.workthreads.WarehousePushThread;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
import java.sql.*;
@@ -34,8 +33,8 @@ public class BaneRecord extends DataRecord {
private String baneDropperHash;
private String baneGuildHash;
private String baneNationHash;
private DateTime baneLiveTime;
private DateTime baneDropTime;
private LocalDateTime baneLiveTime;
private LocalDateTime baneDropTime;
private BaneRecord(Bane bane) {
this.recordType = mbEnums.DataRecordType.BANE;
@@ -129,9 +128,9 @@ public class BaneRecord extends DataRecord {
return outStatement;
}
public static DateTime getLastBaneDateTime(City city) {
public static LocalDateTime getLastBaneDateTime(City city) {
DateTime outDateTime = null;
LocalDateTime outDateTime = null;
try (Connection connection = DbManager.getConnection();
PreparedStatement statement = buildDateTimeQueryStatement(connection, city);
@@ -139,7 +138,7 @@ public class BaneRecord extends DataRecord {
while (rs.next()) {
outDateTime = new DateTime(rs.getTimestamp("endDatetime"));
outDateTime = rs.getTimestamp("endDatetime").toLocalDateTime();
}
@@ -160,7 +159,7 @@ public class BaneRecord extends DataRecord {
}
public static void updateLiveDate(Bane bane, DateTime dateTime) {
public static void updateLiveDate(Bane bane, LocalDateTime dateTime) {
if (bane == null)
return;
@@ -175,13 +174,13 @@ public class BaneRecord extends DataRecord {
}
}
private static PreparedStatement buildUpdateLiveDateStatement(Connection connection, Bane bane, DateTime dateTime) throws SQLException {
private static PreparedStatement buildUpdateLiveDateStatement(Connection connection, Bane bane, LocalDateTime dateTime) throws SQLException {
PreparedStatement outStatement = null;
String queryString = "UPDATE `warehouse_banehistory` SET `liveDatetime` = ?, `dirty` = 1 WHERE `city_id` = ? AND `resolution` = 'PENDING'";
outStatement = connection.prepareStatement(queryString);
outStatement.setTimestamp(1, new java.sql.Timestamp(dateTime.getMillis()));
outStatement.setTimestamp(1, Timestamp.valueOf(dateTime));
outStatement.setString(2, bane.getCity().getHash());
return outStatement;
@@ -366,12 +365,12 @@ public class BaneRecord extends DataRecord {
if (this.baneDropTime == null)
outStatement.setNull(8, java.sql.Types.DATE);
else
outStatement.setTimestamp(8, new java.sql.Timestamp(this.baneDropTime.getMillis()));
outStatement.setTimestamp(8, Timestamp.valueOf(this.baneDropTime));
if (this.baneLiveTime == null)
outStatement.setNull(9, java.sql.Types.DATE);
else
outStatement.setTimestamp(9, new java.sql.Timestamp(this.baneLiveTime.getMillis()));
outStatement.setTimestamp(9, Timestamp.valueOf(this.baneLiveTime));
outStatement.setString(10, this.eventType.name());
+3 -3
View File
@@ -14,7 +14,7 @@ import engine.objects.Bane;
import engine.objects.Building;
import engine.objects.City;
import engine.objects.PlayerCharacter;
import org.joda.time.DateTime;
import java.time.LocalDateTime;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@@ -71,12 +71,12 @@ public class dbBaneHandler extends dbHandlerBase {
}
public boolean SET_BANE_TIME(DateTime toSet, int cityUUID) {
public boolean SET_BANE_TIME(LocalDateTime toSet, int cityUUID) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `dyn_banes` SET `liveDate`=? WHERE `cityUUID`=?")) {
preparedStatement.setTimestamp(1, new java.sql.Timestamp(toSet.getMillis()));
preparedStatement.setTimestamp(1, java.sql.Timestamp.valueOf(toSet));
preparedStatement.setLong(2, cityUUID);
preparedStatement.execute();
@@ -17,7 +17,9 @@ import engine.mbEnums.DbObjectType;
import engine.mbEnums.ProtectionState;
import engine.mbEnums.TaxType;
import engine.objects.*;
import org.joda.time.DateTime;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@@ -40,7 +42,7 @@ public class dbBuildingHandler extends dbHandlerBase {
public Building CREATE_BUILDING(int parentZoneID, int OwnerUUID, String name, int meshUUID,
Vector3fImmutable location, float meshScale, int currentHP,
ProtectionState protectionState, int currentGold, int rank,
DateTime upgradeDate, int blueprintUUID, float w, float rotY) {
Instant upgradeDate, int blueprintUUID, float w, float rotY) {
Building building = null;
@@ -61,7 +63,7 @@ public class dbBuildingHandler extends dbHandlerBase {
preparedStatement.setInt(12, rank);
if (upgradeDate != null)
preparedStatement.setTimestamp(13, new java.sql.Timestamp(upgradeDate.getMillis()));
preparedStatement.setTimestamp(13, new java.sql.Timestamp(upgradeDate.toEpochMilli()));
else
preparedStatement.setNull(13, java.sql.Types.DATE);
@@ -749,7 +751,7 @@ public class dbBuildingHandler extends dbHandlerBase {
return false;
}
public boolean updateBuildingUpgradeTime(LocalDateTime upgradeDateTime, Building toUpgrade, int costToUpgrade) {
public boolean updateBuildingUpgradeTime(Instant upgradeDateTime, Building toUpgrade, int costToUpgrade) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE obj_building SET upgradeDate=?, currentGold=? "
@@ -758,8 +760,7 @@ public class dbBuildingHandler extends dbHandlerBase {
if (upgradeDateTime == null)
preparedStatement.setNull(1, java.sql.Types.DATE);
else
preparedStatement.setTimestamp(1, new java.sql.Timestamp(upgradeDateTime.atZone(ZoneId.systemDefault())
.toInstant().toEpochMilli()));
preparedStatement.setTimestamp(1, new java.sql.Timestamp(upgradeDateTime.toEpochMilli()));
preparedStatement.setInt(2, toUpgrade.getStrongboxValue() - costToUpgrade);
preparedStatement.setInt(3, toUpgrade.getObjectUUID());
@@ -838,7 +839,7 @@ public class dbBuildingHandler extends dbHandlerBase {
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE obj_building SET taxDate=? "
+ "WHERE UID = ?")) {
preparedStatement.setTimestamp(1, new java.sql.Timestamp(DateTime.now().plusDays(7).getMillis()));
preparedStatement.setTimestamp(1, new java.sql.Timestamp(Instant.now().plus(7, java.time.temporal.ChronoUnit.DAYS).toEpochMilli()));
preparedStatement.setInt(2, building.getObjectUUID());
return (preparedStatement.executeUpdate() > 0);
+3 -3
View File
@@ -14,7 +14,7 @@ import engine.mbEnums;
import engine.mbEnums.GuildHistoryType;
import engine.objects.*;
import engine.server.world.WorldServer;
import org.joda.time.DateTime;
import java.time.Instant;
import org.pmw.tinylog.Logger;
import java.sql.*;
@@ -125,7 +125,7 @@ public class dbGuildHandler extends dbHandlerBase {
return false;
}
public boolean ADD_TO_GUILDHISTORY(int target, PlayerCharacter playerCharacter, DateTime historyDate, GuildHistoryType historyType) {
public boolean ADD_TO_GUILDHISTORY(int target, PlayerCharacter playerCharacter, Instant historyDate, GuildHistoryType historyType) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO `dyn_character_guildhistory` (`GuildID`, `CharacterID`, `historyDate`, `historyType`) VALUES (?,?,?,?)")) {
@@ -136,7 +136,7 @@ public class dbGuildHandler extends dbHandlerBase {
if (historyDate == null)
preparedStatement.setNull(3, java.sql.Types.DATE);
else
preparedStatement.setTimestamp(3, new Timestamp(historyDate.getMillis()));
preparedStatement.setTimestamp(3, java.sql.Timestamp.from(historyDate));
preparedStatement.setString(4, historyType.name());
+35 -9
View File
@@ -16,6 +16,8 @@ import engine.mbEnums.ItemType;
import engine.objects.AbstractCharacter;
import engine.objects.CharacterItemManager;
import engine.objects.Item;
import engine.objects.ItemTemplate;
import org.json.JSONObject;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@@ -175,23 +177,47 @@ public class dbItemHandler extends dbHandlerBase {
return itemList;
}
public HashMap<Integer, Integer> LOAD_TEMPLATE_MODTABLES() {
public void LOAD_ITEM_TEMPLATES() {
HashMap<Integer, Integer> modTables = new HashMap<>();
HashMap<ItemType, Integer> templateTCountMap = new HashMap<>();
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_item_templates`;");
ResultSet rs = preparedStatement.executeQuery()) {
while (rs.next()) {
int templateID = rs.getInt("id");
JSONObject jsonObject = new JSONObject(rs.getString("template"));
ItemTemplate itemTemplate = new ItemTemplate(jsonObject);
itemTemplate.template_id = templateID;
ItemTemplate.templates.put(templateID, itemTemplate);
templateTCountMap.merge(itemTemplate.item_type, 1, Integer::sum);
}
Logger.info(templateTCountMap.toString());
} catch (Exception e) {
Logger.error(e);
}
}
public void LOAD_TEMPLATE_MODTABLES() {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_vendor_items`;");
ResultSet rs = preparedStatement.executeQuery()) {
while (rs.next())
modTables.put(rs.getInt("templateID"), rs.getInt("modTable"));
while (rs.next()) {
int templateID = rs.getInt("templateID");
int modTable = rs.getInt("modTable");
ItemTemplate template = ItemTemplate.templates.get(templateID);
template.modTable = modTable;
}
} catch (Exception e) {
Logger.error(e);
}
Logger.info("read: " + modTables.size());
return modTables;
}
public Item GET_ITEM(final int itemUUID) {
@@ -299,7 +325,7 @@ public class dbItemHandler extends dbHandlerBase {
for (Item item : inventory) {
if (item.template.getItemType().equals(ItemType.GOLD))
if (item.template.item_type.equals(ItemType.GOLD))
continue;
try (Connection connection = DbManager.getConnection();
@@ -448,7 +474,7 @@ public class dbItemHandler extends dbHandlerBase {
*/
public boolean UPDATE_GOLD(final Item item, int newValue, int oldValue) {
if (!item.template.getItemType().equals(ItemType.GOLD))
if (!item.template.item_type.equals(ItemType.GOLD))
return false;
try (Connection connection = DbManager.getConnection();
@@ -528,7 +554,7 @@ public class dbItemHandler extends dbHandlerBase {
// Write 0 if we will not modify the value from template
if (value == item.template.getItemValue())
if (value == item.template.item_value)
value = 0;
try (Connection connection = DbManager.getConnection();
+4 -3
View File
@@ -12,7 +12,8 @@ package engine.db.handlers;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.objects.Mob;
import org.joda.time.DateTime;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@@ -82,7 +83,7 @@ public class dbMobHandler extends dbHandlerBase {
return mobileList;
}
public boolean updateUpgradeTime(Mob mob, DateTime upgradeDateTime) {
public boolean updateUpgradeTime(Mob mob, LocalDateTime upgradeDateTime) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE obj_mob SET upgradeDate=? "
@@ -91,7 +92,7 @@ public class dbMobHandler extends dbHandlerBase {
if (upgradeDateTime == null)
preparedStatement.setNull(1, java.sql.Types.DATE);
else
preparedStatement.setTimestamp(1, new java.sql.Timestamp(upgradeDateTime.getMillis()));
preparedStatement.setTimestamp(1, new java.sql.Timestamp(upgradeDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
preparedStatement.setInt(2, mob.getObjectUUID());
+5 -4
View File
@@ -15,7 +15,8 @@ import engine.mbEnums;
import engine.mbEnums.ProfitType;
import engine.objects.NPC;
import engine.objects.NPCProfits;
import org.joda.time.DateTime;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@@ -57,7 +58,7 @@ public class dbNPCHandler extends dbHandlerBase {
runeSets.put(runeSetID, runeList);
} else {
ArrayList<Integer> runeList = runeSets.get(runeSetID);
runeList.add(runeBaseID);
runeList.add(runeSetID);
runeSets.put(runeSetID, runeList);
}
}
@@ -240,7 +241,7 @@ public class dbNPCHandler extends dbHandlerBase {
}
}
public boolean updateUpgradeTime(NPC npc, DateTime upgradeDateTime) {
public boolean updateUpgradeTime(NPC npc, LocalDateTime upgradeDateTime) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE obj_npc SET upgradeDate=? "
@@ -249,7 +250,7 @@ public class dbNPCHandler extends dbHandlerBase {
if (upgradeDateTime == null)
preparedStatement.setNull(1, java.sql.Types.DATE);
else
preparedStatement.setTimestamp(1, new java.sql.Timestamp(upgradeDateTime.getMillis()));
preparedStatement.setTimestamp(1, new java.sql.Timestamp(upgradeDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
preparedStatement.setInt(2, npc.getObjectUUID());
@@ -50,15 +50,7 @@ public class dbPromotionClassHandler extends dbHandlerBase {
public PromotionClass GET_PROMOTION_CLASS(final int objectUUID) {
PromotionClass promotionClass;
if (objectUUID == 0)
return null;
promotionClass = (PromotionClass) DbManager.getFromCache(mbEnums.GameObjectType.PromotionClass, objectUUID);
if (promotionClass != null)
return promotionClass;
PromotionClass promotionClass = null;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `static_rune_promotion` WHERE `ID` = ?")) {
+3 -3
View File
@@ -16,7 +16,7 @@ import engine.mbEnums.ProtectionState;
import engine.objects.AbstractGameObject;
import engine.objects.Building;
import engine.objects.Shrine;
import org.joda.time.DateTime;
import java.time.Instant;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
@@ -53,7 +53,7 @@ public class dbShrineHandler extends dbHandlerBase {
public ArrayList<AbstractGameObject> CREATE_SHRINE(int parentZoneID, int OwnerUUID, String name, int meshUUID,
Vector3fImmutable location, float meshScale, int currentHP,
ProtectionState protectionState, int currentGold, int rank,
DateTime upgradeDate, int blueprintUUID, float w, float rotY, String shrineType) {
Instant upgradeDate, int blueprintUUID, float w, float rotY, String shrineType) {
ArrayList<AbstractGameObject> shrineList = new ArrayList<>();
@@ -74,7 +74,7 @@ public class dbShrineHandler extends dbHandlerBase {
preparedStatement.setInt(12, rank);
if (upgradeDate != null)
preparedStatement.setTimestamp(13, new java.sql.Timestamp(upgradeDate.getMillis()));
preparedStatement.setTimestamp(13, java.sql.Timestamp.from(upgradeDate));
else
preparedStatement.setNull(13, java.sql.Types.DATE);
+8 -22
View File
@@ -20,9 +20,8 @@ import engine.objects.City;
import engine.objects.Transaction;
import engine.objects.Warehouse;
import engine.server.MBServerStatics;
import org.joda.time.DateTime;
import java.time.Instant;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.pmw.tinylog.Logger;
@@ -41,7 +40,7 @@ public class dbWarehouseHandler extends dbHandlerBase {
}
public boolean CREATE_TRANSACTION(int warehouseBuildingID, GameObjectType targetType, int targetUUID, TransactionType transactionType, mbEnums.ResourceType resource, int amount, DateTime date) {
public boolean CREATE_TRANSACTION(int warehouseBuildingID, GameObjectType targetType, int targetUUID, TransactionType transactionType, mbEnums.ResourceType resource, int amount, Instant date) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO `dyn_warehouse_transactions` (`warehouseUID`, `targetType`,`targetUID`, `type`,`resource`,`amount`,`date` ) VALUES (?,?,?,?,?,?,?)")) {
@@ -52,7 +51,7 @@ public class dbWarehouseHandler extends dbHandlerBase {
preparedStatement.setString(4, transactionType.name());
preparedStatement.setString(5, resource.name());
preparedStatement.setInt(6, amount);
preparedStatement.setTimestamp(7, new java.sql.Timestamp(date.getMillis()));
preparedStatement.setTimestamp(7, new java.sql.Timestamp(date.toEpochMilli()));
return (preparedStatement.executeUpdate() > 0);
@@ -135,6 +134,7 @@ public class dbWarehouseHandler extends dbHandlerBase {
while (rs.next()) {
int cityUID = rs.getInt("cityUUID");
JSONObject jsonObject = new JSONObject(rs.getString("warehouse"));
City city = City.getCity(cityUID);
if (city == null) {
@@ -142,18 +142,12 @@ public class dbWarehouseHandler extends dbHandlerBase {
continue;
}
try {
city.warehouse = new Warehouse(new JSONObject(rs.getString("warehouse")));
} catch (JSONException e) {
Logger.error("Warehouse for city " + cityUID + " failed to load: " + e.getMessage());
continue;
}
city.warehouse = new Warehouse(jsonObject);
city.warehouse.city = city;
// Locate warehouse building
for (Building building : city.parentZone.zoneBuildingSet) {
if (building.getBlueprint().getBuildingGroup().equals(mbEnums.BuildingGroup.WAREHOUSE) && building.getRank() != -1) {
if (building.getBlueprint().getBuildingGroup().equals(mbEnums.BuildingGroup.WAREHOUSE)) {
city.warehouse.building = building;
break;
}
@@ -211,16 +205,8 @@ public class dbWarehouseHandler extends dbHandlerBase {
ResultSet rs = preparedStatement.executeQuery()) {
while (rs.next()) {
int workOrderID = rs.getInt("workorderID");
WorkOrder workOrder;
try {
workOrder = new WorkOrder(new JSONObject(rs.getString("workorder")));
} catch (JSONException e) {
Logger.error("WorkOrder " + workOrderID + " failed to load: " + e.getMessage());
continue;
}
JSONObject jsonObject = new JSONObject(rs.getString("workorder"));
WorkOrder workOrder = new WorkOrder(jsonObject);
submitList.add(workOrder);
}
} catch (Exception e) {
+3 -3
View File
@@ -15,8 +15,8 @@ import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.objects.AbstractGameObject;
import engine.objects.Item;
import engine.objects.ItemTemplate;
import engine.objects.PlayerCharacter;
import engine.parsers.objects.CObjectTemplate;
import org.pmw.tinylog.Logger;
/**
@@ -38,7 +38,7 @@ public class CreateItemCmd extends AbstractDevCmd {
}
int templateID = Integer.parseInt(words[0]);
CObjectTemplate template = CObjectTemplate.lookup(templateID);
ItemTemplate template = ItemTemplate.templates.get(templateID);
if (template == null) {
ChatManager.chatSystemInfo(playerCharacter, "No such template found.");
@@ -51,7 +51,7 @@ public class CreateItemCmd extends AbstractDevCmd {
for (int i = 0; i < size; i++) {
if (!playerCharacter.charItemManager.hasRoomInventory(template.getItemWt())) {
if (!playerCharacter.charItemManager.hasRoomInventory(template.item_wt)) {
ChatManager.chatSystemInfo(playerCharacter, "You are encumbered!.");
break;
}
-106
View File
@@ -1,106 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.objects.AbstractGameObject;
import engine.objects.Building;
import engine.objects.City;
import engine.objects.PlayerCharacter;
import engine.objects.Warehouse;
import java.util.HashMap;
public class FillCmd extends AbstractDevCmd {
public FillCmd() {
super("fill");
}
@Override
protected void _doCmd(PlayerCharacter pc, String[] words,
AbstractGameObject target) {
Building building;
City city;
Warehouse warehouse;
int amount = Integer.MAX_VALUE;
HashMap<mbEnums.ResourceType, Integer> oldResources;
if (words.length > 1) {
this.sendUsage(pc);
return;
}
if (words.length == 1 && !words[0].isEmpty()) {
try {
amount = Integer.parseInt(words[0]);
} catch (NumberFormatException e) {
throwbackError(pc, "Amount must be a number, " + words[0] + " is invalid");
return;
}
if (amount < 0) {
throwbackError(pc, "Amount must be 0 or more");
return;
}
}
if (target == null || target.getObjectType() != mbEnums.GameObjectType.Building) {
throwbackError(pc, "Select a warehouse");
return;
}
building = (Building) target;
if (building.getBlueprint() == null || building.getBlueprint().getBuildingGroup() != mbEnums.BuildingGroup.WAREHOUSE) {
throwbackError(pc, "Selected building is not a warehouse");
return;
}
city = building.getCity();
if (city == null || city.warehouse == null || city.warehouse.building == null
|| city.warehouse.building.getObjectUUID() != building.getObjectUUID()) {
throwbackError(pc, "Selected warehouse is not the active warehouse of a city");
return;
}
warehouse = city.warehouse;
oldResources = new HashMap<>(warehouse.resources);
for (mbEnums.ResourceType resourceType : mbEnums.ResourceType.values())
warehouse.resources.put(resourceType, Math.min(amount, resourceType.deposit_limit));
if (!DbManager.WarehouseQueries.UPDATE_WAREHOUSE(warehouse)) {
warehouse.resources.putAll(oldResources);
throwbackError(pc, "Failed to update the warehouse in the database");
return;
}
ChatManager.chatSayInfo(pc, "Filled the " + city.getCityName() + " warehouse"
+ (amount == Integer.MAX_VALUE ? " to each deposit limit" : " with " + amount + " of each resource (capped at the deposit limit)"));
}
@Override
protected String _getHelpString() {
return "Sets every resource in the selected warehouse";
}
@Override
protected String _getUsageString() {
return "' ./fill [amount]' with a warehouse selected (no amount fills each resource to its deposit limit)";
}
}
+5 -6
View File
@@ -18,7 +18,6 @@ import engine.mbEnums.BuildingGroup;
import engine.mbEnums.GameObjectType;
import engine.mbEnums.TargetColor;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import engine.util.StringUtils;
import java.text.DecimalFormat;
@@ -508,17 +507,17 @@ public class InfoCmd extends AbstractDevCmd {
case Item: //intentional passthrough
case MobLoot:
Item item = (Item) target;
CObjectTemplate template = CObjectTemplate.lookup(item.templateID);
output += StringUtils.addWS("Template: " + template.getTemplateId(), 20);
output += "Weight: " + template.getItemWt();
ItemTemplate template = ItemTemplate.templates.get(item.templateID);
output += StringUtils.addWS("Template: " + template.template_id, 20);
output += "Weight: " + template.item_wt;
output += newline;
DecimalFormat df = new DecimalFormat("###,###,###,###,##0");
output += StringUtils.addWS("Qty: "
+ df.format(item.getNumOfItems()), 20);
output += "Charges: " + (byte) item.chargesRemaining
+ '/' + item.template.getItemInitialCharges();
+ '/' + item.template.item_initial_charges;
output += newline;
output += "Name: " + template.getItemBaseName();
output += "Name: " + template.item_base_name;
output += newline;
output += item.getContainerInfo();
+9 -16
View File
@@ -11,11 +11,9 @@ package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.DbManager;
import engine.mbEnums.ItemContainerType;
import engine.mbEnums.ItemType;
import engine.mbEnums.OwnerType;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import engine.powers.EffectsBase;
/**
@@ -61,17 +59,18 @@ public class MakeItemCmd extends AbstractDevCmd {
}
int templateID;
CObjectTemplate template;
ItemTemplate template;
try {
templateID = Integer.parseInt(words[0]);
template = CObjectTemplate.lookup(templateID);
template = ItemTemplate.templates.get(words[0].toLowerCase());
if (template == null) {
throwbackError(pc, "No item template with id " + words[0]);
throwbackError(pc, "Supplied type " + words[0]
+ " failed to parse to an Integer");
return;
}
if (template.getItemType() == ItemType.GOLD) {
if (template.item_type == ItemType.GOLD) {
this.throwbackInfo(pc, "use /addgold to add gold.");
return;
}
@@ -133,7 +132,7 @@ public class MakeItemCmd extends AbstractDevCmd {
return;
}
}
template = CObjectTemplate.lookup(templateID);
template = ItemTemplate.templates.get(templateID);
if (template == null) {
throwbackError(pc, "Unable to find template " + templateID);
@@ -141,8 +140,8 @@ public class MakeItemCmd extends AbstractDevCmd {
}
if ((numItems > 1)
&& (template.getItemType().equals(ItemType.RESOURCE) == false)
&& (template.getItemType().equals(ItemType.OFFERING)) == false)
&& (template.item_type.equals(ItemType.RESOURCE) == false)
&& (template.item_type.equals(ItemType.OFFERING)) == false)
numItems = 1;
CharacterItemManager cim = pc.charItemManager;
@@ -156,7 +155,7 @@ public class MakeItemCmd extends AbstractDevCmd {
for (int i = 0; i < quantity; i++) {
int weight = template.getItemWt();
int weight = template.item_wt;
if (!cim.hasRoomInventory(weight)) {
throwbackError(pc, "Not enough room in inventory for any more of this item. " + i + " produced.");
@@ -170,7 +169,6 @@ public class MakeItemCmd extends AbstractDevCmd {
Item item = new Item(templateID);
item.ownerID = pc.getObjectUUID();
item.ownerType = OwnerType.PlayerCharacter;
item.containerType = ItemContainerType.INVENTORY;
if (numItems > 1)
item.setNumOfItems(numItems);
@@ -182,11 +180,6 @@ public class MakeItemCmd extends AbstractDevCmd {
return;
}
if (item == null) {
throwbackError(pc, "DB error 2: Unable to create item " + templateID + ".");
return;
}
//create prefix
if (!prefix.isEmpty())
item.addPermanentEnchantmentForDev(prefix, 0);
+2 -3
View File
@@ -11,7 +11,6 @@ package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import java.util.ArrayList;
@@ -53,8 +52,8 @@ public class PrintBankCmd extends AbstractDevCmd {
throwbackInfo(pc, "Bank for " + type + ' ' + name + " (" + tar.getObjectUUID() + ')');
for (Item item : list) {
CObjectTemplate template = CObjectTemplate.lookup(item.templateID);
throwbackInfo(pc, " " + template.getItemBaseName() + ", count: " + item.getNumOfItems());
ItemTemplate template = ItemTemplate.templates.get(item.templateID);
throwbackInfo(pc, " " + template.item_base_name + ", count: " + item.getNumOfItems());
}
Item gold = cim.getGoldBank();
+2 -3
View File
@@ -13,7 +13,6 @@ import engine.devcmd.AbstractDevCmd;
import engine.gameManager.ChatManager;
import engine.mbEnums.GameObjectType;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import engine.powers.effectmodifiers.AbstractEffectModifier;
public class PrintBonusesCmd extends AbstractDevCmd {
@@ -34,8 +33,8 @@ public class PrintBonusesCmd extends AbstractDevCmd {
if (target instanceof Item) {
type = "Item";
tar = (Item) target;
CObjectTemplate template = CObjectTemplate.lookup(((Item) tar).templateID);
name = template.getItemBaseName();
ItemTemplate template = ItemTemplate.templates.get(((Item) tar).templateID);
name = template.item_base_name;
} else if (target instanceof AbstractCharacter) {
tar = (AbstractCharacter) target;
name = ((AbstractCharacter) tar).getFirstName();
+3 -3
View File
@@ -66,7 +66,7 @@ public class PrintEquipCmd extends AbstractDevCmd {
throwbackInfo(pc, "Equip for " + type + ' ' + name + " (" + tar.getObjectUUID() + ')');
for (mbEnums.EquipSlotType slot : tarMob.charItemManager.equipped.keySet()) {
Item equip = tarMob.charItemManager.equipped.get(slot);
throwbackInfo(pc, equip.templateID + " : " + equip.template.getItemBaseName() + ", slot: " + slot);
throwbackInfo(pc, equip.templateID + " : " + equip.template.item_base_name + ", slot: " + slot);
}
return;
}
@@ -76,7 +76,7 @@ public class PrintEquipCmd extends AbstractDevCmd {
throwbackInfo(pc, "Equip for " + type + ' ' + name + " (" + tar.getObjectUUID() + ')');
for (mbEnums.EquipSlotType slot : tarMob.charItemManager.equipped.keySet()) {
Item equip = tarMob.charItemManager.equipped.get(slot);
throwbackInfo(pc, equip.templateID + " : " + equip.template.getItemBaseName() + ", slot: " + slot);
throwbackInfo(pc, equip.templateID + " : " + equip.template.item_base_name + ", slot: " + slot);
}
return;
}
@@ -87,7 +87,7 @@ public class PrintEquipCmd extends AbstractDevCmd {
for (mbEnums.EquipSlotType slot : list.keySet()) {
Item item = list.get(slot);
throwbackInfo(pc, " " + item.template.getItemBaseName() + ", slot: " + slot);
throwbackInfo(pc, " " + item.template.item_base_name + ", slot: " + slot);
}
}
@@ -12,7 +12,6 @@ package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.mbEnums.ItemType;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import java.text.DecimalFormat;
import java.util.ArrayList;
@@ -76,18 +75,18 @@ public class PrintInventoryCmd extends AbstractDevCmd {
int goldCount = 0;
for (Item item : inventory) {
CObjectTemplate template = CObjectTemplate.lookup(item.templateID);
ItemTemplate template = ItemTemplate.templates.get(item.templateID);
if (item.template.getItemType().equals(ItemType.GOLD) == false) {
if (item.template.item_type.equals(ItemType.GOLD) == false) {
String chargeInfo = "";
int chargeMax = template.getItemInitialCharges();
int chargeMax = template.item_initial_charges;
if (chargeMax > 0) {
int charges = item.chargesRemaining;
chargeInfo = " charges: " + charges + '/' + chargeMax;
}
throwbackInfo(pc, " " + template.getItemBaseName() + ", count: " + item.getNumOfItems() + chargeInfo);
throwbackInfo(pc, " " + template.item_base_name + ", count: " + item.getNumOfItems() + chargeInfo);
} else
goldCount += item.getNumOfItems();
}
+2 -3
View File
@@ -11,7 +11,6 @@ package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import java.util.ArrayList;
@@ -51,8 +50,8 @@ public class PrintVaultCmd extends AbstractDevCmd {
ArrayList<Item> list = cim.getVault();
throwbackInfo(pc, "Vault for " + type + ' ' + name + " (" + tar.getObjectUUID() + ')');
for (Item item : list) {
CObjectTemplate template = CObjectTemplate.lookup(item.templateID);
throwbackInfo(pc, " " + template.getItemBaseName() + ", count: " + item.getNumOfItems());
ItemTemplate template = ItemTemplate.templates.get(item.templateID);
throwbackInfo(pc, " " + template.item_base_name + ", count: " + item.getNumOfItems());
}
Item gold = cim.getGoldVault();
if (gold != null)
+3 -4
View File
@@ -5,7 +5,6 @@ import engine.gameManager.LootManager;
import engine.gameManager.ZoneManager;
import engine.loot.BootySetEntry;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import java.util.ArrayList;
import java.util.concurrent.ThreadLocalRandom;
@@ -35,10 +34,10 @@ public class SimulateBootyCmd extends AbstractDevCmd {
if (mob.bootySet != 0) {
for (BootySetEntry entry : LootManager._bootySetMap.get(mob.bootySet)) {
CObjectTemplate template = CObjectTemplate.lookup(entry.templateID);
ItemTemplate template = ItemTemplate.templates.get(entry.templateID);
if (template != null)
output += "[" + entry.bootyType + "] " + template.getItemBaseName() + " [Chance] " + entry.dropChance + newline;
output += "[" + entry.bootyType + "] " + template.item_base_name + " [Chance] " + entry.dropChance + newline;
}
}
@@ -58,7 +57,7 @@ public class SimulateBootyCmd extends AbstractDevCmd {
try {
mob.loadInventory();
for (Item lootItem : mob.charItemManager.getInventory()) {
switch (lootItem.template.getItemType()) {
switch (lootItem.template.item_type) {
case EMPLOYMENTCONTRACT: //CONTRACT
Contracts.add(lootItem);
break;
+13 -15
View File
@@ -22,10 +22,10 @@ import engine.mbEnums.BuildingGroup;
import engine.mbEnums.GameObjectType;
import engine.net.client.msg.ErrorPopupMsg;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
@@ -200,31 +200,31 @@ public enum BuildingManager {
return false;
}
CObjectTemplate template = CObjectTemplate.lookup(1705032); // Elan Stone
ItemTemplate template = ItemTemplate.templates.get(1705032); // Elan Stone
if (!player.charItemManager.hasRoomInventory(template.getItemWt()))
if (!player.charItemManager.hasRoomInventory(template.item_wt))
return false;
if (!ItemManager.MakeItemForPlayer(template.getTemplateId(), player, amount))
if (!ItemManager.MakeItemForPlayer(template.template_id, player, amount))
return false;
shrine.setFavors(0);
break;
case WAREHOUSE:
Warehouse warehouse = Warehouse.destroyedWarehouses.get(building.getObjectUUID());
City city = building.getCity();
if (city == null)
return true;
Warehouse warehouse = city.warehouse;
if (warehouse == null)
return false;
for (mbEnums.ResourceType resourceType : EnumSet.allOf(mbEnums.ResourceType.class)) {
CObjectTemplate resourceTemplate = CObjectTemplate.lookup(resourceType.templateID);
if (resourceTemplate == null)
continue;
if (!player.charItemManager.hasRoomInventory(resourceTemplate.getItemWt())) {
if (!player.charItemManager.hasRoomInventory(resourceType.template.item_wt)) {
ChatManager.chatSystemInfo(player, "You can not carry any more of that item.");
return false;
}
@@ -242,9 +242,6 @@ public enum BuildingManager {
}
}
if (Warehouse.isEmpty(warehouse))
Warehouse.destroyedWarehouses.remove(building.getObjectUUID());
break;
}
@@ -278,7 +275,8 @@ public enum BuildingManager {
if (building == null)
return;
if (!DbManager.BuildingQueries.updateBuildingUpgradeTime(upgradeDateTime, building, rankCost)) {
Instant instant = (upgradeDateTime == null) ? null : upgradeDateTime.atZone(ZoneId.systemDefault()).toInstant();
if (!DbManager.BuildingQueries.updateBuildingUpgradeTime(instant, building, rankCost)) {
Logger.error("Failed to set upgradeTime for building " + building.getObjectUUID());
return;
}
+3 -4
View File
@@ -22,7 +22,6 @@ import engine.net.client.ClientConnection;
import engine.net.client.handlers.ClientAdminCommandMsgHandler;
import engine.net.client.msg.chat.*;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import engine.server.MBServerStatics;
import engine.server.world.WorldServer;
import org.pmw.tinylog.Logger;
@@ -536,12 +535,12 @@ public enum ChatManager {
if (item != null) //Steal
if (success) {
String name = "";
if (item.template.getItemType().equals(mbEnums.ItemType.GOLD))
if (item.template.item_type.equals(mbEnums.ItemType.GOLD))
name = amount + " gold ";
else {
String vowels = "aeiou";
CObjectTemplate template = CObjectTemplate.lookup(item.templateID);
String iName = template.getItemBaseName();
ItemTemplate template = ItemTemplate.templates.get(item.templateID);
String iName = template.item_base_name;
if (iName.length() > 0)
if (vowels.indexOf(iName.substring(0, 1).toLowerCase()) >= 0)
name = "an " + iName + ' ';
+30 -138
View File
@@ -14,12 +14,9 @@ import engine.jobs.AttackJob;
import engine.jobs.DeferredPowerJob;
import engine.mbEnums;
import engine.net.client.ClientConnection;
import engine.net.client.msg.PowerProjectileMsg;
import engine.net.client.msg.TargetedActionMsg;
import engine.net.client.msg.UpdateStateMsg;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import engine.parsers.objects.RuneTemplate;
import engine.powers.DamageShield;
import engine.powers.effectmodifiers.AbstractEffectModifier;
import engine.powers.effectmodifiers.WeaponProcEffectModifier;
@@ -94,25 +91,25 @@ public enum CombatManager {
return;
}
if (mainWeapon == null && offWeapon != null && !offWeapon.template.getItemSkillUsed().equals("Block")) {
if (mainWeapon == null && offWeapon != null && !offWeapon.template.item_skill_used.equals("Block")) {
//swing left hand only
processAttack(attacker, target, mbEnums.EquipSlotType.LHELD);
return;
}
if (mainWeapon == null && offWeapon != null && offWeapon.template.getItemSkillUsed().equals("Block")) {
if (mainWeapon == null && offWeapon != null && offWeapon.template.item_skill_used.equals("Block")) {
//no weapon equipped with a shield, punch with one hand
processAttack(attacker, target, mbEnums.EquipSlotType.RHELD);
return;
}
if (mainWeapon != null && offWeapon != null && offWeapon.template.getItemSkillUsed().equals("Block")) {
if (mainWeapon != null && offWeapon != null && offWeapon.template.item_skill_used.equals("Block")) {
//one weapon equipped with a shield, swing with one hand
processAttack(attacker, target, mbEnums.EquipSlotType.RHELD);
return;
}
if (mainWeapon != null && offWeapon != null && !offWeapon.template.getItemSkillUsed().equals("Block")) {
if (mainWeapon != null && offWeapon != null && !offWeapon.template.item_skill_used.equals("Block")) {
//two weapons equipped, swing both hands
processAttack(attacker, target, mbEnums.EquipSlotType.RHELD);
if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter))
@@ -148,20 +145,12 @@ public enum CombatManager {
if (bonus != null)
rangeMod += bonus.getFloatPercentAll(mbEnums.ModType.WeaponRange, mbEnums.SourceType.None);
attackRange += engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_max_range * rangeMod;
} else if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) {
//unarmed mob, add the natural attack range from its rune (0 for most melee mobs)
if (bonus != null)
rangeMod += bonus.getFloatPercentAll(mbEnums.ModType.WeaponRange, mbEnums.SourceType.None);
attackRange += getNaturalAttackRange(attacker, slot) * rangeMod;
attackRange += weapon.template.item_weapon_max_range * rangeMod;
}
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob))
if (((Mob) attacker).isSiege())
attackRange = getSiegeRange((Mob) attacker);
attackRange = 300;
float distanceSquared = attacker.loc.distanceSquared(target.loc);
@@ -213,7 +202,7 @@ public enum CombatManager {
if (weapon != null) {
float wepSpeed = (int) (engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_wepspeed);
float wepSpeed = (int) (weapon.template.item_weapon_wepspeed);
if (weapon.getBonusPercent(mbEnums.ModType.WeaponSpeed, mbEnums.SourceType.None) != 0f) //add weapon speed bonus
wepSpeed *= (1 + weapon.getBonus(mbEnums.ModType.WeaponSpeed, mbEnums.SourceType.None));
@@ -225,22 +214,6 @@ public enum CombatManager {
wepSpeed = 10; //Old was 10, but it can be reached lower with legit buffs,effects.
delay = (long)wepSpeed * 100L;
} else {
//unarmed, use the natural attack speed from the mob or race rune
float naturalSpeed = getNaturalAttackSpeed(attacker, slot);
if (naturalSpeed > 0) {
if (attacker.getBonuses() != null && attacker.getBonuses().getFloatPercentAll(mbEnums.ModType.AttackDelay, mbEnums.SourceType.None) != 0f) //add effects speed bonus
naturalSpeed *= (1 + attacker.getBonuses().getFloatPercentAll(mbEnums.ModType.AttackDelay, mbEnums.SourceType.None));
if (naturalSpeed < 10)
naturalSpeed = 10;
delay = (long) naturalSpeed * 100L;
}
}
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob))
@@ -259,8 +232,7 @@ public enum CombatManager {
//handle retaliate
//siege engines only retaliate on damage, see AbstractCharacter.modifyHealth
if (AbstractCharacter.IsAbstractCharacter(target) && !(target.getObjectType().equals(mbEnums.GameObjectType.Mob) && ((Mob) target).isSiege())) {
if (AbstractCharacter.IsAbstractCharacter(target)) {
if (((AbstractCharacter) target).combatTarget == null || !((AbstractCharacter) target).combatTarget.isAlive()) {
((AbstractCharacter) target).combatTarget = attacker;
if (target.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter) && ((AbstractCharacter) target).isCombat())
@@ -272,13 +244,13 @@ public enum CombatManager {
if (weapon != null && !attacker.getObjectType().equals(mbEnums.GameObjectType.Mob)) {
//check if Out of Stamina
if (attacker.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter)) {
if (attacker.getStamina() < (weapon.template.getItemWt() / 3f)) {
if (attacker.getStamina() < (weapon.template.item_wt / 3f)) {
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
return;
}
}
float stam = weapon.template.getItemWt() / 3f;
float stam = weapon.template.item_wt / 3f;
stam = (stam < 1) ? 1 : stam;
attacker.modifyStamina(-(stam), attacker, true);
} else
@@ -347,7 +319,7 @@ public enum CombatManager {
DispatchManager.sendToAllInRange(attacker, msg);
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon == null ? null : weapon.template, null, slot));
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot));
DispatchManager.sendToAllInRange(target, cmm);
//set auto attack job
@@ -387,7 +359,7 @@ public enum CombatManager {
DispatchManager.dispatchMsgToInterestArea(target, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon == null ? null : weapon.template, null, slot));
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot));
DispatchManager.sendToAllInRange(target, cmm);
//set auto attack job
setAutoAttackJob(attacker, slot, delay);
@@ -418,7 +390,7 @@ public enum CombatManager {
if (((Mob) attacker).isSiege())
damageType = mbEnums.DamageType.SIEGE;
} else {
damageType = engine.parsers.objects.ItemTemplate.getWeapon(attacker.charItemManager.getEquipped().get(slot).templateID).weapon_damage.get(0).damage_type;
damageType = (mbEnums.DamageType) attacker.charItemManager.getEquipped().get(slot).template.item_weapon_damage.keySet().toArray()[0];
}
//get resists
@@ -475,7 +447,7 @@ public enum CombatManager {
if (resists.immuneTo(damageType)) {
//set auto attack job
//we need to send the animation even if the attacker misses
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon == null ? null : weapon.template, null, slot));
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) 0, getSwingAnimation(weapon.template, null, slot));
DispatchManager.sendToAllInRange(target, cmm);
setAutoAttackJob(attacker, slot, delay);
return;
@@ -507,15 +479,6 @@ public enum CombatManager {
}
TargetedActionMsg cmm = new TargetedActionMsg(attacker, target, (float) damage, attackAnim);
DispatchManager.sendToAllInRange(target, cmm);
//siege projectile is sent once per hit, not per AI pulse
if (attacker.getObjectType().equals(mbEnums.GameObjectType.Mob) && ((Mob) attacker).isSiege()
&& target.getObjectType().equals(mbEnums.GameObjectType.Building)) {
PowerProjectileMsg ppm = new PowerProjectileMsg(attacker, target);
ppm.setRange(50);
DispatchManager.dispatchMsgToInterestArea(attacker, ppm, mbEnums.DispatchChannel.SECONDARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
}
}
}
@@ -579,14 +542,13 @@ public enum CombatManager {
target.setCombatTarget(attacker);
}
public static int getSwingAnimation(CObjectTemplate wb, DeferredPowerJob dpj, mbEnums.EquipSlotType slot) {
public static int getSwingAnimation(ItemTemplate wb, DeferredPowerJob dpj, mbEnums.EquipSlotType slot) {
//No weapon, return default animation
if (wb == null)
return 75;
int token;
engine.parsers.objects.ItemTemplate.Weapon weapon = engine.parsers.objects.ItemTemplate.getWeapon(wb.getTemplateId());
if (dpj != null) {
@@ -597,7 +559,7 @@ public enum CombatManager {
}
//Item has no equipment slots and should not try to return an animation, return default instead
if (wb.getItemEqSlotsOr().isEmpty()) {
if (wb.item_eq_slots_or == null || wb.item_eq_slots_or.isEmpty()) {
return 75;
}
@@ -606,18 +568,18 @@ public enum CombatManager {
int random;
//Item can only be equipped in one slot, return animation for that slot
if (wb.getItemEqSlotsOr().size() == 1) {
if (wb.getItemEqSlotsOr().iterator().next().equals(mbEnums.EquipSlotType.RHELD)) {
anim = weapon.weapon_attack_anim_right.get(0)[0];
if (wb.item_eq_slots_or.size() == 1) {
if (wb.item_eq_slots_or.iterator().next().equals(mbEnums.EquipSlotType.RHELD)) {
anim = wb.weapon_attack_anim_right.get(0)[0];
if (dpj != null) {
random = ThreadLocalRandom.current().nextInt(weapon.weapon_attack_anim_right.size());
anim = weapon.weapon_attack_anim_right.get(random)[0];
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_right.size());
anim = wb.weapon_attack_anim_right.get(random)[0];
}
} else {
anim = weapon.weapon_attack_anim_left.get(0)[0];
anim = wb.weapon_attack_anim_left.get(0)[0];
if (dpj != null) {
random = ThreadLocalRandom.current().nextInt(weapon.weapon_attack_anim_left.size());
anim = weapon.weapon_attack_anim_left.get(random)[0];
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_left.size());
anim = wb.weapon_attack_anim_left.get(random)[0];
}
}
return anim;
@@ -625,16 +587,16 @@ public enum CombatManager {
//Item can be equipped in either hand, and should have animation sets for each hand
if (slot.equals(mbEnums.EquipSlotType.RHELD)) {
anim = weapon.weapon_attack_anim_right.get(0)[0];
anim = wb.weapon_attack_anim_right.get(0)[0];
if (dpj != null) {
random = ThreadLocalRandom.current().nextInt(weapon.weapon_attack_anim_right.size());
anim = weapon.weapon_attack_anim_right.get(random)[0];
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_right.size());
anim = wb.weapon_attack_anim_right.get(random)[0];
}
} else {
anim = weapon.weapon_attack_anim_left.get(0)[0];
anim = wb.weapon_attack_anim_left.get(0)[0];
if (dpj != null) {
random = ThreadLocalRandom.current().nextInt(weapon.weapon_attack_anim_left.size());
anim = weapon.weapon_attack_anim_left.get(random)[0];
random = ThreadLocalRandom.current().nextInt(wb.weapon_attack_anim_left.size());
anim = wb.weapon_attack_anim_left.get(random)[0];
}
}
return anim;
@@ -674,76 +636,6 @@ public enum CombatManager {
}
public static float getNaturalAttackSpeed(AbstractCharacter attacker, mbEnums.EquipSlotType slot) {
// Returns the rune natural attack speed (x100 ms) for this hand, or 0 if the rune has none.
float[] attack = getNaturalAttack(attacker, slot);
if (attack == null || attack.length < 1)
return 0;
return attack[0];
}
public static float getNaturalAttackRange(AbstractCharacter attacker, mbEnums.EquipSlotType slot) {
// Returns the rune natural attack range for this hand, or 0 if the rune has none.
float[] attack = getNaturalAttack(attacker, slot);
if (attack == null || attack.length < 2)
return 0;
return attack[1];
}
public static float getSiegeRange(Mob siegeEngine) {
// Siege engines use the range from their rune natural attack (350 for all three), 300 if the rune has none.
float range = getNaturalAttackRange(siegeEngine, mbEnums.EquipSlotType.RHELD);
if (range <= 0)
return 300;
return range;
}
public static float[] getNaturalAttack(AbstractCharacter attacker, mbEnums.EquipSlotType slot) {
// Returns the rune natural attack entry for this hand, or null if the rune has none.
// Mobs use their mobbase rune, players use their race rune.
int runeID;
RuneTemplate rune;
int hand = slot.equals(mbEnums.EquipSlotType.LHELD) ? 2 : 1;
switch (attacker.getObjectType()) {
case Mob:
runeID = ((Mob) attacker).loadID;
break;
case PlayerCharacter:
runeID = ((PlayerCharacter) attacker).getRaceID();
break;
default:
return null;
}
rune = RuneTemplate._runes.get(runeID);
if (rune == null || rune.rune_naturalattacks.isEmpty())
return null;
for (float[] attack : rune.rune_naturalattacks)
if (attack.length > 3 && (int) attack[3] == hand)
return attack;
// No entry for this hand, fall back to the first natural attack
return rune.rune_naturalattacks.get(0);
}
public static int calculatePetDamage(AbstractCharacter agent) {
//damage calc for pet
float range;
@@ -75,7 +75,6 @@ public enum ConfigManager {
// Mobile AI modifiers
MB_AI_CAST_FREQUENCY,
MB_AI_AGGRO_RANGE,
MB_MINION_SPAWN_TIME,
//drop rates
MB_NORMAL_EXP_RATE,
@@ -101,7 +101,6 @@ public enum DevCmdManager {
DevCmdManager.registerDevCmd(new SetAdminRuneCmd());
DevCmdManager.registerDevCmd(new SetInvulCmd());
DevCmdManager.registerDevCmd(new MakeItemCmd());
DevCmdManager.registerDevCmd(new FillCmd());
DevCmdManager.registerDevCmd(new SetSubRaceCmd());
// Admin
+9 -16
View File
@@ -15,8 +15,8 @@ import engine.mbEnums;
import engine.net.client.msg.ItemProductionMsg;
import engine.objects.City;
import engine.objects.Item;
import engine.objects.ItemTemplate;
import engine.objects.NPC;
import engine.parsers.objects.CObjectTemplate;
import engine.powers.EffectsBase;
import org.pmw.tinylog.Logger;
@@ -49,9 +49,6 @@ public enum ForgeManager implements Runnable {
public static final ConcurrentHashMap<NPC, ConcurrentHashMap.KeySetView<WorkOrder, Boolean>> vendorWorkOrderLookup = new ConcurrentHashMap<>();
public static final ConcurrentHashMap<Item, WorkOrder> itemWorkOrderLookup = new ConcurrentHashMap<>();
// Server-only data from static_vendor_items; the client templates have no mod table.
public static HashMap<Integer, Integer> vendorModTables = new HashMap<>();
public static void start() {
Thread forgeManager;
@@ -225,12 +222,12 @@ public enum ForgeManager implements Runnable {
// Calculate production cost for a single run of the workOrder
HashMap<mbEnums.ResourceType, Integer> production_cost = new HashMap<>();
CObjectTemplate template = CObjectTemplate.lookup(workOrder.templateID);
ItemTemplate template = ItemTemplate.templates.get(workOrder.templateID);
// Add gold and resource costs from template
production_cost.put(mbEnums.ResourceType.GOLD, template.getItemValue());
production_cost.putAll(template.getItemResourceCosts());
production_cost.put(mbEnums.ResourceType.GOLD, template.item_value);
production_cost.putAll(template.item_resource_cost);
// Calculate cost of prefix and suffix
@@ -251,8 +248,8 @@ public enum ForgeManager implements Runnable {
// Create new virtual item from specified template
ItemTemplate template = ItemTemplate.templates.get(workOrder.templateID);
Item forgedItem = new Item(workOrder.templateID);
int modTable = getVendorModTable(workOrder.templateID);
// forgedItem gets a negative id; a virtual item which is not persisted
@@ -267,13 +264,13 @@ public enum ForgeManager implements Runnable {
// Assign a prefix and suffix to this item if random rolled
if (workOrder.prefixToken == 0 && workOrder.vendor.getItemModTable().contains(modTable))
forgedItem.prefixToken = calcRandomMod(workOrder.vendor, mbEnums.ItemModType.PREFIX, modTable);
if (workOrder.prefixToken == 0 && workOrder.vendor.getItemModTable().contains((template.modTable)))
forgedItem.prefixToken = calcRandomMod(workOrder.vendor, mbEnums.ItemModType.PREFIX, template.modTable);
else
forgedItem.prefixToken = workOrder.prefixToken;
if (workOrder.suffixToken == 0 && workOrder.vendor.getItemModTable().contains(modTable))
forgedItem.suffixToken = calcRandomMod(workOrder.vendor, mbEnums.ItemModType.SUFFIX, modTable);
if (workOrder.suffixToken == 0 && workOrder.vendor.getItemModTable().contains((template.modTable)))
forgedItem.suffixToken = calcRandomMod(workOrder.vendor, mbEnums.ItemModType.SUFFIX, template.modTable);
else
forgedItem.suffixToken = workOrder.suffixToken;
@@ -367,10 +364,6 @@ public enum ForgeManager implements Runnable {
DbManager.WarehouseQueries.WRITE_WORKORDER(workOrder);
}
public static int getVendorModTable(int templateID) {
return vendorModTables.getOrDefault(templateID, 0);
}
public static int calcRandomMod(NPC vendor, mbEnums.ItemModType itemModType, int modTable) {
// Random prefix or suffix token based on item.template.modtable
+1 -1
View File
@@ -307,7 +307,7 @@ public enum GroupManager {
return false;
}
if (!item.template.getItemType().equals(mbEnums.ItemType.GOLD)) //only split goldItem
if (!item.template.item_type.equals(mbEnums.ItemType.GOLD)) //only split goldItem
return false;
Group group = getGroup(pc);
+5 -5
View File
@@ -16,7 +16,7 @@ import engine.net.client.ClientConnection;
import engine.net.client.msg.guild.AcceptInviteToGuildMsg;
import engine.net.client.msg.guild.GuildInfoMsg;
import engine.objects.*;
import org.joda.time.DateTime;
import java.time.Instant;
public enum GuildManager {
@@ -67,8 +67,8 @@ public enum GuildManager {
return false;
if (playerCharacter.getGuild() != null && !playerCharacter.getGuild().isEmptyGuild()) {
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(playerCharacter.getGuildUUID(), playerCharacter, DateTime.now(), GuildHistoryType.LEAVE)) {
GuildHistory guildHistory = new GuildHistory(playerCharacter.getGuildUUID(), playerCharacter.getGuild().getName(), DateTime.now(), GuildHistoryType.LEAVE);
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(playerCharacter.getGuildUUID(), playerCharacter, Instant.now(), GuildHistoryType.LEAVE)) {
GuildHistory guildHistory = new GuildHistory(playerCharacter.getGuildUUID(), playerCharacter.getGuild().getName(), Instant.now(), GuildHistoryType.LEAVE);
playerCharacter.getGuildHistory().add(guildHistory);
}
}
@@ -90,8 +90,8 @@ public enum GuildManager {
dispatch = Dispatch.borrow(playerCharacter, msg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
}
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(guild.getObjectUUID(), playerCharacter, DateTime.now(), historyType)) {
GuildHistory guildHistory = new GuildHistory(guild.getObjectUUID(), guild.getName(), DateTime.now(), historyType);
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(guild.getObjectUUID(), playerCharacter, Instant.now(), historyType)) {
GuildHistory guildHistory = new GuildHistory(guild.getObjectUUID(), guild.getName(), Instant.now(), historyType);
playerCharacter.getGuildHistory().add(guildHistory);
}
+54 -35
View File
@@ -2,7 +2,6 @@ package engine.gameManager;
import engine.mbEnums;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import engine.powers.EffectsBase;
import org.pmw.tinylog.Logger;
@@ -22,46 +21,66 @@ public enum ItemManager {
public static final AtomicInteger lastNegativeID = new AtomicInteger(0);
// restrict true: the set is a blacklist; false: a whitelist. An empty set allows everyone.
public static Boolean ValidRace(Item item, mbEnums.MonsterType race) {
EnumSet<mbEnums.MonsterType> races = item.template.getItemRaceReq();
boolean restrict = item.template.getItemRaceReqRestrict();
if (races.isEmpty())
if (item.template.item_race_req.isEmpty() && item.template.item_race_res.isEmpty())
return true;
return races.contains(race) != restrict;
if (item.template.item_race_req.isEmpty() == false)
if (item.template.item_race_req.contains(race))
return true;
if (item.template.item_race_res.isEmpty() == false)
if (item.template.item_race_res.contains(race) == false)
return true;
return false;
}
public static Boolean ValidClass(Item item, mbEnums.ClassType base, mbEnums.ClassType profession) {
EnumSet<mbEnums.ClassType> classes = item.template.getItemClassReq();
boolean restrict = item.template.getItemClassReqRestrict();
boolean listed;
// Early exit if no entry
if (classes.isEmpty())
if (item.template.item_class_req.isEmpty() && item.template.item_class_res.isEmpty())
return true;
listed = classes.contains(base) || classes.contains(profession);
if (item.template.item_class_req.isEmpty() == false)
if (item.template.item_class_req.contains(base) || item.template.item_class_req.contains(profession))
return true;
return listed != restrict;
if (item.template.item_class_res.isEmpty() == false)
if (item.template.item_class_res.contains(base) == false && item.template.item_class_res.contains(profession) == false)
return true;
return false;
}
public static Boolean ValidDiscipline(Item item, EnumSet<mbEnums.DisciplineType> discs) {
EnumSet<mbEnums.DisciplineType> disciplines = item.template.getItemDiscReq();
boolean restrict = item.template.getItemDiscReqRestrict();
EnumSet<mbEnums.DisciplineType> workSet;
// Early exit if no entry
if (disciplines.isEmpty())
if (item.template.item_disc_req.isEmpty() && item.template.item_disc_res.isEmpty())
return true;
workSet = EnumSet.copyOf(discs);
workSet.retainAll(disciplines);
EnumSet<mbEnums.DisciplineType> workSet = EnumSet.copyOf(discs);
return workSet.isEmpty() == restrict;
if (item.template.item_disc_req.isEmpty() == false) {
workSet.retainAll(item.template.item_disc_req);
if (workSet.isEmpty() == false)
return true;
}
if (item.template.item_disc_res.isEmpty() == false) {
workSet.retainAll(item.template.item_disc_res);
if (workSet.isEmpty() == false)
return true;
}
return false;
}
public static Boolean canCharacterEquip(Item item, AbstractCharacter character) {
@@ -72,12 +91,12 @@ public enum ItemManager {
CharacterSkill characterSkill;
if (item.template.getItemSkillReq().isEmpty())
if (item.template.item_skill_required.isEmpty())
return true;
for (String skillRequired : item.template.getItemSkillReq().keySet()) {
for (String skillRequired : item.template.item_skill_required.keySet()) {
int required_value = item.template.getItemSkillReq().get(skillRequired);
int required_value = item.template.item_skill_required.get(skillRequired);
characterSkill = skills.get(skillRequired);
if (characterSkill == null)
@@ -93,31 +112,31 @@ public enum ItemManager {
public static boolean isTwoHanded(Item item) {
if (!item.template.getItemType().equals(mbEnums.ItemType.WEAPON))
if (!item.template.item_type.equals(mbEnums.ItemType.WEAPON))
return false;
return item.template.getItemEqSlotsAnd().containsAll(EnumSet.of(mbEnums.EquipSlotType.LHELD, mbEnums.EquipSlotType.RHELD));
return item.template.item_eq_slots_and.contains(EnumSet.of(mbEnums.EquipSlotType.LHELD, mbEnums.EquipSlotType.RHELD));
}
public static boolean isTwoHanded(CObjectTemplate template) {
public static boolean isTwoHanded(ItemTemplate template) {
if (!template.getItemType().equals(mbEnums.ItemType.WEAPON))
if (!template.item_type.equals(mbEnums.ItemType.WEAPON))
return false;
return template.getItemEqSlotsAnd().containsAll(EnumSet.of(mbEnums.EquipSlotType.LHELD, mbEnums.EquipSlotType.RHELD));
return template.item_eq_slots_and.contains(EnumSet.of(mbEnums.EquipSlotType.LHELD, mbEnums.EquipSlotType.RHELD));
}
public static boolean isShield(Item item) {
if (item.template.getItemSkillReq().containsKey("Block"))
if (item.template.item_skill_required.containsKey("Block"))
return true;
return false;
}
public static boolean isShield(CObjectTemplate template) {
public static boolean isShield(ItemTemplate template) {
if (template.getItemSkillReq().containsKey("Block"))
if (template.item_skill_required.containsKey("Block"))
return true;
return false;
@@ -131,7 +150,7 @@ public enum ItemManager {
return false;
//Item not valid for slot
if (item.template.getItemEqSlotsOr().contains(slot) == false)
if (item.template.item_eq_slots_or.contains(slot) == false)
return false;
// Slot is taken
@@ -146,7 +165,7 @@ public enum ItemManager {
(slot == mbEnums.EquipSlotType.RHELD && equipped.get(mbEnums.EquipSlotType.LHELD) != null)))
return false;
if (item.template.getItemType().equals(mbEnums.ItemType.WEAPON))
if (item.template.item_type.equals(mbEnums.ItemType.WEAPON))
if (equipped.get(slot) != null && equipped.get(slot).equals(item) == false)
return false;
@@ -178,7 +197,7 @@ public enum ItemManager {
//players can't wear 0 value items.
return item.template.getItemValue() != 0 || Kit.IsNoobGear(item.templateID);
return item.template.item_value != 0 || Kit.IsNoobGear(item.templateID);
}
+8 -9
View File
@@ -13,7 +13,6 @@ import engine.mbEnums;
import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
@@ -92,8 +91,8 @@ public enum LootManager {
//lastly, check mobs inventory for godly or disc runes to send a server announcement
for (Item item : mob.getInventory()) {
if ((item.templateID > 2499 && item.templateID <= 3050) || item.template.getItemBaseName().toLowerCase().contains("of the gods")) {
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().zoneName + " has found the " + item.template.getItemBaseName() + ". Are you tough enough to take it?");
if ((item.templateID > 2499 && item.templateID <= 3050) || item.template.item_base_name.toLowerCase().contains("of the gods")) {
ChatSystemMsg chatMsg = new ChatSystemMsg(null, mob.getName() + " in " + mob.getParentZone().zoneName + " has found the " + item.template.item_base_name + ". Are you tough enough to take it?");
chatMsg.setMessageType(10);
chatMsg.setChannel(mbEnums.ChatChannelType.SYSTEM.getChannelID());
DispatchManager.dispatchMsgToAll(chatMsg);
@@ -180,12 +179,12 @@ public enum LootManager {
if (itemUUID == 0)
return null;
if (CObjectTemplate.lookup(itemUUID).getItemType().equals(mbEnums.ItemType.RESOURCE)) {
if (ItemTemplate.templates.get(itemUUID).item_type.equals(mbEnums.ItemType.RESOURCE)) {
int amount = ThreadLocalRandom.current().nextInt(tableRow.minSpawn, tableRow.maxSpawn + 1);
return new MobLoot(mob, CObjectTemplate.lookup(itemUUID), amount, false);
return new MobLoot(mob, ItemTemplate.templates.get(itemUUID), amount, false);
}
outItem = new MobLoot(mob, CObjectTemplate.lookup(itemUUID), false);
outItem = new MobLoot(mob, ItemTemplate.templates.get(itemUUID), false);
if (selectedRow.pModTable != 0)
try {
@@ -375,7 +374,7 @@ public enum LootManager {
if (chanceRoll > bse.dropChance)
return;
MobLoot lootItem = new MobLoot(mob, CObjectTemplate.lookup(bse.templateID), true);
MobLoot lootItem = new MobLoot(mob, ItemTemplate.templates.get(bse.templateID), true);
if (lootItem != null)
mob.charItemManager.addItemToInventory(lootItem);
@@ -423,14 +422,14 @@ public enum LootManager {
//create the item from the table, quantity is always 1
MobLoot winnings = new MobLoot(playerCharacter, CObjectTemplate.lookup(selectedItem.templateID), 1, false);
MobLoot winnings = new MobLoot(playerCharacter, ItemTemplate.templates.get(selectedItem.templateID), 1, false);
if (winnings == null)
return;
//early exit if the inventory of the player will not old the item
if (itemMan.hasRoomInventory(winnings.template.getItemWt()) == false) {
if (itemMan.hasRoomInventory(winnings.template.item_wt) == false) {
ErrorPopupMsg.sendErrorPopup(playerCharacter, 21);
return;
}
+21 -31
View File
@@ -19,14 +19,12 @@ import engine.net.client.ClientConnection;
import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.PetMsg;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import engine.powers.EffectsBase;
import engine.powers.RuneSkillAdjustEntry;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
@@ -317,26 +315,26 @@ public enum NPCManager {
//has main hand weapon
Item weapon = guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD);
if (engine.parsers.objects.ItemTemplate._items.get(weapon.templateID).item_primary_attr == mbEnums.AttributeType.Strength)
if (weapon.template.item_primary_attr.equals(mbEnums.AttributeType.Strength))
primaryStat = guard.getStatStrCurrent();
else
primaryStat = guard.getStatDexCurrent();
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin() + engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_damage.get(0).damage_min) * rankModifier) + primaryStat;
guard.maxDamageHandOne = (int) ((guard.mobBase.getDamageMax() + engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_damage.get(0).damage_max) * rankModifier) + primaryStat;
guard.speedHandOne = engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_wepspeed;
guard.rangeHandOne = engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_max_range;
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin() + weapon.template.item_weapon_damage.values().iterator().next()[0]) * rankModifier) + primaryStat;
guard.maxDamageHandOne = (int) ((guard.mobBase.getDamageMax() + weapon.template.item_weapon_damage.values().iterator().next()[1]) * rankModifier) + primaryStat;
guard.speedHandOne = weapon.template.item_weapon_wepspeed;
guard.rangeHandOne = weapon.template.item_weapon_max_range;
} else if (guard.charItemManager.equipped.containsKey(mbEnums.EquipSlotType.LHELD) && !ItemManager.isShield(guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template)) {
//has off hand weapon
Item weapon = guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD);
if (engine.parsers.objects.ItemTemplate._items.get(weapon.templateID).item_primary_attr == mbEnums.AttributeType.Strength)
if (weapon.template.item_primary_attr.equals(mbEnums.AttributeType.Strength))
primaryStat = guard.getStatStrCurrent();
else
primaryStat = guard.getStatDexCurrent();
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin() + engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_damage.get(0).damage_min) * rankModifier) + primaryStat;
guard.maxDamageHandOne = (int) ((guard.mobBase.getDamageMax() + engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_damage.get(0).damage_max) * rankModifier) + primaryStat;
guard.speedHandOne = engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_wepspeed;
guard.rangeHandOne = engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_max_range;
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin() + weapon.template.item_weapon_damage.values().iterator().next()[0]) * rankModifier) + primaryStat;
guard.maxDamageHandOne = (int) ((guard.mobBase.getDamageMax() + weapon.template.item_weapon_damage.values().iterator().next()[1]) * rankModifier) + primaryStat;
guard.speedHandOne = weapon.template.item_weapon_wepspeed;
guard.rangeHandOne = weapon.template.item_weapon_max_range;
} else {
primaryStat = guard.getStatStrCurrent();
guard.minDamageHandOne = (int) ((guard.mobBase.getDamageMin()) * rankModifier) + primaryStat;
@@ -354,8 +352,8 @@ public enum NPCManager {
int baseDef = guard.mobBase.getDefenseRating();
int armorDefense = 0;
for (Item equipped : guard.charItemManager.equipped.values())
if (equipped.template.getItemType().equals(mbEnums.ItemType.ARMOR) || ItemManager.isShield(equipped.template))
armorDefense += engine.parsers.objects.ItemTemplate._items.get(equipped.templateID).item_defense_rating;
if (equipped.template.item_type.equals(mbEnums.ItemType.ARMOR) || ItemManager.isShield(equipped.template))
armorDefense += equipped.template.item_defense_rating;
guard.defenseRating = dexterity + baseDef + armorDefense;
}
@@ -363,9 +361,9 @@ public enum NPCManager {
int strength = guard.getStatStrCurrent();
int baseAtr = guard.mobBase.getAttackRating();
if (guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD) != null)
guard.atrHandOne = baseAtr + (int) ((strength * 0.5f) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD).template.getItemSkillReq().values().toArray()[0] * 4) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD).template.getItemSkillReq().values().toArray()[0] * 3));
guard.atrHandOne = baseAtr + (int) ((strength * 0.5f) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD).template.item_skill_required.values().toArray()[0] * 4) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.RHELD).template.item_skill_required.values().toArray()[0] * 3));
else if (guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD) != null && !ItemManager.isShield(guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template))
guard.atrHandTwo = baseAtr + (int) ((strength * 0.5f) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template.getItemSkillReq().values().toArray()[0] * 4) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template.getItemSkillReq().values().toArray()[0] * 3));
guard.atrHandTwo = baseAtr + (int) ((strength * 0.5f) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template.item_skill_required.values().toArray()[0] * 4) + ((int) guard.charItemManager.equipped.get(mbEnums.EquipSlotType.LHELD).template.item_skill_required.values().toArray()[0] * 3));
else
guard.atrHandOne = baseAtr;
}
@@ -440,17 +438,14 @@ public enum NPCManager {
public static void applyEquipmentResists(Mob mob) {
EnumMap<mbEnums.DamageType, Float> armorResists;
if (mob.charItemManager.equipped.isEmpty())
return;
for (Item equipped : mob.charItemManager.equipped.values()) {
if (equipped.template.getItemType().equals(mbEnums.ItemType.ARMOR)) {
armorResists = equipped.template.getCombatAttackResist();
mob.resists.setResist(mbEnums.DamageType.SLASHING, mob.resists.getResist(mbEnums.DamageType.SLASHING, 0) + armorResists.getOrDefault(mbEnums.DamageType.SLASHING, 0f));
mob.resists.setResist(mbEnums.DamageType.CRUSHING, mob.resists.getResist(mbEnums.DamageType.CRUSHING, 0) + armorResists.getOrDefault(mbEnums.DamageType.CRUSHING, 0f));
mob.resists.setResist(mbEnums.DamageType.PIERCING, mob.resists.getResist(mbEnums.DamageType.PIERCING, 0) + armorResists.getOrDefault(mbEnums.DamageType.PIERCING, 0f));
if (equipped.template.item_type.equals(mbEnums.ItemType.ARMOR)) {
mob.resists.setResist(mbEnums.DamageType.SLASHING, mob.resists.getResist(mbEnums.DamageType.SLASHING, 0) + equipped.template.combat_attack_resist.get("SLASHING"));
mob.resists.setResist(mbEnums.DamageType.CRUSHING, mob.resists.getResist(mbEnums.DamageType.CRUSHING, 0) + equipped.template.combat_attack_resist.get("CRUSHING"));
mob.resists.setResist(mbEnums.DamageType.PIERCING, mob.resists.getResist(mbEnums.DamageType.PIERCING, 0) + equipped.template.combat_attack_resist.get("PIERCING"));
}
}
}
@@ -485,11 +480,6 @@ public enum NPCManager {
npc.runes.add(shopkeeper);
if (NPCManager._runeSetMap.containsKey(npc.runeSetID)) {
for (int runeID : _runeSetMap.get(npc.runeSetID)) {
// Shopkeeper is already applied above and most rune sets repeat it
if (runeID == 252620)
continue;
RuneBase rb = RuneBase.getRuneBase(runeID);
if (rb != null) {
CharacterRune toApply = new CharacterRune(rb, npc.getObjectUUID());
@@ -546,14 +536,14 @@ public enum NPCManager {
public static long calcRollingDuration(NPC vendor, int templateID) {
CObjectTemplate template = CObjectTemplate.lookup(templateID);
ItemTemplate template = ItemTemplate.templates.get(templateID);
float rollingDuration;
if (template == null)
return 0;
if (template.getItemBaneRank() > 0)
return (long) (template.getItemBaneRank() * 60 * 60 * 3 * 1000 * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue()));
if (template.item_bane_rank > 0)
return (long) (template.item_bane_rank * 60 * 60 * 3 * 1000 * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue()));
if (vendor.building == null)
return 600;
+3 -3
View File
@@ -2255,12 +2255,12 @@ public enum PowersManager {
if (pb.targetItem())
return true;
// TODO add these checks later
else if (pb.targetArmor() && item.template.getItemType().equals(ItemType.ARMOR))
else if (pb.targetArmor() && item.template.item_type.equals(ItemType.ARMOR))
return true;
else if (pb.targetJewelry() && item.template.getItemType().equals(ItemType.JEWELRY))
else if (pb.targetJewelry() && item.template.item_type.equals(ItemType.JEWELRY))
return true;
else
return pb.targetWeapon() && item.template.getItemType().equals(ItemType.WEAPON);
return pb.targetWeapon() && item.template.item_type.equals(ItemType.WEAPON);
} // How did we get here? all valid targets have been covered
else
return false;
+3 -6
View File
@@ -11,7 +11,7 @@ package engine.jobs;
import engine.job.AbstractScheduleJob;
import engine.objects.Bane;
import org.joda.time.DateTime;
import java.time.LocalDateTime;
public class BaneDefaultTimeJob extends AbstractScheduleJob {
@@ -31,11 +31,8 @@ public class BaneDefaultTimeJob extends AbstractScheduleJob {
return;
}
DateTime defaultTime = new DateTime(this.bane.getPlacementDate());
defaultTime = defaultTime.plusDays(2);
defaultTime = defaultTime.hourOfDay().setCopy(22);
defaultTime = defaultTime.minuteOfHour().setCopy(0);
defaultTime = defaultTime.secondOfMinute().setCopy(0);
LocalDateTime defaultTime = this.bane.getPlacementDate()
.plusDays(2).withHour(22).withMinute(0).withSecond(0).withNano(0);
this.bane.setLiveDate(defaultTime);
}
+4 -4
View File
@@ -12,9 +12,9 @@ import engine.gameManager.DbManager;
import engine.gameManager.ForgeManager;
import engine.mbEnums;
import engine.objects.Item;
import engine.objects.ItemTemplate;
import engine.objects.NPC;
import engine.objects.Warehouse;
import engine.parsers.objects.CObjectTemplate;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -127,16 +127,16 @@ public class WorkOrder implements Delayed {
int validation_result = 0;
CObjectTemplate template = CObjectTemplate.lookup(workOrder.templateID);
ItemTemplate template = ItemTemplate.templates.get(workOrder.templateID);
if (workOrder.vendor.getBuilding() == null)
return 58; //58: The formula is beyond the means of this facility
if (!workOrder.vendor.charItemManager.hasRoomInventory(template.getItemWt()))
if (!workOrder.vendor.charItemManager.hasRoomInventory(template.item_wt))
return 30; //30: That person cannot carry that item
if ((workOrder.prefixToken != 0 || workOrder.suffixToken != 0) &&
!workOrder.vendor.getItemModTable().contains(ForgeManager.getVendorModTable(workOrder.templateID)))
!workOrder.vendor.getItemModTable().contains((template.modTable)))
return 59; //59: This hireling does not have this formula
if (!Warehouse.calcCostOverrun(workOrder).isEmpty())
+30
View File
@@ -583,6 +583,36 @@ final public class FastMath {
return ret.normalize();
}
/**
* Turns a String into an Integer hash that the client will recognize.
*
* @param s The String to hash
* @return the Integer hash
*/
public static int hash(String s) {
int out = 0, pad = 0;
for (char c : s.toCharArray()) {
if (c == ' ' || c == '\\') {
pad += 5;
continue;
}
if (c > 0x40 && c < 0x60)
out ^= _rotl((byte) 0x60, pad);
out ^= _rotl((byte) (c & 0xDF), pad);
pad += 5;
}
return out;
}
/**
* Utility function for making hashes
*/
private static int _rotl(int value, int shift) {
if ((shift &= 31) == 0)
return value;
return (value << shift) | (value >> (32 - shift));
}
/**
* Gets number of seconds until next hours
*/
+23 -30
View File
@@ -15,6 +15,7 @@ import engine.math.Vector2f;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.objects.AbstractCharacter;
import engine.objects.ItemTemplate;
import engine.objects.Shrine;
import engine.objects.Zone;
import engine.powers.EffectsBase;
@@ -823,7 +824,6 @@ public class mbEnums {
ACID,
DISEASE,
UNKNOWN,
ANTISIEGE,
// these added for immunities
ATTACK,
POWERS,
@@ -842,26 +842,34 @@ public class mbEnums {
public static DamageType getDamageType(String modName) {
String name;
if (modName.isEmpty())
return DamageType.NONE;
// Client and DB strings vary in case and punctuation ("Fire", "Anti-Siege")
if(modName.toLowerCase().equals("blind"))
modName = "BLINDNESS";
name = modName.replaceAll("[\\s,-]", "").toUpperCase();
if(modName.toLowerCase().equals("powerblock"))
modName = "POWERINHIBITOR";
if (name.equals("BLIND"))
name = "BLINDNESS";
//validity check for not looking up damage type that doesn't exist
boolean valid = false;
for(DamageType type : DamageType.values()){
if(type.name().equals(modName))
valid = true;
}
if (name.equals("POWERBLOCK"))
name = "POWERINHIBITOR";
if(!valid)
return DamageType.NONE;
for (DamageType type : DamageType.values())
if (type.name().equals(name))
return type;
DamageType damageType;
return DamageType.NONE;
try {
damageType = DamageType.valueOf(modName.replace(",", "").toUpperCase());
} catch (Exception e) {
Logger.error(e);
return DamageType.NONE;
}
return damageType;
}
}
@@ -1501,15 +1509,6 @@ public class mbEnums {
}
}
// rune_type values from the client cache data (COBJECTS/RUNE)
public enum RuneType {
CLASS,
DISCIPLINE,
RACE,
TALENT
}
public enum ShrineType {
Aelfborn(1701900, -75506007, true),
@@ -2762,6 +2761,7 @@ public class mbEnums {
public static HashMap<Integer, ResourceType> templateHashLookup = new HashMap<>();
public static HashMap<Integer, ResourceType> resourceHashLookup = new HashMap<>();
public int templateID;
public ItemTemplate template;
public int resourceHash;
public int templateHash;
public int deposit_limit;
@@ -2769,6 +2769,7 @@ public class mbEnums {
ResourceType(int templateID, int resourceHash, int templateHash, int deposit_limit, int mine_production) {
this.templateID = templateID;
this.template = ItemTemplate.templates.get(this.templateID);
this.resourceHash = resourceHash;
this.templateHash = templateHash;
this.deposit_limit = deposit_limit;
@@ -2907,14 +2908,6 @@ public class mbEnums {
EMPTY_NEWITEM;
}
// Cache JSON names. UNKNOWN is raw 0, which the client treats as no slot (sb.exe 0x4AC810).
public enum SheathSlot {
UNKNOWN,
BACK,
WAIST,
NONE
}
public enum AttributeType {
None,
Strength,
+56 -50
View File
@@ -14,10 +14,12 @@ import engine.gameManager.*;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import engine.mbEnums.DispatchChannel;
import engine.mobileAI.Threads.MobAIThread;
import engine.mobileAI.Threads.ReSpawner;
import engine.mobileAI.utilities.MovementUtilities;
import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.PowerProjectileMsg;
import engine.objects.*;
import engine.powers.ActionsBase;
import engine.powers.PowersBase;
@@ -44,11 +46,6 @@ public class MobAI {
//
// CombatManager.class implements shared combat routines for all avatars.
// Pet aggro scan in checkForAggro stays off until it checks rune enemy lists,
// filters its targets and keeps pet targets (MBDATA/docs/plan-mask-pet.md steps 2-4).
private static final boolean PET_AGGRO_ENABLED = false;
private static void attackTarget(Mob mob, AbstractWorldObject target) {
try {
@@ -96,7 +93,7 @@ public class MobAI {
mob.updateLocation();
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage());
}
}
@@ -115,9 +112,7 @@ public class MobAI {
if (mob.behaviourType.callsForHelp)
mobCallForHelp(mob);
// siege engines drop targets on their own attack range in determineAction
if (!mob.isSiege() && !MovementUtilities.inRangeDropAggro(mob, target)) {
if (!MovementUtilities.inRangeDropAggro(mob, target)) {
mob.setCombatTarget(null);
return;
}
@@ -138,7 +133,7 @@ public class MobAI {
target.getPet().setCombatTarget(mob);
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackPlayer");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackPlayer" + " " + e.getMessage());
}
}
@@ -160,10 +155,20 @@ public class MobAI {
if (guard.getCombatTarget() == null && !guard.getGuild().equals(mob.getGuild()))
guard.setCombatTarget(mob);
if (mob.isSiege())
MovementManager.sendRWSSMsg(mob);
CombatManager.combatCycle(mob, target);
if (mob.isSiege()) {
PowerProjectileMsg ppm = new PowerProjectileMsg(mob, target);
ppm.setRange(50);
DispatchManager.dispatchMsgToInterestArea(mob, ppm, DispatchChannel.SECONDARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackBuilding");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackBuilding" + " " + e.getMessage());
}
}
@@ -181,7 +186,7 @@ public class MobAI {
CombatManager.combatCycle(mob, target);
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackMob");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackMob" + " " + e.getMessage());
}
}
@@ -243,7 +248,7 @@ public class MobAI {
MovementUtilities.aiMove(mob, mob.destination, true);
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: Patrol");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage());
}
}
@@ -285,7 +290,7 @@ public class MobAI {
return mob.nextCastTime <= System.currentTimeMillis();
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: canCast");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: canCast" + " " + e.getMessage());
}
return false;
}
@@ -382,7 +387,7 @@ public class MobAI {
return true;
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCast" + " " + e.getMessage());
}
return false;
}
@@ -447,7 +452,7 @@ public class MobAI {
mob.nextCallForHelp = System.currentTimeMillis() + 60000;
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCallForHelp");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCallForHelp" + " " + e.getMessage());
}
}
@@ -513,16 +518,7 @@ public class MobAI {
boolean bypassLoadedPlayerCheck = false;
if (mob.isPlayerGuard() || mob.isSiege()) {
bypassLoadedPlayerCheck = true;
if (mob.isSiege()) {
// siege engines hold a character target until it dies or leaves their attack range
if (mob.combatTarget != null && AbstractCharacter.IsAbstractCharacter(mob.combatTarget))
if (mob.combatTarget.loc.distanceSquared(mob.loc) > mob.getRange() * mob.getRange())
mob.setCombatTarget(null);
} else if (mob.combatTarget != null && mob.combatTarget.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter))
if (mob.combatTarget != null && mob.combatTarget.getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter))
if (mob.combatTarget.loc.distanceSquared(mob.loc) > 10000)
mob.setCombatTarget(null);
}
@@ -548,7 +544,7 @@ public class MobAI {
PlayerCharacter target = (PlayerCharacter) mob.getCombatTarget();
if (!mob.isSiege() && !mob.playerAgroMap.containsKey(target.getObjectUUID())) {
if (!mob.playerAgroMap.containsKey(target.getObjectUUID())) {
mob.setCombatTarget(null);
return;
}
@@ -579,7 +575,7 @@ public class MobAI {
break;
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: DetermineAction");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: DetermineAction" + " " + e.getMessage());
}
}
@@ -634,7 +630,7 @@ public class MobAI {
}
}
if (PET_AGGRO_ENABLED && aiAgent.getCombatTarget() == null) {
if (aiAgent.getCombatTarget() == null) {
//look for pets to aggro if no players found to aggro
@@ -653,7 +649,7 @@ public class MobAI {
}
}
} catch (Exception e) {
Logger.error(e, aiAgent.getObjectUUID() + " " + aiAgent.getName() + " Failed At: CheckForAggro");
Logger.info(aiAgent.getObjectUUID() + " " + aiAgent.getName() + " Failed At: CheckForAggro" + " " + e.getMessage());
}
}
@@ -706,7 +702,7 @@ public class MobAI {
}
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckMobMovement");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckMobMovement" + " " + e.getMessage());
}
}
@@ -750,7 +746,7 @@ public class MobAI {
ReSpawner.respawnQueue.put(aiAgent);
}
} catch (Exception e) {
Logger.error(e, aiAgent.getObjectUUID() + " " + aiAgent.getName() + " Failed At: CheckForRespawn");
Logger.info(aiAgent.getObjectUUID() + " " + aiAgent.getName() + " Failed At: CheckForRespawn" + " " + e.getMessage());
}
}
@@ -765,7 +761,7 @@ public class MobAI {
if (mob.getCombatTarget() == null)
return;
if (mob.getCombatTarget().getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter) && !MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) && !mob.agentType.equals(mbEnums.AIAgentType.PET) && !mob.isSiege()) {
if (mob.getCombatTarget().getObjectType().equals(mbEnums.GameObjectType.PlayerCharacter) && !MovementUtilities.inRangeDropAggro(mob, (PlayerCharacter) mob.getCombatTarget()) && !mob.agentType.equals(mbEnums.AIAgentType.PET)) {
mob.setCombatTarget(null);
return;
@@ -773,7 +769,7 @@ public class MobAI {
attackTarget(mob, mob.getCombatTarget());
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckForAttack");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckForAttack" + " " + e.getMessage());
}
}
@@ -816,7 +812,7 @@ public class MobAI {
mob.playerAgroMap.replaceAll((e, v) -> 0f);
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome" + " " + e.getMessage());
}
}
@@ -855,7 +851,7 @@ public class MobAI {
mob.updateMovementState();
mob.updateLocation();
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: chaseTarget");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: chaseTarget" + " " + e.getMessage());
}
}
@@ -881,17 +877,13 @@ public class MobAI {
if (aggroMob.agentType.equals(mbEnums.AIAgentType.PET))
continue;
//don't attack siege engines
if (aggroMob.isSiege())
continue;
if (mob.getLoc().distanceSquared2D(aggroMob.getLoc()) > sqr(50))
continue;
mob.setCombatTarget(aggroMob);
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: SafeGuardAggro");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: SafeGuardAggro" + " " + e.getMessage());
}
}
@@ -921,7 +913,7 @@ public class MobAI {
checkForAttack(mob); //only check to attack if combat target is not null
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardLogic");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardLogic" + " " + e.getMessage());
}
}
@@ -954,7 +946,7 @@ public class MobAI {
mob.setHealth(mob.getHealthMax());
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: PetLogic");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: PetLogic" + " " + e.getMessage());
}
}
@@ -978,7 +970,7 @@ public class MobAI {
}
checkForAttack(mob);
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: HamletGuardLogic");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: HamletGuardLogic" + " " + e.getMessage());
}
}
@@ -1051,7 +1043,7 @@ public class MobAI {
checkForAttack(mob);
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: DefaultLogic");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: DefaultLogic" + " " + e.getMessage());
}
}
@@ -1107,11 +1099,25 @@ public class MobAI {
return;
}
}
if (mob.getCombatTarget() == null) {
// guards never auto-aggro siege engines; they only respond when one damages a city building
//look for siege equipment to aggro if no players found to aggro
HashSet<AbstractWorldObject> awoList = WorldGrid.getObjectsInRangePartial(mob, MobAIThread.AI_BASE_AGGRO_RANGE, MBServerStatics.MASK_SIEGE);
for (AbstractWorldObject awoMob : awoList) {
Mob aggroMob = (Mob) awoMob;
if (guardCanAggro(mob, aggroMob)) {
mob.setCombatTarget(aggroMob);
return;
}
}
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckForPlayerGuardAggro");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckForPlayerGuardAggro" + e.getMessage());
}
}
@@ -1174,7 +1180,7 @@ public class MobAI {
}
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardCanAggro");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: GuardCanAggro" + " " + e.getMessage());
}
return false;
}
@@ -1226,7 +1232,7 @@ public class MobAI {
}
}
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: randomGuardPatrolPoints");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: randomGuardPatrolPoints" + " " + e);
}
}
@@ -1261,7 +1267,7 @@ public class MobAI {
}
return mostHatedTarget;
} catch (Exception e) {
Logger.error(e, mob.getObjectUUID() + " " + mob.getName() + " Failed At: ChangeTargetFromMostHated");
Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: ChangeTargetFromMostHated" + " " + e.getMessage());
}
return null;
}
+9 -8
View File
@@ -12,7 +12,8 @@ package engine.net;
import engine.math.Vector3f;
import engine.math.Vector3fImmutable;
import engine.util.ByteBufferUtils;
import org.joda.time.DateTime;
import java.time.Instant;
import java.time.ZoneId;
import java.nio.ByteBuffer;
import java.time.LocalDateTime;
@@ -57,13 +58,13 @@ public class ByteBufferWriter {
this.bb.putLong(x);
}
public synchronized void putDateTime(DateTime dateTime) {
this.put((byte) dateTime.getDayOfMonth());
this.put((byte) ((byte) dateTime.getMonthOfYear() - 1));
this.putInt(dateTime.getYear() - 1900);
this.put((byte) dateTime.getHourOfDay());
this.put((byte) dateTime.getMinuteOfHour());
this.put((byte) dateTime.getSecondOfDay());
public synchronized void putDateTime(Instant dateTime) {
this.put((byte) dateTime.atZone(ZoneId.systemDefault()).toLocalDate().getDayOfMonth());
this.put((byte) ((byte) dateTime.atZone(ZoneId.systemDefault()).toLocalDate().getMonthValue() - 1));
this.putInt(dateTime.atZone(ZoneId.systemDefault()).toLocalDate().getYear() - 1900);
this.put((byte) dateTime.atZone(ZoneId.systemDefault()).toLocalTime().getHour());
this.put((byte) dateTime.atZone(ZoneId.systemDefault()).toLocalTime().getMinute());
this.put((byte) dateTime.atZone(ZoneId.systemDefault()).toLocalTime().getSecond());
}
public synchronized void putLocalDateTime(LocalDateTime dateTime) {
+2 -2
View File
@@ -14,7 +14,7 @@ import engine.gameManager.ChatManager;
import engine.net.client.ClientConnection;
import engine.objects.PlayerCharacter;
import engine.server.MBServerStatics;
import org.joda.time.DateTime;
import java.time.Instant;
import org.pmw.tinylog.Logger;
import java.lang.reflect.Constructor;
@@ -85,7 +85,7 @@ public class NetMsgFactory {
if (protocolMsg == Protocol.NONE) {
String errorString = DateTime.now().toString() + origin.lastProtocol.name();
String errorString = Instant.now().toString() + origin.lastProtocol.name();
int errorCode = errorString.hashCode();
@@ -22,7 +22,7 @@ import engine.net.client.msg.guild.GuildInfoMsg;
import engine.objects.Guild;
import engine.objects.GuildHistory;
import engine.objects.PlayerCharacter;
import org.joda.time.DateTime;
import java.time.Instant;
public class AcceptInviteToGuildHandler extends AbstractClientMsgHandler {
@@ -90,8 +90,8 @@ public class AcceptInviteToGuildHandler extends AbstractClientMsgHandler {
//Add to guild History
if (player.getGuild() != null) {
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(player.getGuildUUID(), player, DateTime.now(), GuildHistoryType.JOIN)) {
GuildHistory guildHistory = new GuildHistory(player.getGuildUUID(), player.getGuild().getName(), DateTime.now(), GuildHistoryType.JOIN);
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(player.getGuildUUID(), player, Instant.now(), GuildHistoryType.JOIN)) {
GuildHistory guildHistory = new GuildHistory(player.getGuildUUID(), player.getGuild().getName(), Instant.now(), GuildHistoryType.JOIN);
player.getGuildHistory().add(guildHistory);
}
}
@@ -46,7 +46,7 @@ public class ActivateNPCMsgHandler extends AbstractClientMsgHandler {
// Filter hirelings by slot type
for (Item hirelings : player.getInventory()) {
if (hirelings.template.getItemType().equals(ItemType.EMPLOYMENTCONTRACT)) {
if (hirelings.template.item_type.equals(ItemType.EMPLOYMENTCONTRACT)) {
contract = DbManager.ContractQueries.GET_CONTRACT(hirelings.templateID);
@@ -78,7 +78,7 @@ public class AddItemToTradeWindowMsgHandler extends AbstractClientMsgHandler {
if (!item.validForInventory(source.getClientConnection(), source, source.charItemManager))
return false;
if (!tradingWith.hasRoomTrade(item.template.getItemWt())) {
if (!tradingWith.hasRoomTrade(item.template.item_wt)) {
dispatch = Dispatch.borrow(source, msg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
return false;
@@ -25,7 +25,7 @@ import engine.objects.Guild;
import engine.objects.GuildHistory;
import engine.objects.GuildStatusController;
import engine.objects.PlayerCharacter;
import org.joda.time.DateTime;
import java.time.Instant;
public class BanishUnbanishHandler extends AbstractClientMsgHandler {
@@ -95,8 +95,8 @@ public class BanishUnbanishHandler extends AbstractClientMsgHandler {
//Set guild history
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(guild.getObjectUUID(), toBanish, DateTime.now(), GuildHistoryType.BANISHED)) {
GuildHistory guildHistory = new GuildHistory(toBanish.getGuildUUID(), toBanish.getGuild().getName(), DateTime.now(), GuildHistoryType.BANISHED);
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(guild.getObjectUUID(), toBanish, Instant.now(), GuildHistoryType.BANISHED)) {
GuildHistory guildHistory = new GuildHistory(toBanish.getGuildUUID(), toBanish.getGuild().getName(), Instant.now(), GuildHistoryType.BANISHED);
toBanish.getGuildHistory().add(guildHistory);
}
}
@@ -97,13 +97,9 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler {
if (city == null)
return true;
Warehouse.destroyedWarehouses.remove(building.getObjectUUID());
DbManager.WarehouseQueries.DELETE_WAREHOUSE(city.warehouse);
// Rubble no longer owns city.warehouse, which may be null or a newly placed warehouse
if (city.warehouse != null && building.getRank() != -1) {
DbManager.WarehouseQueries.DELETE_WAREHOUSE(city.warehouse);
city.warehouse = null;
}
city.warehouse = null;
}
@@ -24,7 +24,6 @@ import engine.net.client.msg.guild.GuildInfoMsg;
import engine.objects.Guild;
import engine.objects.Item;
import engine.objects.PlayerCharacter;
import engine.parsers.objects.DeedTemplate;
import engine.util.StringUtils;
public class GuildCreationFinalizeHandler extends AbstractClientMsgHandler {
@@ -43,7 +42,6 @@ public class GuildCreationFinalizeHandler extends AbstractClientMsgHandler {
Guild playerGuild;
Item charter;
DeedTemplate charterDeed;
Dispatch dispatch;
msg = (GuildCreationFinalizeMsg) baseMsg;
@@ -67,9 +65,7 @@ public class GuildCreationFinalizeHandler extends AbstractClientMsgHandler {
// Item must be a valid charterType (type 10 in db)
charterDeed = DeedTemplate._deeds.get(charter.templateID);
if (charterDeed == null || (charterDeed.item_type.equals(ItemType.CHARTER) == false)) {
if (charter == null || (charter.template.item_type.equals(ItemType.CHARTER) == false)) {
ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND);
return true;
}
@@ -238,10 +238,10 @@ public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
if (targetItem == null)
return;
if (targetItem.template.getItemType().equals(ItemType.GOLD))
if (targetItem.template.item_type.equals(ItemType.GOLD))
return;
if (!vendor.charItemManager.hasRoomInventory(targetItem.template.getItemWt())) {
if (!vendor.charItemManager.hasRoomInventory(targetItem.template.item_wt)) {
ErrorPopupMsg.sendErrorPopup(player, 21);
return;
}
@@ -319,7 +319,7 @@ public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
if (targetItem == null)
continue;
if (targetItem.template.getItemType().equals(ItemType.GOLD))
if (targetItem.template.item_type.equals(ItemType.GOLD))
return;
if (!vendor.charItemManager.doesCharOwnThisItem(targetItem.getObjectUUID()))
@@ -328,14 +328,14 @@ public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
if (!vendor.charItemManager.inventoryContains(targetItem))
continue;
itemValue = targetItem.template.getItemValue();
itemValue = targetItem.template.item_value;
if (vendor.getBuilding().getStrongboxValue() + itemValue > vendor.getBuilding().getMaxGold()) {
ErrorPopupMsg.sendErrorPopup(player, 201);
break;
}
switch (targetItem.template.getItemType()) {
switch (targetItem.template.item_type) {
case EMPLOYMENTCONTRACT:
case CHARTER:
case DEED:
@@ -465,13 +465,13 @@ public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
if (targetItem == null)
return;
if (targetItem.template.getItemType().equals(ItemType.GOLD))
if (targetItem.template.item_type.equals(ItemType.GOLD))
return;
if (!vendor.charItemManager.inventoryContains(targetItem))
return;
if (!player.charItemManager.hasRoomInventory(targetItem.template.getItemWt()))
if (!player.charItemManager.hasRoomInventory(targetItem.template.item_wt))
return;
player.charItemManager.buyFromNPC(targetItem, vendor);
@@ -161,7 +161,7 @@ public class LootMsgHandler extends AbstractClientMsgHandler {
if (itemRet == null)
return true;
if (item.template.getItemType().equals(mbEnums.ItemType.GOLD)) {
if (item.template.item_type.equals(mbEnums.ItemType.GOLD)) {
// this is done to prevent the temporary goldItem item
// (from the mob) from appearing in player's inventory.
// It also updates the goldItem quantity display
@@ -187,7 +187,7 @@ public class LootMsgHandler extends AbstractClientMsgHandler {
//TODO send group loot message if player is grouped and visible
Group group = GroupManager.getGroup(player);
if (group != null && group.getSplitGold() && (item.template.getItemType().equals(mbEnums.ItemType.GOLD) == false)) {
if (group != null && group.getSplitGold() && (item.template.item_type.equals(mbEnums.ItemType.GOLD) == false)) {
String name = item.getName();
String text = player.getFirstName() + " has looted " + name + '.';
ChatManager.chatGroupInfoCanSee(player, text);
@@ -202,7 +202,7 @@ public class LootMsgHandler extends AbstractClientMsgHandler {
if (itemRet == null)
return true;
if (item.template.getItemType().equals(mbEnums.ItemType.GOLD)) {
if (item.template.item_type.equals(mbEnums.ItemType.GOLD)) {
// this is done to prevent the temporary goldItem item
// (from the mob) from appearing in player's inventory.
// It also updates the goldItem quantity display
@@ -241,7 +241,7 @@ public class LootMsgHandler extends AbstractClientMsgHandler {
//TODO send group loot message if player is grouped and visible
Group group = GroupManager.getGroup(player);
if (group != null && group.getSplitGold() && (item.template.getItemType().equals(mbEnums.ItemType.GOLD) == false)) {
if (group != null && group.getSplitGold() && (item.template.item_type.equals(mbEnums.ItemType.GOLD) == false)) {
String name = item.getName();
String text = player.getFirstName() + " has looted " + name + '.';
ChatManager.chatGroupInfoCanSee(player, text);
@@ -15,7 +15,7 @@ import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.ManageCityAssetsMsg;
import engine.net.client.msg.PlaceAssetMsg;
import engine.objects.*;
import org.joda.time.DateTime;
import java.time.LocalDateTime;
/*
* @Author:
@@ -141,9 +141,17 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
return true;
}
Warehouse warehouse = Warehouse.destroyedWarehouses.get(building.getObjectUUID());
City city = building.getCity();
if (warehouse == null || Warehouse.isEmpty(warehouse)) {
if (city == null)
return true;
Warehouse warehouse = city.warehouse;
if (warehouse == null)
return true;
if (Warehouse.isEmpty(warehouse)) {
ErrorPopupMsg.sendErrorPopup(player, 167); // no more resources.
return true;
}
@@ -243,11 +251,10 @@ public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
return true;
}
DateTime baneLive = new DateTime(bane.getPlacementDate());
LocalDateTime baneLive = bane.getPlacementDate();
baneLive = baneHour == 24 ? baneLive.plusDays(3) : baneLive.plusDays(2);
baneLive = baneHour == 24 ? baneLive.hourOfDay().setCopy(0) : baneLive.hourOfDay().setCopy(baneHour);
baneLive = baneLive.minuteOfHour().setCopy(0);
baneLive = baneLive.secondOfMinute().setCopy(1);
baneLive = baneHour == 24 ? baneLive.withHour(0) : baneLive.withHour(baneHour);
baneLive = baneLive.withMinute(0).withSecond(1).withNano(0);
bane.setLiveDate(baneLive);
outMsg.actionType = 18;
@@ -8,7 +8,6 @@ import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.*;
import engine.objects.*;
import engine.parsers.objects.DeedTemplate;
import engine.powers.PowersBase;
import java.util.ArrayList;
@@ -79,7 +78,7 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
int uuid = item.templateID;
switch (item.template.getItemType()) {
switch (item.template.item_type) {
case DEED: //buildings
//Call add building screen here, ib.getUseID() get's building ID
@@ -100,7 +99,7 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
pam.setX(loc.getX() + 64); //offset grid from tol
pam.setY(loc.getY());
pam.setZ(loc.getZ() + 64); //offset grid from tol
pam.addPlacementInfo(DeedTemplate._deeds.get(item.templateID).deed_structure_id);
pam.addPlacementInfo(item.template.deed_structure_id);
dispatch = Dispatch.borrow(player, pam);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
@@ -188,14 +187,14 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
if (uuid > 680069 && uuid < 680074) //Handle Charter, Deed, Petition, Warrant here
break;
if (item.template.getItemBaneRank() > 0) {
if (item.template.item_bane_rank > 0) {
// Only one banestone at a time
lock.writeLock().lock();
try {
if (Bane.summonBanestone(player, origin, item.template.getItemBaneRank()) == true)
if (Bane.summonBanestone(player, origin, item.template.item_bane_rank) == true)
itemMan.consume(item);
} finally {
lock.writeLock().unlock();
@@ -226,7 +225,7 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
// Bypass for waterbuckets
if (item.template.getItemType().equals(mbEnums.ItemType.BUCKET)) {
if (item.template.item_type.equals(mbEnums.ItemType.BUCKET)) {
// test for valid target type
if (target.getObjectType() == mbEnums.GameObjectType.PlayerCharacter)
@@ -251,9 +250,10 @@ public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
}
if (waterbucketBypass == false) {
engine.parsers.objects.PowerGrant powerGrant = item.template.getItemPowerGrant().get(0);
PowersBase powerAction = PowersManager.powersBaseByIDString.get(powerGrant.power_type);
PowersManager.applyPower(player, target, Vector3fImmutable.ZERO, powerAction.getToken(), powerGrant.power_value, true);
String powerString = item.template.item_power_grant.keySet().iterator().next();
PowersBase powerAction = PowersManager.powersBaseByIDString.get(powerString);
int powerValue = item.template.item_power_grant.get(powerString);
PowersManager.applyPower(player, target, Vector3fImmutable.ZERO, powerAction.getToken(), powerValue, true);
}
itemMan.consume(item);
} else //just remove the item at this point
@@ -18,9 +18,8 @@ import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.PlaceAssetMsg;
import engine.net.client.msg.PlaceAssetMsg.PlacementInfo;
import engine.objects.*;
import engine.parsers.objects.DeedTemplate;
import engine.server.MBServerStatics;
import org.joda.time.DateTime;
import java.time.Instant;
import org.pmw.tinylog.Logger;
import java.time.LocalDateTime;
@@ -136,8 +135,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
private static boolean validateBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo placementInfo) {
Bane bane;
if (serverZone.guild_zone == false) {
PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName());
return false;
@@ -208,15 +205,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
return false;
}
// Siege equipment has its own validation and never reaches here
bane = city.getBane();
if (bane != null) {
PlaceAssetMsg.sendPlaceAssetError(origin, 74, ""); //"Only buildings of war may be placed during a bane"
return false;
}
if (placementCollisionCheck(serverZone, origin, placementInfo)) {
PlaceAssetMsg.sendPlaceAssetError(origin, 3, ""); // Conflict between proposed assets
return false;
@@ -357,8 +345,8 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
Item contract = null;
for (Item inventoryItem : playerCharacter.getInventory()) {
if (inventoryItem.template.getItemType().equals(ItemType.DEED) &&
DeedTemplate._deeds.get(inventoryItem.templateID).deed_structure_id == buildingList.getBlueprintUUID()) {
if (inventoryItem.template.item_type.equals(ItemType.DEED) &&
inventoryItem.template.deed_structure_id == buildingList.getBlueprintUUID()) {
contract = inventoryItem;
break;
}
@@ -1154,7 +1142,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
Blueprint blueprint;
Building newMesh;
DateTime completionDate;
Instant completionDate;
float vendorRotation;
float buildingRotation;
@@ -1169,9 +1157,9 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
if ((blueprint.getBuildingGroup().equals(BuildingGroup.SIEGETENT))
|| (blueprint.getBuildingGroup().equals(BuildingGroup.BULWARK)))
completionDate = DateTime.now().plusMinutes(15);
completionDate = Instant.now().plusSeconds(15 * 60);
else
completionDate = DateTime.now().plusHours(blueprint.getRankTime(1));
completionDate = Instant.now().plusSeconds(blueprint.getRankTime(1) * 3600);
Vector3fImmutable localLoc = new Vector3fImmutable(ZoneManager.worldToLocal(buildingInfo.getLoc(), currentZone));
@@ -1240,7 +1228,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
ArrayList<AbstractGameObject> shrineObjects = DbManager.ShrineQueries.CREATE_SHRINE(
currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0),
localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.PROTECTED, 0, 0,
DateTime.now().plusHours(blueprint.getRankTime(1)), blueprint.getMeshForRank(0), vendorRotation, buildingRotation, shrineType.name());
Instant.now().plusSeconds(blueprint.getRankTime(1) * 3600), blueprint.getMeshForRank(0), vendorRotation, buildingRotation, shrineType.name());
if (shrineObjects == null) {
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
@@ -1300,7 +1288,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
float buildingRotation = buildingInfo.getRot().y;
float vendorRotation = buildingInfo.getW();
DateTime completionDate = DateTime.now().plusHours(blueprint.getRankTime(1));
Instant completionDate = Instant.now().plusSeconds(blueprint.getRankTime(1) * 3600);
newMesh = DbManager.BuildingQueries.CREATE_BUILDING(
@@ -1345,7 +1333,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
warehouseBuilding = DbManager.BuildingQueries.CREATE_BUILDING(
currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0),
localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.NONE, 0, 0,
DateTime.now().plusHours(blueprint.getRankTime(1)), blueprint.getMeshForRank(0), vendorRotation, buildingRotation);
Instant.now().plusSeconds(blueprint.getRankTime(1) * 3600), blueprint.getMeshForRank(0), vendorRotation, buildingRotation);
if (warehouseBuilding == null) {
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
@@ -1353,7 +1341,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
}
Warehouse warehouse = new Warehouse(warehouseBuilding);
Warehouse.destroyedWarehouses.values().removeIf(destroyed -> destroyed.city == city);
city.warehouse = warehouse;
DbManager.WarehouseQueries.UPDATE_WAREHOUSE(warehouse);
@@ -85,7 +85,7 @@ public class RepairMsgHandler extends AbstractClientMsgHandler {
//make sure item is damaged and not destroyed
short dur = (short) toRepair.combat_health_current;
short max = (short) toRepair.template.getCombatHealthFull();
short max = (short) toRepair.template.combat_health_full;
//account for durability modifications
@@ -68,7 +68,7 @@ public class TransferItemFromBankMsgHandler extends AbstractClientMsgHandler {
return true;
;
if (item.template.getItemType().equals(mbEnums.ItemType.GOLD)) {
if (item.template.item_type.equals(mbEnums.ItemType.GOLD)) {
if (!itemManager.moveGoldToInventory(item, msg.getNumItems()))
return true;
@@ -85,7 +85,7 @@ public class TransferItemFromBankMsgHandler extends AbstractClientMsgHandler {
// Not gold, process update here
if (!itemManager.hasRoomInventory(item.template.getItemWt()))
if (!itemManager.hasRoomInventory(item.template.item_wt))
return true;
if (itemManager.moveItemToInventory(item) == false)
@@ -65,7 +65,7 @@ public class TransferItemToBankMsgHandler extends AbstractClientMsgHandler {
return true;
if (item.containerType == mbEnums.ItemContainerType.INVENTORY && itemManager.isBankOpen())
if (item.template.getItemType().equals(mbEnums.ItemType.GOLD)) {
if (item.template.item_type.equals(mbEnums.ItemType.GOLD)) {
if (!itemManager.moveGoldToBank(item, msg.getNumItems()))
return true;
UpdateGoldMsg goldMes = new UpdateGoldMsg(player);
@@ -76,7 +76,7 @@ public class TransferItemToBankMsgHandler extends AbstractClientMsgHandler {
} else {
if (!itemManager.hasRoomBank(item.template.getItemWt()))
if (!itemManager.hasRoomBank(item.template.item_wt))
return true;
if (!itemManager.moveItemToBank(item))
@@ -86,7 +86,7 @@ public class VendorBuyMsgHandler extends AbstractClientMsgHandler {
if (me.objectUUID == vendorBuyMsg.getItemID()) {
//test room available for item
if (!itemMan.hasRoomInventory(me.template.getItemWt()))
if (!itemMan.hasRoomInventory(me.template.item_wt))
return true;
int cost = me.getValue();
@@ -148,10 +148,10 @@ public class VendorBuyMsgHandler extends AbstractClientMsgHandler {
//test room available for item
if (!itemMan.hasRoomInventory(vendorItem.template.getItemWt()))
if (!itemMan.hasRoomInventory(vendorItem.template.item_wt))
return true;
int cost = vendorItem.template.getItemValue();
int cost = vendorItem.template.item_value;
if (vendorItem.flags.contains(mbEnums.ItemFlags.Identified) || vendorItem.isCustomValue())
cost = vendorItem.magicValue;
@@ -94,7 +94,7 @@ public class VendorSellMsgHandler extends AbstractClientMsgHandler {
return true;
if (npc.getParentZone() != null && npc.getParentZone().playerCityUUID != 0)
if (!npc.charItemManager.hasRoomInventory(sell.template.getItemWt())) {
if (!npc.charItemManager.hasRoomInventory(sell.template.item_wt)) {
ErrorPopupMsg.sendErrorPopup(player, 21);
return true;
}
@@ -104,7 +104,7 @@ public class VendorSellMsgHandler extends AbstractClientMsgHandler {
//get goldItem cost to sell
cost = (int) (sell.template.getItemValue() * (sell.combat_health_current / sell.template.getCombatHealthFull()));
cost = (int) (sell.template.item_value * (sell.combat_health_current / sell.template.combat_health_full));
float bargain = player.getBargain();
float profit = npc.getBuyPercent(player) + bargain;
@@ -17,8 +17,8 @@ import engine.net.Protocol;
import engine.objects.Building;
import engine.objects.Guild;
import engine.server.MBServerStatics;
import org.joda.time.DateTime;
import org.joda.time.Seconds;
import java.time.LocalDateTime;
import java.time.Duration;
public class ArcMineWindowAvailableTimeMsg extends ClientNetMsg {
@@ -26,8 +26,8 @@ public class ArcMineWindowAvailableTimeMsg extends ClientNetMsg {
private Building treeOfLife;
private int currentMineHour;
private Seconds secondsLeft;
private DateTime lateTime;
private Duration secondsLeft;
private LocalDateTime lateTime;
private int late;
/**
@@ -72,15 +72,15 @@ public class ArcMineWindowAvailableTimeMsg extends ClientNetMsg {
currentMineHour = guild.getMineTime();
late = MBServerStatics.MINE_LATE_WINDOW;
lateTime = DateTime.now();
lateTime = LocalDateTime.now();
if (late == 0)
lateTime = lateTime.plusDays(1);
lateTime = lateTime.hourOfDay().setCopy(late);
lateTime = lateTime.withHour(late);
late = ((late > 23) ? (late - 24) : late);
secondsLeft = Seconds.secondsBetween(DateTime.now(), lateTime);
secondsLeft = Duration.between(LocalDateTime.now(), lateTime);
}
/**
@@ -106,4 +106,4 @@ public class ArcMineWindowAvailableTimeMsg extends ClientNetMsg {
public void setBuildingUUID(int buildingUUID) {
this.buildingUUID = buildingUUID;
}
}
}
@@ -18,9 +18,6 @@ import engine.net.ByteBufferReader;
import engine.net.ByteBufferWriter;
import engine.net.Protocol;
import engine.objects.*;
import org.joda.time.DateTime;
import org.joda.time.Period;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Set;
@@ -397,37 +394,33 @@ public class ManageCityAssetsMsg extends ClientNetMsg {
else
writer.put((byte) 0);
DateTime placedOn = bane.getLiveDate();
LocalDateTime placedOn = bane.getLiveDate();
if (placedOn == null)
placedOn = new DateTime(DateTime.now());
placedOn = LocalDateTime.now();
//set Calander to date of bane live.
DateTime now = DateTime.now();
DateTime defaultTime = new DateTime(bane.getPlacementDate());
DateTime playerEnterWorldTime = new DateTime(this.assetManager.getTimeStamp("EnterWorld"));
Period period = new Period(playerEnterWorldTime.getMillis(), now.getMillis());
int hoursLoggedIn = period.getHours();
LocalDateTime now = LocalDateTime.now();
LocalDateTime defaultTime = bane.getPlacementDate();
LocalDateTime playerEnterWorldTime = LocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(this.assetManager.getTimeStamp("EnterWorld")), ZoneId.systemDefault());
int hoursLoggedIn = (int) java.time.Duration.between(playerEnterWorldTime, now).toHours();
hoursLoggedIn = hoursLoggedIn < 0 ? 0 : hoursLoggedIn;
defaultTime = defaultTime.plusDays(2);
defaultTime = defaultTime.hourOfDay().setCopy(22);
defaultTime = defaultTime.minuteOfHour().setCopy(0);
defaultTime = defaultTime.secondOfMinute().setCopy(0);
defaultTime = defaultTime.plusDays(2).withHour(22).withMinute(0).withSecond(0).withNano(0);
long curTime = now.getMillis();
long curTime = now.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
long timeLeft = 0;
if (bane.getLiveDate() != null)
timeLeft = bane.getLiveDate().getMillis() - curTime;
timeLeft = bane.getLiveDate().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - curTime;
else
timeLeft = defaultTime.getMillis() - curTime + 1000;
timeLeft = defaultTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() - curTime + 1000;
//DO not touch these. They are static formula's until i get the correct converter for SB Time.
writer.put((byte) placedOn.dayOfMonth().get());
writer.put((byte) placedOn.monthOfYear().get());
writer.putInt(placedOn.year().get() - 1900);
writer.put((byte) placedOn.getDayOfMonth());
writer.put((byte) placedOn.getMonthValue());
writer.putInt(placedOn.getYear() - 1900);
writer.put((byte) 0);
writer.put((byte) 0);
writer.put((byte) 0);
+27 -33
View File
@@ -19,10 +19,8 @@ import engine.net.ByteBufferReader;
import engine.net.ByteBufferWriter;
import engine.net.Protocol;
import engine.objects.*;
import engine.parsers.objects.CObjectTemplate;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.joda.time.Seconds;
import java.time.Duration;
import java.time.LocalDateTime;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
@@ -138,7 +136,6 @@ public class ManageNPCMsg extends ClientNetMsg {
@Override
protected void _serialize(ByteBufferWriter writer) {
Period upgradePeriod;
int upgradePeriodInSeconds;
try {
@@ -200,21 +197,20 @@ public class ManageNPCMsg extends ClientNetMsg {
writer.putInt(npc.getUpgradeCost());
if (npc.isRanking() && npc.getUpgradeDateTime().isAfter(DateTime.now()))
upgradePeriod = new Period(DateTime.now(), npc.getUpgradeDateTime());
else
upgradePeriod = new Period(0);
long upgradeTotalSecs = 0;
if (npc.isRanking() && npc.getUpgradeDateTime().isAfter(LocalDateTime.now()))
upgradeTotalSecs = Duration.between(LocalDateTime.now(), npc.getUpgradeDateTime()).getSeconds();
writer.put((byte) upgradePeriod.getDays()); //for timer
writer.put((byte) (int) (upgradeTotalSecs / 86400)); //for timer
writer.put((byte) unknown26);//unknown
writer.putInt(100); //unknown
writer.put((byte) upgradePeriod.getHours()); //for timer
writer.put((byte) upgradePeriod.getMinutes()); //for timer
writer.put((byte) upgradePeriod.getSeconds()); //for timer
writer.put((byte) (int) ((upgradeTotalSecs % 86400) / 3600)); //for timer
writer.put((byte) (int) ((upgradeTotalSecs % 3600) / 60)); //for timer
writer.put((byte) (int) (upgradeTotalSecs % 60)); //for timer
if (npc.isRanking() && npc.getUpgradeDateTime().isAfter(DateTime.now()))
upgradePeriodInSeconds = Seconds.secondsBetween(DateTime.now(), npc.getUpgradeDateTime()).getSeconds();
if (npc.isRanking() && npc.getUpgradeDateTime().isAfter(LocalDateTime.now()))
upgradePeriodInSeconds = (int) upgradeTotalSecs;
else
upgradePeriodInSeconds = 0;
@@ -421,18 +417,17 @@ public class ManageNPCMsg extends ClientNetMsg {
writer.putInt(rollableSet.size());
for (int templateID : rollableSet) {
CObjectTemplate template = CObjectTemplate.lookup(templateID);
int modTable = ForgeManager.getVendorModTable(templateID);
ItemTemplate template = ItemTemplate.templates.get(templateID);
writer.put((byte) 1);
writer.putInt(0);
writer.putInt(templateID); //itemID
writer.putInt(template.getItemValue());
writer.putInt(template.item_value);
writer.putInt(600);
writer.put((byte) 1);
writer.put((byte) modTable);
writer.put((byte) modTable);
writer.put((byte) modTable);
writer.put((byte) modTable);//EffectItemType
writer.put((byte) template.modTable);
writer.put((byte) template.modTable);
writer.put((byte) template.modTable);
writer.put((byte) template.modTable);//EffectItemType
}
ArrayList<Item> cooking = NPCManager.getAllCookingForVendor(npc);
@@ -446,7 +441,7 @@ public class ManageNPCMsg extends ClientNetMsg {
writer.putInt(0);
writer.putInt(item.templateID);
writer.putInt(item.template.getItemValue());
writer.putInt(item.template.item_value);
long timeLife = item.getDateToUpgrade() - System.currentTimeMillis();
@@ -591,21 +586,20 @@ public class ManageNPCMsg extends ClientNetMsg {
writer.putInt(Mob.getUpgradeCost(mobA));
if (mobA.isRanking() && mobA.getUpgradeDateTime().isAfter(DateTime.now()))
upgradePeriod = new Period(DateTime.now(), mobA.getUpgradeDateTime());
else
upgradePeriod = new Period(0);
long upgradeTotalSecs = 0;
if (mobA.isRanking() && mobA.getUpgradeDateTime().isAfter(LocalDateTime.now()))
upgradeTotalSecs = Duration.between(LocalDateTime.now(), mobA.getUpgradeDateTime()).getSeconds();
writer.put((byte) upgradePeriod.getDays()); //for timer
writer.put((byte) (int) (upgradeTotalSecs / 86400)); //for timer
writer.put((byte) unknown26);//unknown
writer.putInt(100); //unknown
writer.put((byte) upgradePeriod.getHours()); //for timer
writer.put((byte) upgradePeriod.getMinutes()); //for timer
writer.put((byte) upgradePeriod.getSeconds()); //for timer
writer.put((byte) (int) ((upgradeTotalSecs % 86400) / 3600)); //for timer
writer.put((byte) (int) ((upgradeTotalSecs % 3600) / 60)); //for timer
writer.put((byte) (int) (upgradeTotalSecs % 60)); //for timer
if (mobA.isRanking() && mobA.getUpgradeDateTime().isAfter(DateTime.now()))
upgradePeriodInSeconds = Seconds.secondsBetween(DateTime.now(), mobA.getUpgradeDateTime()).getSeconds();
if (mobA.isRanking() && mobA.getUpgradeDateTime().isAfter(LocalDateTime.now()))
upgradePeriodInSeconds = (int) upgradeTotalSecs;
else
upgradePeriodInSeconds = 0;
@@ -54,7 +54,7 @@ public class UpdateInventoryMsg extends ClientNetMsg {
for (Item item : list) {
if (item.template.getItemType().equals(ItemType.GOLD)) {
if (item.template.item_type.equals(ItemType.GOLD)) {
if (item.getNumOfItems() == 0)
continue;
}
+1 -6
View File
@@ -16,7 +16,6 @@ import engine.net.ByteBufferWriter;
import engine.net.Protocol;
import engine.objects.Item;
import engine.objects.PlayerCharacter;
import engine.parsers.objects.DeedTemplate;
public class UseCharterMsg extends ClientNetMsg {
@@ -62,13 +61,9 @@ public class UseCharterMsg extends ClientNetMsg {
public void configure() {
DeedTemplate charterDeed;
if (close) {
for (Item i : player.getInventory()) {
charterDeed = DeedTemplate._deeds.get(i.templateID);
if (charterDeed != null && charterDeed.item_type.equals(ItemType.CHARTER)) {
if (i.template.item_type.equals(ItemType.CHARTER)) {
charterUUID = i.getObjectUUID();
break;
}
@@ -156,7 +156,7 @@ public class VendorBuyWindowMsg extends ClientNetMsg {
for (Item item : inventory) {
if (item.getOwnerID() != ownerID)
continue;
if (item.template.getItemType().equals(ItemType.GOLD)) {
if (item.template.item_type.equals(ItemType.GOLD)) {
if (item.getNumOfItems() == 0)
continue;
}
@@ -17,7 +17,7 @@ import engine.net.ByteBufferWriter;
import engine.net.Protocol;
import engine.net.client.msg.ClientNetMsg;
import engine.objects.*;
import org.joda.time.DateTime;
import java.time.Instant;
public class GuildInfoMsg extends ClientNetMsg {
@@ -306,7 +306,7 @@ class GuildInfoMessageType4 extends GuildInfoMessageType {
writer.putString(guildLeaderName);
writer.putString(pc.getName());
writer.putDateTime(DateTime.now());
writer.putDateTime(Instant.now());
writer.put((byte) 1);
writer.put((byte) 1);
writer.put((byte) 1);
@@ -401,7 +401,7 @@ class GuildInfoMessageType5 extends GuildInfoMessageType {
writer.putString("Guild Leader");
writer.putString(""); //Nation Leader - I believe
DateTime now = DateTime.now();
Instant now = Instant.now();
writer.putDateTime(now);
writer.put((byte) 1);
+49 -130
View File
@@ -29,8 +29,6 @@ import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.ApplyRuneMsg;
import engine.net.client.msg.UpdateStateMsg;
import engine.parsers.objects.CObjectTemplate;
import engine.parsers.objects.RuneTemplate;
import engine.powers.EffectsBase;
import engine.powers.PowersBase;
import engine.powers.effectmodifiers.AbstractEffectModifier;
@@ -654,34 +652,16 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
AssignDefenseValue(abstractCharacter);
// calculate atr and damage for each hand
ConcurrentHashMap<EquipSlotType, Item> equipped = abstractCharacter.charItemManager.getEquipped();
AssignDamageAtrForPlayers(abstractCharacter, equipped.get(EquipSlotType.RHELD), true, equipped.get(EquipSlotType.LHELD));
AssignDamageAtrForPlayers(abstractCharacter, equipped.get(EquipSlotType.LHELD), false, equipped.get(EquipSlotType.RHELD));
AssignDamageAtrForPlayers(abstractCharacter, equipped.get(EquipSlotType.RHELD), true, equipped.get(EquipSlotType.RHELD));
AssignDamageAtrForPlayers(abstractCharacter, equipped.get(EquipSlotType.LHELD), false, equipped.get(EquipSlotType.LHELD));
if (abstractCharacter.getObjectType().equals(GameObjectType.Mob)) {
Mob mob = (Mob) abstractCharacter;
RuneTemplate rune = RuneTemplate._runes.get(mob.loadID);
float minDamage = mob.mobBase.getDamageMin();
float maxDamage = mob.mobBase.getDamageMax();
int attackRating = mob.mobBase.getAttackRating();
// The client (ArcMobile, 0x46D200) takes mob damage straight from the rune MINDAMAGE/MAXDAMAGE,
// with no stat scaling. Use the rune when it has damage, otherwise keep the mobbase value.
if (rune != null && rune.rune_max_damage > 0) {
minDamage = rune.rune_min_damage;
maxDamage = rune.rune_max_damage;
}
// Likewise ATR comes straight from the rune ATTACK for mobiles (0x466570).
if (rune != null && rune.rune_attack > 0)
attackRating = rune.rune_attack;
abstractCharacter.minDamageHandOne = (int) minDamage;
abstractCharacter.minDamageHandTwo = (int) minDamage;
abstractCharacter.maxDamageHandOne = (int) maxDamage;
abstractCharacter.maxDamageHandTwo = (int) maxDamage;
abstractCharacter.atrHandOne = attackRating;
abstractCharacter.atrHandTwo = attackRating;
abstractCharacter.minDamageHandOne = (int) mob.mobBase.getDamageMin();
abstractCharacter.minDamageHandTwo = (int) mob.mobBase.getDamageMin();
abstractCharacter.maxDamageHandOne = (int) mob.mobBase.getDamageMax();
abstractCharacter.maxDamageHandTwo = (int) mob.mobBase.getDamageMax();
abstractCharacter.atrHandOne = mob.mobBase.getAttackRating();
abstractCharacter.atrHandTwo = mob.mobBase.getAttackRating();
abstractCharacter.defenseRating = mob.mobBase.getDefenseRating();
}
}
@@ -693,17 +673,16 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
// make sure weapon exists
boolean noWeapon = false;
CObjectTemplate weaponTemplate = null;
engine.parsers.objects.ItemTemplate.Damage damage;
ItemTemplate weaponTemplate = null;
if (weapon == null)
noWeapon = true;
else {
CObjectTemplate itemTemplate = weapon.template;
ItemTemplate itemTemplate = weapon.template;
if (itemTemplate == null)
noWeapon = true;
else if (!weapon.template.getItemType().equals(ItemType.WEAPON)) {
else if (!weapon.template.item_type.equals(ItemType.WEAPON)) {
defaultAtrAndDamage(abstractCharacter, mainHand);
return;
} else
@@ -720,7 +699,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
if (noWeapon) {
if (mainHand) {
Item off = abstractCharacter.charItemManager.getEquipped().get(EquipSlotType.LHELD);
if (off != null && off.template != null && off.template.getItemType().equals(ItemType.WEAPON))
if (off != null && off.template != null && off.template.item_type.equals(ItemType.WEAPON))
abstractCharacter.rangeHandOne = 10 * (1 + (abstractCharacter.statStrBase / 600)); // Set
// to
// no
@@ -738,24 +717,15 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
mastDam = CharacterSkill.getQuickMastery(abstractCharacter, "Unarmed Combat Mastery");
else
mastDam = masteryPercentage;
// Base fist damage from the race rune natural attack (1-4 for all races), scaled below like a weapon.
// Matches the client's unarmed damage calc (0x46D200).
float[] naturalAttack = CombatManager.getNaturalAttack(abstractCharacter, mainHand ? EquipSlotType.RHELD : EquipSlotType.LHELD);
if (naturalAttack != null && naturalAttack.length > 9) {
min = (int) naturalAttack[8];
max = (int) naturalAttack[9];
} else {
min = 1;
max = 3;
}
// TODO Correct these
min = 1;
max = 3;
} else {
if (mainHand)
abstractCharacter.rangeHandOne = engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_max_range * (1 + (abstractCharacter.statStrBase / 600));
abstractCharacter.rangeHandOne = weapon.template.item_weapon_max_range * (1 + (abstractCharacter.statStrBase / 600));
else
abstractCharacter.rangeHandTwo = engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_max_range * (1 + (abstractCharacter.statStrBase / 600));
abstractCharacter.rangeHandTwo = weapon.template.item_weapon_max_range * (1 + (abstractCharacter.statStrBase / 600));
if (abstractCharacter.bonuses != null) {
float range_bonus = 1 + abstractCharacter.bonuses.getFloatPercentAll(ModType.WeaponRange, SourceType.None);
@@ -767,20 +737,20 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
}
skillPercentage = getModifiedAmount(abstractCharacter.skills.get(weapon.template.getItemSkillUsed()));
masteryPercentage = getModifiedAmount(abstractCharacter.skills.get(weaponTemplate.getItemSkillMasteryUsed()));
skillPercentage = getModifiedAmount(abstractCharacter.skills.get(weapon.template.item_skill_used));
masteryPercentage = getModifiedAmount(abstractCharacter.skills.get(weaponTemplate.item_skill_mastery_used));
if (masteryPercentage == 0f)
mastDam = 0f;
// mastDam = CharacterSkill.getQuickMastery(this, wb.getMastery());
else
mastDam = masteryPercentage;
damage = engine.parsers.objects.ItemTemplate.getWeapon(weapon.templateID).weapon_damage.get(0);
int[] damages = (int[]) weaponTemplate.item_weapon_damage.values().toArray()[0];
min = damage.damage_min;
max = damage.damage_max;
min = damages[0];
max = damages[1];
strBased = engine.parsers.objects.ItemTemplate._items.get(weapon.templateID).item_primary_attr == AttributeType.Strength;
strBased = weaponTemplate.item_primary_attr.equals(AttributeType.Strength);
}
if (abstractCharacter.effects != null && abstractCharacter.effects.containsKey("DeathShroud"))
@@ -829,7 +799,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
//calculate speed
if (weaponTemplate != null)
speed = engine.parsers.objects.ItemTemplate.getWeapon(weaponTemplate.getTemplateId()).weapon_wepspeed;
speed = weaponTemplate.item_weapon_wepspeed;
else
speed = 20f; //unarmed attack speed
if (weapon != null)
@@ -884,12 +854,15 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
max *= percentMaxDamage;
}
// Client (0x466EB0 sets char+0xD0C, 0x46D200 applies it): 30% cut only when both hands hold a WEAPON.
//if duel wielding, cut damage by 30%
if (!noWeapon && otherHand != null && otherHand.template != null
&& otherHand.template.getItemType().equals(ItemType.WEAPON)) {
min *= 0.7f;
max *= 0.7f;
if (otherHand != null) {
ItemTemplate ibo = otherHand.template;
if (ibo != null && otherHand.template.equals(ItemType.WEAPON)) {
min *= 0.7f;
max *= 0.7f;
}
}
// calculate damage
@@ -955,7 +928,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
if (ItemManager.isShield(shield) == false)
return 0;
CObjectTemplate template = shield.template;
ItemTemplate template = shield.template;
if (template == null)
return 0;
@@ -969,7 +942,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
} else
skillMod = blockSkill.getModifiedAmount();
float def = engine.parsers.objects.ItemTemplate._items.get(shield.templateID).item_defense_rating;
float def = template.item_defense_rating;
//apply item defense bonuses
@@ -991,30 +964,29 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
if (armor == null)
return 0;
CObjectTemplate template = armor.template;
ItemTemplate template = armor.template;
if (template == null)
return 0;
if (!armor.template.getItemType().equals(ItemType.ARMOR))
if (!armor.template.item_type.equals(ItemType.ARMOR))
return 0;
// "Cloth" is a placeholder in Skills.cfg (token 0) that no character learns
if (armor.template.getItemSkillUsed().isEmpty() || armor.template.getItemSkillUsed().equals("Cloth"))
return engine.parsers.objects.ItemTemplate._items.get(armor.templateID).item_defense_rating;
if (armor.template.item_skill_used.isEmpty())
return template.item_defense_rating;
CharacterSkill armorSkill = abstractCharacter.skills.get(armor.template.getItemSkillUsed());
CharacterSkill armorSkill = abstractCharacter.skills.get(armor.template.item_skill_used);
if (abstractCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) && armorSkill == null) {
Logger.error("Player " + abstractCharacter.getObjectUUID()
+ " has armor equipped without the nescessary skill to equip it");
return engine.parsers.objects.ItemTemplate._items.get(armor.templateID).item_defense_rating;
return template.item_defense_rating;
}
if (armorSkill == null)
return engine.parsers.objects.ItemTemplate._items.get(armor.templateID).item_defense_rating; // Mobiles do not have armor skills @TODO
return template.item_defense_rating; // Mobiles do not have armor skills @TODO
float def = engine.parsers.objects.ItemTemplate._items.get(armor.templateID).item_defense_rating;
float def = template.item_defense_rating;
//apply item defense bonuses
@@ -1032,7 +1004,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
private static float getWeaponDefense(AbstractCharacter abstractCharacter, ConcurrentHashMap<EquipSlotType, Item> equipped) {
Item weapon = equipped.get(EquipSlotType.RHELD);
CObjectTemplate weaponTemplate = null;
ItemTemplate weaponTemplate = null;
CharacterSkill skill, mastery;
float val = 0;
boolean unarmed = false;
@@ -1053,8 +1025,8 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
skill = abstractCharacter.skills.get("Unarmed Combat");
mastery = abstractCharacter.skills.get("Unarmed Combat Mastery");
} else {
skill = abstractCharacter.skills.get(weapon.template.getItemSkillUsed());
mastery = abstractCharacter.skills.get(weaponTemplate.getItemSkillMasteryUsed());
skill = abstractCharacter.skills.get(weapon.template.item_skill_used);
mastery = abstractCharacter.skills.get(weaponTemplate.item_skill_mastery_used);
}
if (skill != null)
@@ -1089,7 +1061,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
for (Item item : equipped.values()) {
CObjectTemplate ib = item.template;
ItemTemplate ib = item.template;
if (ib == null)
continue;
@@ -1504,22 +1476,13 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
Mob mob = (Mob) this;
if (mob.isSiege()) {
return CombatManager.getSiegeRange(mob);
return 300;
}
float range = 8;
if ((this).charItemManager.equipped.get(EquipSlotType.RHELD) != null) {
range = engine.parsers.objects.ItemTemplate.getWeapon(((Mob) this).charItemManager.equipped.get(EquipSlotType.RHELD).templateID).weapon_max_range;
range = ((Mob) this).charItemManager.equipped.get(EquipSlotType.RHELD).template.item_weapon_max_range;
} else if (((Mob) this).charItemManager.equipped.get(EquipSlotType.LHELD) != null) {
range = engine.parsers.objects.ItemTemplate.getWeapon(((Mob) this).charItemManager.equipped.get(EquipSlotType.LHELD).templateID).weapon_max_range;
} else {
// Unarmed: use the rune natural attack range when it has one (e.g. Gasser 150), not clamped.
// Most melee runes have 0, so they keep the default of 8.
float naturalRange = CombatManager.getNaturalAttackRange(mob, EquipSlotType.RHELD);
if (naturalRange > 0)
return naturalRange;
range = ((Mob) this).charItemManager.equipped.get(EquipSlotType.LHELD).template.item_weapon_max_range;
}
// TODO Is this clamp from live?
@@ -1864,15 +1827,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
if (this.getObjectType().equals(GameObjectType.Mob)) {
//handle hate value addition
Mob target = (Mob) this;
// Siege engines switch to whoever damages them, players and pets alike.
// Misses and non-damaging powers do not pull them.
if (target.isSiege() && value < 0f && attacker != null && !attacker.equals(target)) {
target.setCombatTarget(attacker);
flagSiegeAttackerHostile(target, attacker);
}
if (attacker.getObjectType().equals(GameObjectType.PlayerCharacter)) {
if (target.playerAgroMap.containsKey(attacker.getObjectUUID()))
@@ -1906,41 +1860,6 @@ public abstract class AbstractCharacter extends AbstractWorldObject {
return 0;
}
private static void flagSiegeAttackerHostile(Mob siegeEngine, AbstractCharacter attacker) {
// Damaging a siege engine on a city grid flags the player hostile to that
// city, unless they belong to the city's nation or an allied nation.
// Pets flag their owner.
City city;
AbstractCharacter flagged;
Guild cityNation;
city = ZoneManager.getCityAtLocation(siegeEngine.loc);
if (city == null)
return;
flagged = attacker;
if (attacker.getObjectType().equals(GameObjectType.Mob))
flagged = ((Mob) attacker).guardCaptain;
if (flagged == null || !flagged.getObjectType().equals(GameObjectType.PlayerCharacter))
return;
cityNation = city.getGuild().getNation();
if (flagged.getGuild().getNation().equals(cityNation))
return;
if (cityNation.getAllyList().contains(flagged.getGuild().getNation()))
return;
if (!city.cityOutlaws.contains(flagged.getObjectUUID()))
city.cityOutlaws.add(flagged.getObjectUUID());
}
public float getCurrentHitpoints() {
return this.health.get();
}
@@ -148,20 +148,9 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
public void dismiss() {
boolean isSiegeEngine;
isSiegeEngine = this.getObjectType() == GameObjectType.Mob && ((Mob) this).isSiege();
if (this.isPet()) {
if (isSiegeEngine) {
// Released siege engines stay in place, alive, and keep firing at
// their current target until a Rod of Command takes them again.
this.agentType = mbEnums.AIAgentType.MOBILE;
} else if ((this.agentType.equals(mbEnums.AIAgentType.PET))) { //delete summoned pet
if ((this.agentType.equals(mbEnums.AIAgentType.PET))) { //delete summoned pet
WorldGrid.RemoveWorldObject(this);
@@ -178,8 +167,7 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
// clear owner and set not alive
if (!isSiegeEngine)
this.isAlive.set(false);
this.isAlive.set(false);
PlayerCharacter owner = (PlayerCharacter) this.guardCaptain;
@@ -200,8 +188,6 @@ public abstract class AbstractIntelligenceAgent extends AbstractCharacter {
this.guardCaptain = null;
}
if (isSiegeEngine && this.isAlive())
WorldGrid.updateObject(this);
}
}
+3 -3
View File
@@ -172,7 +172,7 @@ public class Account extends AbstractGameObject {
this.vault = DbManager.ItemQueries.GET_ITEMS_FOR_ACCOUNT(this.getObjectUUID());
for (Item item : this.vault) {
if (item.template.getItemType().equals(mbEnums.ItemType.GOLD)) {
if (item.template.item_type.equals(mbEnums.ItemType.GOLD)) {
this.vaultGold = item;
}
}
@@ -216,7 +216,7 @@ public class Account extends AbstractGameObject {
return;
if (item.containerType == mbEnums.ItemContainerType.INVENTORY && player.charItemManager.isVaultOpen()) {
if (!player.charItemManager.hasRoomVault(item.template.getItemWt())) {
if (!player.charItemManager.hasRoomVault(item.template.item_wt)) {
ItemToVaultMsgHandler.forceTransferFromVaultToInventory(msg, origin, "There is no room in your vault.");
return;
}
@@ -262,7 +262,7 @@ public class Account extends AbstractGameObject {
return;
if (item.containerType == mbEnums.ItemContainerType.VAULT && itemManager.isVaultOpen()) {
if (!itemManager.hasRoomInventory(item.template.getItemWt())) {
if (!itemManager.hasRoomInventory(item.template.item_wt)) {
ItemFromVaultMsgHandler.forceTransferFromInventoryToVault(msg, origin, "There is no room in your inventory.");
return;
}
+18 -22
View File
@@ -25,7 +25,8 @@ import engine.net.client.ClientConnection;
import engine.net.client.msg.PlaceAssetMsg;
import engine.net.client.msg.chat.ChatSystemMsg;
import engine.server.MBServerStatics;
import org.joda.time.DateTime;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
@@ -40,8 +41,8 @@ public final class Bane {
private final int cityUUID;
private final int stoneUUID;
private int ownerUUID;
private DateTime placementDate = null;
private DateTime liveDate = null;
private LocalDateTime placementDate = null;
private LocalDateTime liveDate = null;
private BaneDefaultTimeJob defaultTimeJob;
// Internal cache for banes
@@ -62,12 +63,12 @@ public final class Bane {
sqlDateTime = rs.getTimestamp("placementDate");
if (sqlDateTime != null)
this.placementDate = new DateTime(sqlDateTime);
this.placementDate = LocalDateTime.ofInstant(sqlDateTime.toInstant(), ZoneId.systemDefault());
sqlDateTime = rs.getTimestamp("liveDate");
if (sqlDateTime != null)
this.liveDate = new DateTime(sqlDateTime);
this.liveDate = LocalDateTime.ofInstant(sqlDateTime.toInstant(), ZoneId.systemDefault());
switch (this.getSiegePhase()) {
@@ -81,7 +82,7 @@ public final class Bane {
this.activateBaneJob.cancelJob();
abtj = new ActivateBaneJob(cityUUID);
JobScheduler.getInstance().scheduleJob(abtj, this.liveDate.getMillis());
JobScheduler.getInstance().scheduleJob(abtj, this.liveDate.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
this.activateBaneJob = abtj;
break;
@@ -93,7 +94,7 @@ public final class Bane {
this.activateBaneJob.cancelJob();
abtj = new ActivateBaneJob(cityUUID);
JobScheduler.getInstance().scheduleJob(abtj, this.liveDate.getMillis());
JobScheduler.getInstance().scheduleJob(abtj, this.liveDate.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
this.activateBaneJob = abtj;
break;
@@ -353,7 +354,7 @@ public final class Bane {
return phase;
}
if (DateTime.now().isAfter(this.liveDate)) {
if (LocalDateTime.now().isAfter(this.liveDate)) {
phase = SiegePhase.WAR; //war
return phase;
}
@@ -368,15 +369,10 @@ public final class Bane {
private void setDefaultTime() {
DateTime timeToSetDefault = new DateTime(this.placementDate);
timeToSetDefault = timeToSetDefault.plusDays(1);
LocalDateTime timeToSetDefault = this.placementDate.plusDays(1);
DateTime currentTime = DateTime.now();
DateTime defaultTime = new DateTime(this.placementDate);
defaultTime = defaultTime.plusDays(2);
defaultTime = defaultTime.hourOfDay().setCopy(22);
defaultTime = defaultTime.minuteOfHour().setCopy(0);
defaultTime = defaultTime.secondOfMinute().setCopy(0);
LocalDateTime currentTime = LocalDateTime.now();
LocalDateTime defaultTime = this.placementDate.plusDays(2).withHour(22).withMinute(0).withSecond(0);
if (currentTime.isAfter(timeToSetDefault))
this.setLiveDate(defaultTime);
@@ -386,7 +382,7 @@ public final class Bane {
this.defaultTimeJob.cancelJob();
BaneDefaultTimeJob bdtj = new BaneDefaultTimeJob(this);
JobScheduler.getInstance().scheduleJob(bdtj, timeToSetDefault.getMillis());
JobScheduler.getInstance().scheduleJob(bdtj, timeToSetDefault.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
this.defaultTimeJob = bdtj;
}
}
@@ -453,7 +449,7 @@ public final class Bane {
return true;
}
public final DateTime getPlacementDate() {
public final LocalDateTime getPlacementDate() {
return placementDate;
}
@@ -462,14 +458,14 @@ public final class Bane {
return (this.getSiegePhase() != SiegePhase.CHALLENGE);
}
public final DateTime getLiveDate() {
public final LocalDateTime getLiveDate() {
return liveDate;
}
public void setLiveDate(DateTime baneTime) {
public void setLiveDate(LocalDateTime baneTime) {
if (DbManager.BaneQueries.SET_BANE_TIME(baneTime, this.getCity().getObjectUUID())) {
this.liveDate = new DateTime(baneTime);
this.liveDate = baneTime;
// Push event to warehouse
@@ -511,7 +507,7 @@ public final class Bane {
ActivateBaneJob abtj = new ActivateBaneJob(cityUUID);
JobScheduler.getInstance().scheduleJob(abtj, this.liveDate.getMillis());
JobScheduler.getInstance().scheduleJob(abtj, this.liveDate.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
this.activateBaneJob = abtj;
} else {
Logger.debug("error with city " + this.getCity().getName());
+1 -39
View File
@@ -10,11 +10,7 @@
package engine.objects;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.net.ByteBufferWriter;
import engine.parsers.objects.RuneTemplate;
import engine.util.Hasher;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -108,42 +104,8 @@ public class BaseClass extends AbstractGameObject {
}
/**
* Rune Template Constructor
*/
public BaseClass(RuneTemplate rune) {
super(rune.template_id);
this.name = rune.obj_name;
this.description = rune.rune_dsc;
this.strMod = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Strength, 0).byteValue();
this.dexMod = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Dexterity, 0).byteValue();
this.conMod = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Constitution, 0).byteValue();
this.intMod = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Intelligence, 0).byteValue();
this.spiMod = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Spirit, 0).byteValue();
this.token = Hasher.SBStringHash(rune.rune_sub_type);
this.healthMod = rune.rune_health;
this.manaMod = rune.rune_mana;
this.staminaMod = rune.rune_stamina;
this.skillsGranted = DbManager.SkillReqQueries.GET_REQS_FOR_RUNE(this.getObjectUUID());
this.powersGranted = PowerReq.getPowerReqsForRune(this.getObjectUUID());
this.effectsList = (DbManager.MobBaseQueries.GET_RUNEBASE_EFFECTS(this.getObjectUUID()));
}
public static void LoadAllBaseClasses() {
int loadedCount = 0;
// Promotion classes and the Pet class are also CLASS runes, but not standard creation runes
for (RuneTemplate rune : RuneTemplate._runes.values()) {
if (rune.rune_type != mbEnums.RuneType.CLASS || !rune.rune_is_standard_character_creation)
continue;
DbManager.addToCache(new BaseClass(rune));
loadedCount++;
}
Logger.info("Loaded " + loadedCount + " base classes from runes");
DbManager.BaseClassQueries.GET_ALL_BASE_CLASSES();
}
public static void serializeForClientMsg(BaseClass baseClass, ByteBufferWriter writer) {
+1 -4
View File
@@ -395,10 +395,8 @@ public class Building extends AbstractWorldObject {
//friendly building has been attacked, add attacker to city outlaw list
if (!playerCity.cityOutlaws.contains(attacker.getObjectUUID()) && attacker.getObjectType().equals(GameObjectType.PlayerCharacter))
playerCity.cityOutlaws.add(attacker.getObjectUUID());
//only city guards respond; siege engines and pets in the zone are left alone
for (Mob guard : playerCity.getParent().zoneMobSet)
if (guard.isPlayerGuard() && guard.combatTarget == null)
if (guard.combatTarget == null)
guard.setCombatTarget(attacker);
}
}
@@ -433,7 +431,6 @@ public class Building extends AbstractWorldObject {
// Special handling of warehouses
if (blueprint.getBuildingGroup() == BuildingGroup.WAREHOUSE) {
Warehouse.destroyedWarehouses.put(this.getObjectUUID(), city.warehouse);
DbManager.WarehouseQueries.DELETE_WAREHOUSE(city.warehouse);
city.warehouse = null;
}
+33 -34
View File
@@ -17,7 +17,6 @@ import engine.mbEnums.ItemType;
import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.*;
import engine.parsers.objects.CObjectTemplate;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
@@ -131,19 +130,19 @@ public class CharacterItemManager {
this.equipped.put(i.equipSlot, i);
break;
case BANK:
if (i.template.getItemType().equals(ItemType.GOLD))
if (i.template.item_type.equals(ItemType.GOLD))
this.goldBank = i;
else if (this.bank.contains(i) == false)
this.bank.add(i);
break;
case INVENTORY:
if (i.template.getItemType().equals(ItemType.GOLD))
if (i.template.item_type.equals(ItemType.GOLD))
this.goldInventory = i;
else if (this.inventory.contains(i) == false)
this.inventory.add(i);
break;
case VAULT:
if (i.template.getItemType().equals(ItemType.GOLD))
if (i.template.item_type.equals(ItemType.GOLD))
this.goldVault = i;
else if (this.vault.contains(i) == false)
this.vault.add(i);
@@ -176,13 +175,13 @@ public class CharacterItemManager {
this.equipped.put(i.equipSlot, i);
break;
case BANK:
if (i.template.getItemType().equals(ItemType.GOLD))
if (i.template.item_type.equals(ItemType.GOLD))
this.goldBank = i;
else if (this.bank.contains(i) == false)
this.bank.add(i);
break;
case INVENTORY:
if (i.template.getItemType().equals(ItemType.GOLD))
if (i.template.item_type.equals(ItemType.GOLD))
this.goldInventory = i;
else if (this.inventory.contains(i) == false)
this.inventory.add(i);
@@ -512,7 +511,7 @@ public class CharacterItemManager {
if (i == null)
return false;
if (i.template.getItemType().equals(ItemType.GOLD)) {
if (i.template.item_type.equals(ItemType.GOLD)) {
if (this.getGoldInventory() != null) {
if (i.getObjectUUID() == this.getGoldInventory().getObjectUUID())
this.goldInventory = null;
@@ -542,7 +541,7 @@ public class CharacterItemManager {
}
private synchronized boolean junk(Item i, boolean updateInventory) {
if (i.template.getItemType().equals(ItemType.GOLD)) {
if (i.template.item_type.equals(ItemType.GOLD)) {
if (this.getGoldInventory().getObjectUUID() == i.getObjectUUID())
if (DbManager.ItemQueries.UPDATE_GOLD(i, 0)) {
this.getGoldInventory().setNumOfItems(0);
@@ -597,7 +596,7 @@ public class CharacterItemManager {
if (equippedContains(item)) {
fromEquip = true;
if (item.template.getItemType().equals(ItemType.GOLD))
if (item.template.item_type.equals(ItemType.GOLD))
this.absCharacter.cancelOnUnEquip();
}
@@ -815,7 +814,7 @@ public class CharacterItemManager {
// This removes ingame item from inventory for loot.
private synchronized boolean removeItemFromInventory(Item i) {
if (i.template.getItemType().equals(ItemType.GOLD)) {
if (i.template.item_type.equals(ItemType.GOLD)) {
if (i.getObjectUUID() != this.getGoldInventory().getObjectUUID())
return false;
if (!DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, 0)) {
@@ -838,7 +837,7 @@ public class CharacterItemManager {
// This adds item to inventory for loot. Validity checks already handled
public synchronized boolean addItemToInventory(Item i) {
if (i.template.getItemType().equals(ItemType.GOLD))
if (i.template.item_type.equals(ItemType.GOLD))
if (this.absCharacter.getObjectType() == GameObjectType.Mob) {
if (this.goldInventory == null)
loadGoldItems();
@@ -857,7 +856,7 @@ public class CharacterItemManager {
this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal());
if (i.template != null)
this.inventoryWeight += i.template.getItemWt();
this.inventoryWeight += i.template.item_wt;
return true;
}
@@ -1042,7 +1041,7 @@ public class CharacterItemManager {
if (npc.getContractID() >= 1900 && npc.getContractID() <= 1906)
eatItem = true;
if (itemToSell.template.getItemType().equals(ItemType.POTION))
if (itemToSell.template.item_type.equals(ItemType.POTION))
eatItem = true;
if (eatItem) {
@@ -1086,14 +1085,14 @@ public class CharacterItemManager {
synchronized (this) {
synchronized (itemMan) {
CObjectTemplate template = purchasedItem.template;
ItemTemplate template = purchasedItem.template;
if (template == null)
return false;
//test inventory is not full
if (!hasRoomInventory(template.getItemWt()))
if (!hasRoomInventory(template.item_wt))
return false;
if (!itemMan.inventory.contains(purchasedItem))
@@ -1106,8 +1105,8 @@ public class CharacterItemManager {
// Reset value
purchasedItem.value = (int) (purchasedItem.template.getItemValue() * (purchasedItem.combat_health_current / purchasedItem.template.getCombatHealthFull()));
purchasedItem.magicValue = purchasedItem.template.getItemValue() + purchasedItem.calcMagicValue();
purchasedItem.value = (int) (purchasedItem.template.item_value * (purchasedItem.combat_health_current / purchasedItem.template.combat_health_full));
purchasedItem.magicValue = purchasedItem.template.item_value + purchasedItem.calcMagicValue();
// db transfer successfully, remove from this character
// skip this check if this is a mobLoot item (which is not in any inventory)
@@ -1185,9 +1184,9 @@ public class CharacterItemManager {
synchronized (lockFirst) {
synchronized (lockSecond) {
// make sure current player has item in inventory
if (lootItem.template.getItemType().equals(ItemType.GOLD) && lootItem.getObjectUUID() != this.getGoldInventory().getObjectUUID() && !(this.absCharacter.getObjectType().equals(GameObjectType.Mob)))
if (lootItem.template.item_type.equals(ItemType.GOLD) && lootItem.getObjectUUID() != this.getGoldInventory().getObjectUUID() && !(this.absCharacter.getObjectType().equals(GameObjectType.Mob)))
return null;
else if (!this.inventory.contains(lootItem) && !this.equipped.containsValue(lootItem) && !lootItem.template.getItemType().equals(ItemType.GOLD))
else if (!this.inventory.contains(lootItem) && !this.equipped.containsValue(lootItem) && !lootItem.template.item_type.equals(ItemType.GOLD))
return null;
// get weight of item
@@ -1195,13 +1194,13 @@ public class CharacterItemManager {
if (lootItem.template == null)
return null;
int weight = lootItem.template.getItemWt();
int weight = lootItem.template.item_wt;
// make sure lootingPlayer has room for item
if (!lootItem.template.getItemType().equals(ItemType.GOLD) && !looterItems.hasRoomInventory(weight))
if (!lootItem.template.item_type.equals(ItemType.GOLD) && !looterItems.hasRoomInventory(weight))
return null;
if (lootItem.template.getItemType().equals(ItemType.GOLD))
if (lootItem.template.item_type.equals(ItemType.GOLD))
if (amount != -1) { //from steal
int total = lootItem.getNumOfItems();
amount = (amount > total) ? total : amount;
@@ -1264,19 +1263,19 @@ public class CharacterItemManager {
* Delegates
*/
public synchronized boolean bankContains(Item item) {
if (item.template.getItemType().equals(ItemType.GOLD))
if (item.template.item_type.equals(ItemType.GOLD))
return (this.getGoldBank() != null && this.goldBank.getObjectUUID() == item.getObjectUUID());
return bank.contains(item);
}
public synchronized boolean inventoryContains(Item item) {
if (item.template.getItemType().equals(ItemType.GOLD))
if (item.template.item_type.equals(ItemType.GOLD))
return (this.getGoldInventory() != null && this.goldInventory.getObjectUUID() == item.getObjectUUID());
return inventory.contains(item);
}
public synchronized boolean vaultContains(Item item) {
if (item.template.getItemType().equals(ItemType.GOLD))
if (item.template.item_type.equals(ItemType.GOLD))
return (this.getGoldVault() != null && this.goldVault.getObjectUUID() == item.getObjectUUID());
return this.account.getVault().contains(item);
}
@@ -1519,13 +1518,13 @@ public class CharacterItemManager {
item.zeroItem();
item.containerType = mbEnums.ItemContainerType.INVENTORY;
if (item.template.getItemType().equals(ItemType.GOLD))
if (item.template.item_type.equals(ItemType.GOLD))
//only add gold item once
if (!corpse.hasGold())
corpse.setHasGold(true);
newInventory.add(item);
} else //item
if (item.template.getItemType().equals(ItemType.GOLD)) {
if (item.template.item_type.equals(ItemType.GOLD)) {
int amt = item.getNumOfItems();
item.setNumOfItems(0);
MobLoot ml = new MobLoot(this.absCharacter, amt);
@@ -1677,7 +1676,7 @@ public class CharacterItemManager {
if (item == null)
continue;
weight += item.template.getItemWt();
weight += item.template.item_wt;
}
return weight;
}
@@ -1697,7 +1696,7 @@ public class CharacterItemManager {
this.bankWeight = 0;
for (Item item : this.bank) {
if (item.template != null)
this.bankWeight += item.template.getItemWt();
this.bankWeight += item.template.item_wt;
}
}
@@ -1708,7 +1707,7 @@ public class CharacterItemManager {
while (it.hasNext()) {
Item item = it.next();
if (item.template != null)
this.equipWeight += item.template.getItemWt();
this.equipWeight += item.template.item_wt;
}
}
@@ -1716,7 +1715,7 @@ public class CharacterItemManager {
this.inventoryWeight = 0;
for (Item item : this.inventory) {
if (item.template != null)
this.inventoryWeight += item.template.getItemWt();
this.inventoryWeight += item.template.item_wt;
}
}
@@ -1724,7 +1723,7 @@ public class CharacterItemManager {
this.vaultWeight = 0;
for (Item item : this.vault) {
if (item.template != null)
this.vaultWeight += item.template.getItemWt();
this.vaultWeight += item.template.item_wt;
}
}
@@ -1756,7 +1755,7 @@ public class CharacterItemManager {
return;
if (!item.moveItemToInventory(player))
Logger.error("templateL " + item.template.getTemplateId());
Logger.error("templateL " + item.template.template_id);
// remove it from other lists:
this.remItemFromLists(item);
@@ -1933,7 +1932,7 @@ public class CharacterItemManager {
return;
//don't damage noob gear, hair or beards.
if (item.template.getCombatHealthFull() == 0)
if (item.template.combat_health_full == 0)
return;
if (!item.isCanDestroy())
+3 -3
View File
@@ -296,14 +296,14 @@ public class Corpse extends AbstractWorldObject {
//get weight of item
int weight = item.template.getItemWt();
int weight = item.template.item_wt;
//make sure looter has room for item
if (item.template.getItemType().equals(ItemType.GOLD) == false && !looterItems.hasRoomInventory(weight))
if (item.template.item_type.equals(ItemType.GOLD) == false && !looterItems.hasRoomInventory(weight))
return null;
//attempt to transfer item in db
if (item.template.getItemType().equals(ItemType.GOLD)) {
if (item.template.item_type.equals(ItemType.GOLD)) {
if (!looterItems.moveGoldToInventory(item, item.getNumOfItems()))
return null;
} else if (!item.moveItemToInventory(looter))
+3 -3
View File
@@ -22,7 +22,7 @@ import engine.net.client.msg.ErrorPopupMsg;
import engine.net.client.msg.UpdateClientAlliancesMsg;
import engine.net.client.msg.guild.GuildInfoMsg;
import engine.server.world.WorldServer;
import org.joda.time.DateTime;
import java.time.Instant;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
@@ -612,8 +612,8 @@ public class Guild extends AbstractWorldObject {
//Add to Guild History
if (pc.getGuild() != null) {
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(pc.getGuildUUID(), pc, DateTime.now(), historyType)) {
GuildHistory guildHistory = new GuildHistory(pc.getGuildUUID(), pc.getGuild().name, DateTime.now(), historyType);
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(pc.getGuildUUID(), pc, Instant.now(), historyType)) {
GuildHistory guildHistory = new GuildHistory(pc.getGuildUUID(), pc.getGuild().name, Instant.now(), historyType);
pc.getGuildHistory().add(guildHistory);
}
}
+8 -7
View File
@@ -13,10 +13,11 @@ package engine.objects;
import engine.mbEnums.GameObjectType;
import engine.mbEnums.GuildHistoryType;
import engine.net.ByteBufferWriter;
import org.joda.time.DateTime;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
public class GuildHistory {
@@ -24,12 +25,12 @@ public class GuildHistory {
private int guildID;
private String guildName;
private DateTime time;
private Instant time;
private GuildHistoryType historyType;
public GuildHistory(int guildID, String guildName,
DateTime dateTime, GuildHistoryType historyType) {
Instant dateTime, GuildHistoryType historyType) {
super();
this.guildID = guildID;
this.guildName = guildName;
@@ -49,9 +50,9 @@ public class GuildHistory {
sqlDateTime = rs.getTimestamp("historyDate");
if (sqlDateTime != null)
this.time = new DateTime(sqlDateTime);
this.time = sqlDateTime.toInstant();
else
this.time = DateTime.now().minusYears(1);
this.time = Instant.now().minus(1, ChronoUnit.YEARS);
this.historyType = GuildHistoryType.valueOf(rs.getString("historyType"));
}
@@ -77,11 +78,11 @@ public class GuildHistory {
writer.putDateTime(this.time);
}
public DateTime getTime() {
public Instant getTime() {
return time;
}
public void setTime(DateTime time) {
public void setTime(Instant time) {
this.time = time;
}
+23 -30
View File
@@ -20,8 +20,6 @@ import engine.net.ByteBufferWriter;
import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.DeleteItemMsg;
import engine.parsers.objects.CObjectTemplate;
import engine.parsers.objects.UserPowerAction;
import engine.powers.EffectsBase;
import engine.powers.effectmodifiers.AbstractEffectModifier;
import engine.powers.poweractions.AbstractPowerAction;
@@ -33,7 +31,6 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
@@ -58,7 +55,7 @@ public class Item extends AbstractWorldObject {
public int templateID;
private long dateToUpgrade;
public int magicValue;
public CObjectTemplate template;
public ItemTemplate template;
public String name = "";
public int prefixToken; // Forge support
public int suffixToken; // Forge support
@@ -71,14 +68,14 @@ public class Item extends AbstractWorldObject {
public Item(int templateID) {
super();
this.templateID = templateID;
this.template = CObjectTemplate.lookup(templateID);
this.chargesRemaining = this.template.getItemInitialCharges();
this.combat_health_current = this.template.getCombatHealthFull();
this.template = ItemTemplate.templates.get(templateID);
this.chargesRemaining = this.template.item_initial_charges;
this.combat_health_current = this.template.combat_health_full;
this.equipSlot = EquipSlotType.NONE;
this.containerType = ItemContainerType.NONE;
this.numberOfItems = 1;
this.flags.addAll(this.template.getItemFlags());
this.value = this.template.getItemValue();
this.flags.addAll(this.template.item_flags);
this.value = this.template.item_value;
this.magicValue = this.value + calcMagicValue();
loadTemplateEnchantments();
}
@@ -90,7 +87,7 @@ public class Item extends AbstractWorldObject {
super(rs);
this.templateID = rs.getInt("templateID");
this.template = CObjectTemplate.lookup(this.templateID);
this.template = ItemTemplate.templates.get(this.templateID);
if (this.template == null)
Logger.error("Null template of " + this.templateID);
@@ -169,7 +166,7 @@ public class Item extends AbstractWorldObject {
this.value = rs.getInt("value");
if (this.value == 0) {
this.value = this.template.getItemValue();
this.value = this.template.item_value;
this.magicValue = this.value + calcMagicValue();
} else
this.magicValue = this.value; // Value was overridden in vendor inventory
@@ -241,7 +238,7 @@ public class Item extends AbstractWorldObject {
writer.putString(item.name); // Unknown. pad?
writer.put((byte) 1); // End Datablock byte
writer.putFloat(item.template.getCombatHealthFull());
writer.putFloat(item.template.combat_health_full);
writer.putFloat((float) item.combat_health_current);
writer.put((byte) 1); // End Datablock byte
@@ -258,7 +255,7 @@ public class Item extends AbstractWorldObject {
} else
writer.putInt(item.numberOfItems); // Amount of gold
} else
writer.putInt(item.template.getItemValue());
writer.putInt(item.template.item_value);
writer.putInt(item.getValue());
@@ -291,7 +288,7 @@ public class Item extends AbstractWorldObject {
writer.putInt(36); //Magical, blue name
else
writer.putInt(40); //Magical, unidentified
else if (item.template.getItemUserPowerAction().isEmpty() == false)
else if (item.template.item_user_power_action.size() > 0)
writer.putInt(36); //Magical, blue name
else
writer.putInt(4); //Non-Magical, grey name
@@ -301,7 +298,7 @@ public class Item extends AbstractWorldObject {
writer.put((byte) 0);
if (item.template.getItemType().equals(ItemType.EMPLOYMENTCONTRACT) == false) {
if (item.template.item_type.equals(ItemType.EMPLOYMENTCONTRACT) == false) {
writer.putShort((short) 0);
return;
}
@@ -466,7 +463,7 @@ public class Item extends AbstractWorldObject {
int serialized = 0;
for (Item item : list) {
if (item.template.getItemType().equals(ItemType.GOLD))
if (item.template.item_type.equals(ItemType.GOLD))
if (item.numberOfItems == 0)
continue;
try {
@@ -500,7 +497,7 @@ public class Item extends AbstractWorldObject {
int serialized = 0;
for (Item item : list) {
if (item.template.getItemType().equals(ItemType.GOLD))
if (item.template.item_type.equals(ItemType.GOLD))
if (item.numberOfItems == 0)
continue;
try {
@@ -934,16 +931,12 @@ public class Item extends AbstractWorldObject {
private void loadTemplateEnchantments() {
EffectsBase effect;
LinkedHashMap<String, int[]> templateEnchantments = new LinkedHashMap<>();
if (ConfigManager.serverType.equals(mbEnums.ServerType.LOGINSERVER))
return;
// Duplicate powers collapse to the last entry; applying one twice would double its magic value.
for (UserPowerAction userPowerAction : this.template.getItemUserPowerAction())
templateEnchantments.put(userPowerAction.power, userPowerAction.arguments);
for (String effectID : templateEnchantments.keySet()) {
for (String effectID : this.template.item_user_power_action.keySet()) {
effect = PowersManager.getEffectByIDString(effectID);
@@ -953,7 +946,7 @@ public class Item extends AbstractWorldObject {
}
AbstractPowerAction apa = PowersManager.getPowerActionByIDString(effect.getIDString());
apa.applyBakedInStatsForItem(this, templateEnchantments.get(effectID)[0]);
apa.applyBakedInStatsForItem(this, this.template.item_user_power_action.get(effectID)[0]);
}
}
@@ -962,7 +955,7 @@ public class Item extends AbstractWorldObject {
// No enchantments for negative id items in the db. Early exit.
if (this.objectUUID < 0) {
this.magicValue = this.template.getItemValue() + calcMagicValue();
this.magicValue = this.template.item_value + calcMagicValue();
return;
}
@@ -978,8 +971,8 @@ public class Item extends AbstractWorldObject {
// Value is overridden the db
if (this.value == this.template.getItemValue())
this.magicValue = this.template.getItemValue() + calcMagicValue();
if (this.value == this.template.item_value)
this.magicValue = this.template.item_value + calcMagicValue();
}
public void addPermanentEnchantment(String enchantID, int rank) {
@@ -1123,11 +1116,11 @@ public class Item extends AbstractWorldObject {
else
modifiedValue = this.value;
if (this.template.getItemInitialCharges() > 0)
modifiedValue = modifiedValue * (this.chargesRemaining / this.template.getItemInitialCharges());
if (this.template.item_initial_charges > 0)
modifiedValue = modifiedValue * (this.chargesRemaining / this.template.item_initial_charges);
if (this.template.getCombatHealthFull() > 0)
modifiedValue = (int) (modifiedValue * (this.combat_health_current / this.template.getCombatHealthFull()));
if (this.template.combat_health_full > 0)
modifiedValue = (int) (modifiedValue * (this.combat_health_current / this.template.combat_health_full));
return modifiedValue;
}
+623
View File
@@ -0,0 +1,623 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.objects;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import org.json.JSONArray;
import org.json.JSONObject;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
public class ItemTemplate {
// MB Dev Notes:
// This class parses JSON data generated by mbEditor Pro 2.1.
// Cache definitions are loaded for ItemType.ITEM, ItemType,DEED
// and ItemType.RUNE.
//
// Exported JSON data is stored in db table static_item_templates
// and can be easily mass updated using tooling available on the Wiki.
//
// Always read never write!
// Use copies of fields to avoid side effects.
// Global template lookup
public static HashMap<Integer, ItemTemplate> templates = new HashMap<>();
public int template_id;
// Template Properties
public String obj_name;
public boolean obj_pickable;
public Vector3fImmutable obj_scale;
public Vector3fImmutable obj_forward_vector;
public Vector3fImmutable obj_default_alignment;
public int obj_render_object;
public int obj_icon;
public final HashMap<String, String> obj_sparse_data = new HashMap<>();
public float combat_health_current;
public float combat_health_full;
public final HashMap<String, Float> combat_attack_resist = new HashMap<>();
public mbEnums.ItemType item_type;
public int item_eq_slots_value;
public boolean item_eq_slots_type;
public final EnumSet<mbEnums.EquipSlotType> item_eq_slots_or = EnumSet.noneOf(mbEnums.EquipSlotType.class);
public final EnumSet<mbEnums.EquipSlotType> item_eq_slots_and = EnumSet.noneOf(mbEnums.EquipSlotType.class);
public boolean item_takeable;
public int item_value;
public int item_wt;
public float item_passive_defense_mod;
public String item_base_name;
public String item_dsc;
public int item_render_object_female;
public float item_health_full;
public String item_skill_used = "";
public String item_skill_mastery_used = "";
public int item_parry_anim_id;
public float item_bulk_factor;
public final HashMap<mbEnums.ShrineType, Integer> item_offering_info = new HashMap<>();
public int item_defense_rating;
public float item_weapon_wepspeed;
public float item_weapon_max_range;
public int item_weapon_projectile_id;
public float item_weapon_projectile_speed;
public int item_weapon_combat_idle_anim;
public final HashMap<mbEnums.DamageType, int[]> item_weapon_damage = new HashMap<>();
public final ArrayList<int[]> weapon_attack_anim_right = new ArrayList<>();
public final ArrayList<int[]> weapon_attack_anim_left = new ArrayList<>();
public mbEnums.AttributeType item_primary_attr = mbEnums.AttributeType.None;
public mbEnums.AttributeType item_secondary_attr = mbEnums.AttributeType.None;
public final EnumSet<mbEnums.ItemFlags> item_flags = EnumSet.noneOf(mbEnums.ItemFlags.class);
public final EnumSet<mbEnums.ItemUseFlags> item_use_flags = EnumSet.noneOf(mbEnums.ItemUseFlags.class);
public int item_initial_charges;
public final HashMap<String, Integer> item_skill_required = new HashMap<>();
public final EnumSet<mbEnums.MonsterType> item_race_req = EnumSet.noneOf(mbEnums.MonsterType.class);
public final EnumSet<mbEnums.MonsterType> item_race_res = EnumSet.noneOf(mbEnums.MonsterType.class);
public final EnumSet<mbEnums.ClassType> item_class_req = EnumSet.noneOf(mbEnums.ClassType.class);
public final EnumSet<mbEnums.ClassType> item_class_res = EnumSet.noneOf(mbEnums.ClassType.class);
public final EnumSet<mbEnums.DisciplineType> item_disc_req = EnumSet.noneOf(mbEnums.DisciplineType.class);
public final EnumSet<mbEnums.DisciplineType> item_disc_res = EnumSet.noneOf(mbEnums.DisciplineType.class);
public int item_level_req;
public mbEnums.SexType item_sex_req;
public final HashMap<String, int[]> item_user_power_action = new HashMap<>();
public final HashMap<String, Integer> item_power_grant = new HashMap<>();
public final HashMap<String, int[]> item_power_action = new HashMap<>();
public final HashMap<mbEnums.ResourceType, Integer> item_resource_cost = new HashMap<>();
public int modTable;
public int deed_type;
public int deed_furniture_id;
public int deed_target_id;
public int deed_employment;
public int deed_start_rank;
public int deed_name_lookup;
public boolean deed_indoors;
public boolean deed_is_fortress;
public float deed_namelookup_val;
public boolean deed_custom_city;
public int deed_structure_id;
public final HashMap<mbEnums.AttributeType, Integer> rune_attr_adj = new HashMap<>();
public final HashMap<mbEnums.AttributeType, Integer> rune_max_attr_adj = new HashMap<>();
public final HashMap<String, Integer> rune_skill_grant = new HashMap<>();
public final HashMap<String, Integer> skill_granted_skills = new HashMap<>();
public final HashMap<String, Integer> power_granted_skills = new HashMap<>();
public String rune_type;
public String rune_sub_type;
public boolean rune_is_standard_character_creation = false;
public int rune_creation_cost;
public int rune_rank;
public int rune_pracs_per_level;
public float rune_exp_req_to_level;
public mbEnums.SexType rune_sex;
public int rune_class_icon;
public int rune_health;
public int rune_mana;
public int rune_stamina;
public float rune_min_damage;
public float rune_max_damage;
public int rune_attack;
public int rune_defense;
public int rune_level;
public final HashMap<mbEnums.MovementType, Float> rune_speed = new HashMap<>();
public int rune_group_type;
public boolean rune_group_is_faction = false;
public boolean rune_group_is_guild = false;
public String rune_dsc;
public String rune_fx_txt;
public final EnumSet<mbEnums.MobBehaviourType> rune_group_tactics = EnumSet.noneOf(mbEnums.MobBehaviourType.class);
public final EnumSet<mbEnums.MobBehaviourType> rune_group_role_set = EnumSet.noneOf(mbEnums.MobBehaviourType.class);
public boolean rune_renderable = false;
public int rune_natural_power_attack;
public final HashMap<String, String> rune_sparse_data = new HashMap<>();
public final HashMap<String, int[]> rune_skill_adj = new HashMap<>();
public final EnumSet<mbEnums.MonsterType> rune_enemy_monster_types = EnumSet.noneOf(mbEnums.MonsterType.class);
public final EnumSet<mbEnums.MonsterType> rune_not_enemy_monster_types = EnumSet.noneOf(mbEnums.MonsterType.class);
public final ArrayList<Integer> rune_groupee_monster_types = new ArrayList<>();
public final ArrayList<Integer> rune_helper_monster_types = new ArrayList<>();
public int item_bane_rank;
public ItemTemplate(JSONObject jsonObject) {
try {
// Reading a String
obj_name = jsonObject.getString("obj_name");
// Reading a boolean
obj_pickable = jsonObject.getBoolean("obj_pickable");
// Reading floats from an array (note always check for empty arrays)
JSONArray scaleData = jsonObject.getJSONArray("obj_scale");
if (scaleData.isEmpty() == false)
obj_scale = new Vector3fImmutable(scaleData.getFloat(0), scaleData.getFloat(1),
scaleData.getFloat(2));
JSONArray forwardVector = jsonObject.getJSONArray("obj_forward_vector");
if (forwardVector.isEmpty() == false)
obj_forward_vector = new Vector3fImmutable(forwardVector.getFloat(0), forwardVector.getFloat(1),
forwardVector.getFloat(2));
JSONArray defaultAlignment = jsonObject.getJSONArray("obj_default_alignment");
if (defaultAlignment.isEmpty() == false)
obj_default_alignment = new Vector3fImmutable(defaultAlignment.getFloat(0), defaultAlignment.getFloat(1),
defaultAlignment.getFloat(2));
// Reading an integer value
obj_render_object = jsonObject.getInt("obj_render_object");
obj_icon = jsonObject.getInt("obj_icon");
JSONObject obj_sparse_json = jsonObject.getJSONObject("obj_sparse_data");
for (String sparseType : obj_sparse_json.keySet()) {
Object sparseValue = obj_sparse_json.get(sparseType);
obj_sparse_data.put(sparseType, sparseValue.toString());
}
// Banes are defined by their sparse data field
if (obj_sparse_data.get("ACTIONRESPONSE") != null)
if (obj_sparse_data.get("ACTIONRESPONSE").equals("4250517122"))
item_bane_rank = jsonObject.getInt("item_bane_rank");
// Reading float values
combat_health_current = jsonObject.getFloat("combat_health_current");
combat_health_full = jsonObject.getFloat("combat_health_full");
// Reading a hashmap of floats
JSONObject resist_json = jsonObject.getJSONObject("combat_attack_resist");
for (String resistType : resist_json.keySet()) {
float resistValue = resist_json.getFloat(resistType);
combat_attack_resist.put(resistType, resistValue);
}
// Parsing an enum
item_type = mbEnums.ItemType.valueOf(jsonObject.getString("item_type"));
item_eq_slots_value = jsonObject.getInt("item_eq_slots_value");
item_eq_slots_type = jsonObject.getBoolean("item_eq_slots_type");
// Parsing an enumset
JSONArray eq_slots_or = jsonObject.getJSONArray("item_eq_slots_or");
if (eq_slots_or.isEmpty() == false)
for (Object o : eq_slots_or)
item_eq_slots_or.add(mbEnums.EquipSlotType.valueOf((String) o));
JSONArray eq_slots_and = jsonObject.getJSONArray("item_eq_slots_and");
if (eq_slots_and.isEmpty() == false)
for (Object o : eq_slots_and)
item_eq_slots_and.add(mbEnums.EquipSlotType.valueOf((String) o));
item_takeable = jsonObject.getBoolean("item_takeable");
item_value = (jsonObject.getInt("item_value"));
item_wt = jsonObject.getInt("item_wt");
item_passive_defense_mod = jsonObject.getFloat("item_passive_defense_mod");
item_base_name = jsonObject.getString("item_base_name");
item_dsc = jsonObject.getString("item_dsc");
item_render_object_female = jsonObject.getInt("item_render_object_female");
item_health_full = jsonObject.getFloat("item_health_full");
Object skill_used = jsonObject.get("item_skill_used");
if (skill_used instanceof String) {
if (skill_used.equals("Cloth") == false)
item_skill_used = (String) skill_used;
}
Object mastery_used = jsonObject.get("item_skill_mastery_used");
if (mastery_used instanceof String)
item_skill_mastery_used = (String) mastery_used;
item_parry_anim_id = jsonObject.getInt("item_parry_anim_id");
// Reading offering data
JSONArray offering_data = jsonObject.getJSONArray("item_offering_info");
for (Object entry : offering_data) {
JSONObject offering_entry = (JSONObject) entry;
String offering_type = offering_entry.getString("offering_type").replaceAll("-", "");
int offering_value = offering_entry.getInt("offering_value");
item_offering_info.put(mbEnums.ShrineType.valueOf(offering_type), offering_value);
}
// Fields only present for ARMOR
if (item_type.equals(mbEnums.ItemType.ARMOR)) {
item_bulk_factor = jsonObject.getFloat("item_bulk_factor");
item_defense_rating = jsonObject.getInt("item_defense_rating");
}
// Fields only present for WEAPON
if (item_type.equals(mbEnums.ItemType.WEAPON)) {
JSONObject item_weapon = jsonObject.getJSONObject("item_weapon");
item_weapon_wepspeed = item_weapon.getFloat("weapon_wepspeed");
item_weapon_max_range = item_weapon.getFloat("weapon_max_range");
item_weapon_projectile_id = item_weapon.getInt("weapon_projectile_id");
item_weapon_projectile_speed = item_weapon.getFloat("weapon_projectile_speed");
item_weapon_combat_idle_anim = item_weapon.getInt("weapon_combat_idle_anim");
JSONArray weapon_damage = item_weapon.getJSONArray("weapon_damage");
if (weapon_damage.isEmpty() == false)
for (Object o : weapon_damage) {
JSONObject damage_entry = (JSONObject) o;
mbEnums.DamageType damageType = mbEnums.DamageType.getDamageType(damage_entry.getString("damage_type"));
int min = damage_entry.getInt("damage_min");
int max = damage_entry.getInt("damage_max");
int[] minMax = {min, max};
item_weapon_damage.put(damageType, minMax);
}
JSONArray attack_anim_right = item_weapon.getJSONArray("weapon_attack_anim_right");
if (attack_anim_right.isEmpty() == false)
for (Object o : attack_anim_right) {
JSONArray animationEntry = (JSONArray) o;
int animation = animationEntry.getInt(0);
int duration = animationEntry.getInt(1);
weapon_attack_anim_right.add(new int[]{animation, duration});
}
JSONArray attack_anim_left = item_weapon.getJSONArray("weapon_attack_anim_left");
if (attack_anim_left.isEmpty() == false)
for (Object o : attack_anim_left) {
JSONArray animationEntry = (JSONArray) o;
int animation = animationEntry.getInt(0);
int duration = animationEntry.getInt(1);
weapon_attack_anim_left.add(new int[]{animation, duration});
}
item_primary_attr = mbEnums.AttributeType.valueOf(jsonObject.getString("item_primary_attr"));
item_secondary_attr = mbEnums.AttributeType.valueOf(jsonObject.getString("item_secondary_attr"));
}
JSONArray itemflags = jsonObject.getJSONArray("item_flags");
if (itemflags.isEmpty() == false)
for (Object o : itemflags) {
String flag = (String) o;
if (flag.equals("None") == false)
item_flags.add(mbEnums.ItemFlags.valueOf((String) o));
}
JSONArray itemUseflags = jsonObject.getJSONArray("item_use_flags");
if (itemUseflags.isEmpty() == false)
for (Object o : itemUseflags)
item_use_flags.add(mbEnums.ItemUseFlags.valueOf((String) o));
item_initial_charges = jsonObject.getInt("item_initial_charges");
JSONArray skill_required = jsonObject.getJSONArray("item_skill_req");
if (skill_required.isEmpty() == false)
for (Object o : skill_required) {
JSONObject skill_req = (JSONObject) o;
String skill_type = skill_req.getString("skill_type");
int skill_level = skill_req.getInt("skill_level");
if (skill_type.equals("Cloth") == false)
item_skill_required.put(skill_type, skill_level);
}
JSONObject race_required = jsonObject.getJSONObject("item_race_req");
boolean restrict = race_required.getBoolean("restrict");
JSONArray races = race_required.getJSONArray("races");
if (races.isEmpty() == false)
for (Object o : races) {
String race = (String) o;
race = race.replaceAll("\\s", "");
race = race.replaceAll(",", "");
race = race.replaceAll("-", "");
if (restrict)
item_race_res.add(mbEnums.MonsterType.valueOf(race));
else
item_race_req.add(mbEnums.MonsterType.valueOf(race));
}
JSONObject class_required = jsonObject.getJSONObject("item_class_req");
restrict = class_required.getBoolean("restrict");
JSONArray classes = class_required.getJSONArray("classes");
if (classes.isEmpty() == false)
for (Object o : classes) {
String classEntry = (String) o;
classEntry = classEntry.replaceAll("\\s", "");
classEntry = classEntry.replaceAll(",", "");
if (restrict)
item_class_res.add(mbEnums.ClassType.valueOf(classEntry));
else
item_class_req.add(mbEnums.ClassType.valueOf(classEntry));
}
JSONObject disc_required = jsonObject.getJSONObject("item_disc_req");
restrict = disc_required.getBoolean("restrict");
JSONArray discs = disc_required.getJSONArray("discs");
if (discs.isEmpty() == false)
for (Object o : discs) {
String disc = (String) o;
disc = disc.replaceAll("\\s", "");
disc = disc.replaceAll(",", "");
if (restrict)
item_disc_res.add(mbEnums.DisciplineType.valueOf(disc));
else
item_disc_req.add(mbEnums.DisciplineType.valueOf(disc));
}
item_level_req = jsonObject.getInt("item_level_req");
item_sex_req = mbEnums.SexType.valueOf(jsonObject.getString("item_sex_req"));
JSONArray userPowerActions = jsonObject.getJSONArray("item_user_power_action");
if (userPowerActions.isEmpty() == false)
for (Object o : userPowerActions) {
JSONObject powerActionEntry = (JSONObject) o;
String power = powerActionEntry.getString("power");
JSONArray args = powerActionEntry.getJSONArray("arguments");
int[] arguments = {args.getInt(0), args.getInt(1)};
item_user_power_action.put(power, arguments);
}
JSONArray powerGrantsArray = jsonObject.getJSONArray("item_power_grant");
if (powerGrantsArray.isEmpty() == false) {
for (Object grantArrayEntry : powerGrantsArray) {
JSONObject powerGrantEntry = (JSONObject) grantArrayEntry;
String power_type = powerGrantEntry.getString("power_type");
int power_value = powerGrantEntry.getInt("power_value");
item_power_grant.put(power_type, power_value);
JSONArray skill_granted_array = powerGrantEntry.getJSONArray("power_granted_skills");
for (Object skillGrantEntry : skill_granted_array) {
JSONArray skill_entry = (JSONArray) skillGrantEntry;
String skill_type = skill_entry.getString(0);
int skill_level = skill_entry.getInt(1);
power_granted_skills.put(skill_type, skill_level);
}
}
}
JSONArray item_power_actions = jsonObject.getJSONArray("item_power_action");
if (item_power_actions.isEmpty() == false)
for (Object o : item_power_actions) {
JSONObject powerActionEntry = (JSONObject) o;
String power = powerActionEntry.getString("power_type");
JSONArray power_actions = powerActionEntry.getJSONArray("power_actions");
JSONObject argument_entry = power_actions.getJSONObject(0);
JSONArray power_args = argument_entry.getJSONArray("power_arguments");
int[] power_arguments = {power_args.getInt(0), power_args.getInt(1)};
item_power_action.put(power, power_arguments);
}
JSONArray resource_costs = jsonObject.getJSONArray("item_resource_costs");
if (resource_costs.isEmpty() == false)
for (Object o : resource_costs) {
JSONObject resource_entry = (JSONObject) o;
mbEnums.ResourceType resource_type = mbEnums.ResourceType.valueOf(resource_entry.getString("resource_type").toUpperCase());
int resource_value = resource_entry.getInt("resource_value");
item_resource_cost.put(resource_type, resource_value);
}
// Deed related fields
if (item_type.equals(mbEnums.ItemType.DEED)) {
deed_type = jsonObject.getInt("deed_type");
deed_furniture_id = jsonObject.getInt("deed_furniture_id");
deed_target_id = jsonObject.getInt("deed_target_id");
deed_employment = jsonObject.getInt("deed_employment");
deed_start_rank = jsonObject.getInt("deed_start_rank");
deed_name_lookup = jsonObject.getInt("deed_name_lookup");
deed_indoors = jsonObject.getBoolean("deed_indoors");
deed_is_fortress = jsonObject.getBoolean("deed_is_fortress");
deed_namelookup_val = jsonObject.getFloat("deed_namelookup_val");
deed_custom_city = jsonObject.getBoolean("deed_custom_city");
deed_structure_id = jsonObject.getInt("deed_structure_id");
}
if (item_type.equals(mbEnums.ItemType.RUNE)) {
rune_type = jsonObject.getString("rune_type");
Object subType = jsonObject.get("rune_sub_type");
if (subType instanceof String)
rune_sub_type = (String) subType;
rune_is_standard_character_creation = jsonObject.getBoolean("rune_is_standard_character_creation");
rune_creation_cost = jsonObject.getInt("rune_creation_cost");
rune_rank = jsonObject.getInt("rune_rank");
rune_pracs_per_level = jsonObject.getInt("rune_pracs_per_level");
rune_exp_req_to_level = jsonObject.getFloat("rune_exp_req_to_level");
rune_sex = mbEnums.SexType.valueOf(jsonObject.getString("rune_sex"));
rune_class_icon = jsonObject.getInt("rune_class_icon");
rune_health = jsonObject.getInt("rune_health");
rune_mana = jsonObject.getInt("rune_mana");
rune_stamina = jsonObject.getInt("rune_stamina");
rune_min_damage = jsonObject.getFloat("rune_min_damage");
rune_max_damage = jsonObject.getFloat("rune_max_damage");
rune_attack = jsonObject.getInt("rune_attack");
rune_defense = jsonObject.getInt("rune_defense");
rune_level = jsonObject.getInt("rune_level");
JSONObject rune_speed_json = jsonObject.getJSONObject("rune_speed");
for (String key : rune_speed_json.keySet()) {
mbEnums.MovementType movementType = mbEnums.MovementType.valueOf(key);
float speed = rune_speed_json.getFloat(key);
rune_speed.put(movementType, speed);
}
JSONObject rune_group = jsonObject.getJSONObject("rune_group");
rune_group_type = rune_group.getInt("group_type");
rune_group_is_faction = rune_group.getBoolean("group_is_faction");
rune_group_is_guild = rune_group.getBoolean("group_is_guild");
rune_dsc = jsonObject.getString("rune_dsc");
rune_fx_txt = jsonObject.getString("rune_fx_txt");
long group_tactics_bitvector = jsonObject.getLong("rune_group_tactics");
rune_group_tactics.addAll(mbEnums.fromLong(group_tactics_bitvector, mbEnums.MobBehaviourType.class));
long group_role_bitvector = jsonObject.getLong("rune_group_role_set");
rune_group_role_set.addAll(mbEnums.fromLong(group_role_bitvector, mbEnums.MobBehaviourType.class));
JSONArray enemy_types_json = jsonObject.getJSONArray("rune_enemy_monster_types");
for (Object o : enemy_types_json) {
String enemy = (String) o;
enemy = enemy.replaceAll("-", "");
mbEnums.MonsterType monsterType = mbEnums.MonsterType.valueOf(enemy);
rune_enemy_monster_types.add(monsterType);
}
JSONArray not_enemy_types_json = jsonObject.getJSONArray("rune_not_enemy_monster_types");
for (Object o : not_enemy_types_json) {
String notenemy = (String) o;
notenemy = notenemy.replaceAll("-", "");
mbEnums.MonsterType monsterType = mbEnums.MonsterType.valueOf(notenemy);
rune_not_enemy_monster_types.add(monsterType);
}
JSONArray groupee_types_json = jsonObject.getJSONArray("rune_groupee_monster_types");
for (Object o : groupee_types_json) {
int groupeeId = (int) o;
rune_groupee_monster_types.add(groupeeId);
}
JSONArray helper_types_json = jsonObject.getJSONArray("rune_helper_monster_types");
for (Object o : helper_types_json) {
int helperId = (int) o;
rune_helper_monster_types.add(helperId);
}
rune_renderable = jsonObject.getBoolean("rune_renderable");
rune_natural_power_attack = jsonObject.getInt("rune_natural_power_attack");
JSONObject rune_sparse_json = jsonObject.getJSONObject("rune_sparse_data");
for (String sparseType : rune_sparse_json.keySet()) {
Object sparseValue = rune_sparse_json.get(sparseType);
rune_sparse_data.put(sparseType, sparseValue.toString());
}
JSONArray skill_adj_json = (JSONArray) jsonObject.get("rune_skill_adj");
for (Object skillEntry : skill_adj_json) {
JSONObject skill = (JSONObject) skillEntry;
String typeString = skill.getString("skill_type");
JSONArray adjArray = skill.getJSONArray("skill_adjusts");
for (Object adjustList : adjArray) {
JSONArray adjustEntry = (JSONArray) adjustList;
int[] adjust = {adjustEntry.getInt(0), adjustEntry.getInt(1)};
rune_skill_adj.put(typeString, adjust);
}
}
JSONArray attr_adj_json = jsonObject.getJSONArray("rune_attr_adj");
for (Object attributeEntry : attr_adj_json) {
JSONObject attribute = (JSONObject) attributeEntry;
String typeString = attribute.getString("attr_type");
mbEnums.AttributeType attributeType = mbEnums.AttributeType.valueOf(typeString);
int attributeValue = attribute.getInt("attr_value");
rune_attr_adj.put(attributeType, attributeValue);
}
JSONArray max_attr_adj_json = jsonObject.getJSONArray("rune_max_attr_adj");
for (Object attributeEntry : max_attr_adj_json) {
JSONObject attribute = (JSONObject) attributeEntry;
String typeString = attribute.getString("attr_type");
mbEnums.AttributeType attributeType = mbEnums.AttributeType.valueOf(typeString);
int attributeValue = attribute.getInt("attr_value");
rune_max_attr_adj.put(attributeType, attributeValue);
}
JSONArray skill_grant_json = jsonObject.getJSONArray("rune_skill_grant");
if (skill_grant_json.isEmpty() == false)
for (Object runeSkillEntry : skill_grant_json) {
JSONObject skill_granted = (JSONObject) runeSkillEntry;
String typeString = skill_granted.getString("skill_type");
int skill_level = skill_granted.getInt("skill_value");
rune_skill_grant.put(typeString, skill_level);
JSONArray skill_granted_array = skill_granted.getJSONArray("skill_granted_skills");
for (Object skillGrantEntry : skill_granted_array) {
JSONArray skill_entry = (JSONArray) skillGrantEntry;
typeString = skill_entry.getString(0);
skill_level = skill_entry.getInt(1);
skill_granted_skills.put(typeString, skill_level);
}
}
}
} catch (Exception e) {
Logger.error(obj_name + ":" + e);
}
}
}
+11 -45
View File
@@ -24,7 +24,8 @@ import engine.net.client.msg.PetMsg;
import engine.net.client.msg.PlaceAssetMsg;
import engine.server.MBServerStatics;
import org.jetbrains.annotations.NotNull;
import org.joda.time.DateTime;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
@@ -71,7 +72,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
public long nextAttackTime = System.currentTimeMillis();
private int lastMobPowerToken = 0;
private DeferredPowerJob weaponPower;
private DateTime upgradeDateTime = null;
private LocalDateTime upgradeDateTime = null;
private boolean lootSync = false;
// New Mobile constructor. Fill in the blanks and then call
@@ -126,7 +127,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
sqlDateTime = rs.getTimestamp("upgradeDate");
if (sqlDateTime != null)
upgradeDateTime = new DateTime(sqlDateTime);
upgradeDateTime = LocalDateTime.ofInstant(sqlDateTime.toInstant(), ZoneId.systemDefault());
else
upgradeDateTime = null;
@@ -436,30 +437,6 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
return mobile;
}
// MB_MINION_SPAWN_TIME (seconds) shortens guard/siege minion spawns for testing; 0 or blank keeps the normal timers.
private static int minionSpawnDelay(int defaultDelay) {
String overrideValue;
int overrideDelay;
overrideValue = ConfigManager.MB_MINION_SPAWN_TIME.getValue();
if (overrideValue == null || overrideValue.trim().isEmpty())
return defaultDelay;
try {
overrideDelay = Integer.parseInt(overrideValue.trim());
} catch (NumberFormatException e) {
Logger.warn("MB_MINION_SPAWN_TIME is not a number: " + overrideValue);
return defaultDelay;
}
if (overrideDelay <= 0)
return defaultDelay;
return overrideDelay;
}
public static synchronized Mob createGuardMinion(Mob guardCaptain, short level, String minionName) {
Mob minionMobile;
@@ -479,7 +456,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
minionMobile.deathTime = System.currentTimeMillis();
minionMobile.guardCaptain = guardCaptain;
minionMobile.spawnDelay = minionSpawnDelay((int) (-2.500 * guardCaptain.building.getRank() + 22.5) * 60);
minionMobile.spawnDelay = (int) (-2.500 * guardCaptain.building.getRank() + 22.5) * 60;
minionMobile.behaviourType = mbEnums.MobBehaviourType.GuardMinion;
minionMobile.agentType = AIAgentType.GUARDMINION;
minionMobile.guardedCity = guardCaptain.guardedCity;
@@ -538,7 +515,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
siegeMinion.behaviourType = MobBehaviourType.SiegeEngine;
siegeMinion.agentType = AIAgentType.SIEGEENGINE;
siegeMinion.bindLoc = Vector3fImmutable.ZERO;
siegeMinion.spawnDelay = minionSpawnDelay(60 * 15);
siegeMinion.spawnDelay = (60 * 15);
siegeMinion.runAfterLoad();
@@ -576,12 +553,6 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
petMinion.despawned = false;
petMinion.runAfterLoad();
// Summoned pets carry MASK_PET. Necro pets keep their own NecroPet handling.
if (!petMinion.isNecroPet())
petMinion.setObjectTypeMask(petMinion.getObjectTypeMask() | MBServerStatics.MASK_PET);
DbManager.addToCache(petMinion);
petMinion.setLoc(petMinion.bindLoc);
@@ -623,8 +594,8 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
// Submit upgrade job for future date or current instant
if (mob.getUpgradeDateTime().isAfter(DateTime.now()))
JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob), mob.getUpgradeDateTime().getMillis());
if (mob.getUpgradeDateTime().isAfter(LocalDateTime.now()))
JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob), mob.getUpgradeDateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
else
JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(mob), 0);
@@ -650,7 +621,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
return upgradeCost;
}
public static void setUpgradeDateTime(Mob mob, DateTime upgradeDateTime) {
public static void setUpgradeDateTime(Mob mob, LocalDateTime upgradeDateTime) {
if (!DbManager.MobQueries.updateUpgradeTime(mob, upgradeDateTime)) {
Logger.error("Failed to set upgradeTime for building " + mob.currentID);
@@ -1348,11 +1319,6 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
if (!ac.getObjectType().equals(GameObjectType.PlayerCharacter))
return;
// siege engines only switch targets on damage, see AbstractCharacter.modifyHealth
if (this.isSiege())
return;
if (this.getCombatTarget() == null)
this.setCombatTarget(ac);
@@ -1388,7 +1354,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
this.weaponPower = weaponPower;
}
public DateTime getUpgradeDateTime() {
public LocalDateTime getUpgradeDateTime() {
lock.readLock().lock();
@@ -1468,7 +1434,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed {
if (!building.transferGold(-rankCost, false))
return;
DateTime dateToUpgrade = DateTime.now().plusHours(Mob.getUpgradeTime(this));
LocalDateTime dateToUpgrade = LocalDateTime.now().plusHours(Mob.getUpgradeTime(this));
Mob.setUpgradeDateTime(this, dateToUpgrade);
// Schedule upgrade job
+1 -5
View File
@@ -127,13 +127,9 @@ public class MobBase extends AbstractGameObject {
for (BootySetEntry equipmentSetEntry : equipList) {
Item item = new Item(equipmentSetEntry.templateID);
if (item.template.getItemEqSlotsOr().isEmpty())
continue;
item.objectUUID = ItemManager.lastNegativeID.decrementAndGet();
item.drop_chance = equipmentSetEntry.dropChance;
item.equipSlot = item.template.getItemEqSlotsOr().iterator().next();
item.equipSlot = item.template.item_eq_slots_or.iterator().next();
equip.put(item.equipSlot, item);
}
+6 -7
View File
@@ -15,7 +15,6 @@ import engine.gameManager.PowersManager;
import engine.mbEnums;
import engine.mbEnums.ItemType;
import engine.mbEnums.OwnerType;
import engine.parsers.objects.CObjectTemplate;
import engine.powers.poweractions.AbstractPowerAction;
import org.pmw.tinylog.Logger;
@@ -31,22 +30,22 @@ public final class MobLoot extends Item {
private String prefix = "";
private String suffix = "";
public MobLoot(AbstractCharacter mob, CObjectTemplate template, boolean noSteal) {
public MobLoot(AbstractCharacter mob, ItemTemplate template, boolean noSteal) {
this(mob, template, 0, noSteal);
}
public MobLoot(AbstractCharacter mob, int qtyOfGold) {
this(mob, CObjectTemplate.lookup(mbEnums.ResourceType.GOLD.templateID), qtyOfGold, false);
this(mob, ItemTemplate.templates.get(mbEnums.ResourceType.GOLD.templateID), qtyOfGold, false);
}
public MobLoot(AbstractCharacter mob, CObjectTemplate template, int quantity, boolean noSteal) {
public MobLoot(AbstractCharacter mob, ItemTemplate template, int quantity, boolean noSteal) {
super(template.getTemplateId());
super(template.template_id);
this.ownerType = OwnerType.Mob;
this.ownerID = mob.getObjectUUID();
this.objectUUID = generateId();
if (quantity == 0 && template.getItemType() == ItemType.RESOURCE)
if (quantity == 0 && template.item_type == ItemType.RESOURCE)
quantity = 1;
if (quantity > 0)
@@ -106,7 +105,7 @@ public final class MobLoot extends Item {
if (isDeleted)
return null;
if (this.template.getItemType().equals(ItemType.GOLD))
if (this.template.item_type.equals(ItemType.GOLD))
return null;
Item item = this;
+15 -15
View File
@@ -23,9 +23,9 @@ import engine.net.ByteBufferWriter;
import engine.net.Dispatch;
import engine.net.client.msg.PetMsg;
import engine.net.client.msg.PlaceAssetMsg;
import engine.parsers.objects.CObjectTemplate;
import engine.server.MBServerStatics;
import org.joda.time.DateTime;
import java.time.LocalDateTime;
import java.time.ZoneId;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
@@ -68,7 +68,7 @@ public class NPC extends AbstractCharacter {
protected int symbol;
// Variables NOT to be stored in db
protected boolean isStatic = false;
private DateTime upgradeDateTime = null;
private LocalDateTime upgradeDateTime = null;
private HashSet<Integer> canRoll = null;
public int parentZoneUUID;
public int equipmentSetID = 0;
@@ -132,7 +132,7 @@ public class NPC extends AbstractCharacter {
sqlDateTime = rs.getTimestamp("upgradeDate");
if (sqlDateTime != null)
upgradeDateTime = new DateTime(sqlDateTime);
upgradeDateTime = LocalDateTime.ofInstant(sqlDateTime.toInstant(), ZoneId.systemDefault());
else
upgradeDateTime = null;
@@ -528,9 +528,9 @@ public class NPC extends AbstractCharacter {
// Submit upgrade job for future date or current instant
if (this.getUpgradeDateTime().isAfter(DateTime.now()))
if (this.getUpgradeDateTime().isAfter(LocalDateTime.now()))
jc = JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(this),
this.getUpgradeDateTime().getMillis());
this.getUpgradeDateTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
else
JobScheduler.getInstance().scheduleJob(new UpgradeNPCJob(this), 0);
@@ -908,7 +908,7 @@ public class NPC extends AbstractCharacter {
return new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
}
public DateTime getUpgradeDateTime() {
public LocalDateTime getUpgradeDateTime() {
lock.readLock().lock();
try {
return upgradeDateTime;
@@ -917,7 +917,7 @@ public class NPC extends AbstractCharacter {
}
}
public void setUpgradeDateTime(DateTime upgradeDateTime) {
public void setUpgradeDateTime(LocalDateTime upgradeDateTime) {
if (!DbManager.NPCQueries.updateUpgradeTime(this, upgradeDateTime)) {
Logger.error("Failed to set upgradeTime for building " + currentID);
@@ -962,15 +962,15 @@ public class NPC extends AbstractCharacter {
maxSkill = 110;
break;
}
CObjectTemplate itemTemplate;
ItemTemplate itemTemplate;
int skillRequired = 0;
for (Integer itemID : fullItemList) {
itemTemplate = CObjectTemplate.lookup(itemID);
itemTemplate = ItemTemplate.templates.get(itemID);
if (itemTemplate.getItemSkillReq().values().iterator().hasNext())
skillRequired = itemTemplate.getItemSkillReq().values().iterator().next();
if (itemTemplate.item_skill_required.values().iterator().hasNext())
skillRequired = itemTemplate.item_skill_required.values().iterator().next();
boolean exclude = skillRequired == 0 && CObjectTemplate.lookup(itemID).getItemType().equals(ItemType.WEAPON);
boolean exclude = skillRequired == 0 && ItemTemplate.templates.get(itemID).item_type.equals(ItemType.WEAPON);
if (skillRequired <= maxSkill && !exclude)
filteredItemList.add(itemID);
}
@@ -1060,7 +1060,7 @@ public class NPC extends AbstractCharacter {
int rankCost;
Building building;
DateTime dateToUpgrade;
LocalDateTime dateToUpgrade;
this.lock.writeLock().lock();
@@ -1103,7 +1103,7 @@ public class NPC extends AbstractCharacter {
if (!building.transferGold(-rankCost, false))
return;
dateToUpgrade = DateTime.now().plusHours(this.getUpgradeTime());
dateToUpgrade = LocalDateTime.now().plusHours(this.getUpgradeTime());
this.setUpgradeDateTime(dateToUpgrade);
+18 -18
View File
@@ -32,13 +32,13 @@ import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.*;
import engine.net.client.msg.login.CommitNewCharacterMsg;
import engine.parsers.objects.CObjectTemplate;
import engine.powers.EffectsBase;
import engine.server.MBServerStatics;
import engine.server.login.LoginServer;
import engine.server.world.WorldServer;
import engine.util.MiscUtils;
import org.joda.time.DateTime;
import java.time.Instant;
import java.time.ZoneId;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
@@ -703,11 +703,11 @@ public class PlayerCharacter extends AbstractCharacter {
writer.putInt(token);
writer.putInt((int) timeLeft / 1000);
}
DateTime enterWorld = new DateTime(playerCharacter.timestamps.get("EnterWorld"));
Instant enterWorld = Instant.ofEpochMilli(playerCharacter.timestamps.get("EnterWorld"));
writer.putDateTime(enterWorld);
writer.putInt(0x49EF1E98); //DUnno what playerCharacter is.
writer.putFloat(DateTime.now().hourOfDay().get()); //daylight in float.
writer.putFloat(Instant.now().atZone(ZoneId.systemDefault()).toLocalTime().getHour()); //daylight in float.
writer.putFloat(6); //interval of light to change per game hour //float
//writer.putInt(1637194901); //playerCharacter is actually an opcode taht is in recordings, no clue what it is, dumped it and it changes nothing
} else {
@@ -1354,10 +1354,10 @@ public class PlayerCharacter extends AbstractCharacter {
public static float getDexPenalty(Item armor) {
if (armor == null)
return 0f;
CObjectTemplate ab = armor.template;
ItemTemplate ab = armor.template;
if (ab == null)
return 0f;
return engine.parsers.objects.ItemTemplate._items.get(armor.templateID).item_bulk_factor;
return ab.item_bulk_factor;
}
public static void InitializeSkillsOnLoad(PlayerCharacter pc) {
@@ -2817,15 +2817,15 @@ public class PlayerCharacter extends AbstractCharacter {
if (item == null)
return false;
CObjectTemplate ib = item.template;
ItemTemplate ib = item.template;
if (ib != null) {
if ((item.template.getItemType().equals(ItemType.WEAPON))
&& (item.template.getItemSkillUsed().equals(type) || ib.getItemSkillMasteryUsed().equals(type)))
if ((item.template.item_type.equals(ItemType.WEAPON))
&& (item.template.item_skill_used.equals(type) || ib.item_skill_mastery_used.equals(type)))
return true;
return (item.template.getItemType().equals(ItemType.ARMOR))
&& (item.template.getItemSkillUsed().equals(type));
return (item.template.item_type.equals(ItemType.ARMOR))
&& (item.template.item_skill_used.equals(type));
}
return false;
@@ -3769,8 +3769,8 @@ public class PlayerCharacter extends AbstractCharacter {
ConcurrentHashMap<EquipSlotType, Item> equipped = this.charItemManager.getEquipped();
Item off = equipped.get(EquipSlotType.LHELD);
Item main = equipped.get(EquipSlotType.RHELD);
CObjectTemplate wbMain = null;
CObjectTemplate wbOff = null;
ItemTemplate wbMain = null;
ItemTemplate wbOff = null;
if (main != null)
wbMain = main.template;
if (off != null)
@@ -3792,8 +3792,8 @@ public class PlayerCharacter extends AbstractCharacter {
this.bonuses.setBool(ModType.Parry, SourceType.None, false);
if ((this.baseClass != null && this.baseClass.getObjectUUID() == 2500)
|| (this.promotionClass != null && this.promotionClass.getObjectUUID() == 2520))
if (wbMain == null || engine.parsers.objects.ItemTemplate.getWeapon(wbMain.getTemplateId()).weapon_max_range < MBServerStatics.RANGED_WEAPON_RANGE)
if (wbOff == null || engine.parsers.objects.ItemTemplate.getWeapon(wbOff.getTemplateId()).weapon_max_range < MBServerStatics.RANGED_WEAPON_RANGE)
if (wbMain == null || wbMain.item_weapon_max_range < MBServerStatics.RANGED_WEAPON_RANGE)
if (wbOff == null || wbOff.item_weapon_max_range < MBServerStatics.RANGED_WEAPON_RANGE)
this.bonuses.setBool(ModType.Parry, SourceType.None, true);
}
@@ -4185,9 +4185,8 @@ public class PlayerCharacter extends AbstractCharacter {
} else if (currentPet.isSiege()) {
currentPet.agentType = AIAgentType.MOBILE;
// released siege engine keeps its current target
currentPet.guardCaptain = null;
currentPet.setCombatTarget(null);
if (currentPet.isAlive())
WorldGrid.updateObject(currentPet);
}
@@ -4195,6 +4194,7 @@ public class PlayerCharacter extends AbstractCharacter {
toCommand.setPet(this, false);
this.setPet(toCommand);
toCommand.setCombatTarget(null);
PetMsg petMsg = new PetMsg(6, toCommand);
Dispatch dispatch = Dispatch.borrow(this, petMsg);
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
@@ -4365,7 +4365,7 @@ public class PlayerCharacter extends AbstractCharacter {
}
if (count > 0) {
this.timestamps.put("RealmClaim", DateTime.now().plusMinutes(3).getMillis());
this.timestamps.put("RealmClaim", Instant.now().plusSeconds(180).toEpochMilli());
for (PlayerCharacter toSend : SessionManager.getAllActivePlayerCharacters()) {
ChatManager.chatSystemInfo(toSend, this.getCombinedName() + " is seeking to claim a realm and already has " + count + " blessngs!");
}
-78
View File
@@ -10,13 +10,8 @@
package engine.objects;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.mbEnums.GameObjectType;
import engine.net.ByteBufferWriter;
import engine.parsers.cache.CObjectIndex;
import engine.parsers.objects.RuneTemplate;
import engine.util.Hasher;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -108,79 +103,6 @@ public class PromotionClass extends AbstractGameObject {
}
/**
* Rune Template Constructor
*/
public PromotionClass(RuneTemplate rune) {
super(rune.template_id);
this.name = rune.obj_name;
this.description = rune.rune_dsc;
this.token = Hasher.SBStringHash(rune.rune_sub_type);
this.healthMod = rune.rune_health;
this.manaMod = rune.rune_mana;
this.staminaMod = rune.rune_stamina;
this.allowedRunes = getAllowedRuneTokens(rune);
this.skillsGranted = DbManager.SkillReqQueries.GET_REQS_FOR_RUNE(this.getObjectUUID());
this.powersGranted = PowerReq.getPowerReqsForRune(this.getObjectUUID());
this.effectsGranted = DbManager.RuneBaseEffectQueries.GET_EFFECTS_FOR_RUNEBASE(this.getObjectUUID());
this.effectsGrantedFighter = DbManager.RuneBaseEffectQueries.GET_EFFECTS_FOR_RUNEBASE((this.getObjectUUID() * 10) + 2500);
this.effectsGrantedHealer = DbManager.RuneBaseEffectQueries.GET_EFFECTS_FOR_RUNEBASE((this.getObjectUUID() * 10) + 2501);
this.effectsGrantedRogue = DbManager.RuneBaseEffectQueries.GET_EFFECTS_FOR_RUNEBASE((this.getObjectUUID() * 10) + 2502);
this.effectsGrantedMage = DbManager.RuneBaseEffectQueries.GET_EFFECTS_FOR_RUNEBASE((this.getObjectUUID() * 10) + 2503);
this.effectsList = DbManager.MobBaseQueries.GET_RUNEBASE_EFFECTS(this.getObjectUUID());
}
// Promotions are the CLASS runes that require a base class; this skips the creation classes and Pet 2522.
public static boolean isPromotionRune(RuneTemplate rune) {
return rune.rune_type == mbEnums.RuneType.CLASS && !rune.rune_is_standard_character_creation
&& !rune.item_class_req.isEmpty();
}
// Race and base class tokens are SBStringHash(rune_sub_type) of the runes named in the req lists.
// Every promotion rune's lists are whitelists (restrict false).
private static ArrayList<Integer> getAllowedRuneTokens(RuneTemplate rune) {
ArrayList<Integer> tokens = new ArrayList<>();
Integer classRuneId;
int token;
for (mbEnums.MonsterType race : rune.item_race_req)
for (int raceRuneId : CObjectIndex.getRaceRuneIds(race)) {
token = Hasher.SBStringHash(RuneTemplate._runes.get(raceRuneId).rune_sub_type);
if (!tokens.contains(token))
tokens.add(token);
}
for (mbEnums.ClassType classType : rune.item_class_req) {
classRuneId = CObjectIndex.getClassRuneId(classType);
if (classRuneId != null)
tokens.add(Hasher.SBStringHash(RuneTemplate._runes.get(classRuneId).rune_sub_type));
}
return tokens;
}
public static void LoadAllPromotions() {
int loadedCount = 0;
for (RuneTemplate rune : RuneTemplate._runes.values()) {
if (!isPromotionRune(rune))
continue;
DbManager.addToCache(new PromotionClass(rune));
loadedCount++;
}
Logger.info("Loaded " + loadedCount + " promotion classes from runes");
// The CSR/admin rows 2901+ have no promotion rune; the DB loader skips ids already cached
DbManager.PromotionQueries.GET_ALL_PROMOTIONS();
}
public static void serializeForClientMsg(PromotionClass promotionClass, ByteBufferWriter writer) {
writer.putInt(3); // For BaseClass
writer.putInt(0); // Pad
+1 -106
View File
@@ -13,11 +13,7 @@ import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.mbEnums.RaceType;
import engine.net.ByteBufferWriter;
import engine.parsers.cache.CacheParserUtil;
import engine.parsers.objects.RuneTemplate;
import engine.server.MBServerStatics;
import engine.util.Hasher;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -31,9 +27,6 @@ public class Race {
private static ConcurrentHashMap<Integer, Race> _raceByID = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
// Creation points before the race rune's rune_creation_cost is taken off
private static final int STARTING_POINT_POOL = 30;
private final String name;
private final String description;
private final int raceRuneID;
@@ -114,106 +107,8 @@ public class Race {
}
/**
* Rune Template Constructor
* minHeight and strHeightMod are server-only and come from the static_rune_race row.
*/
public Race(RuneTemplate rune, Race dbRace) {
this.raceRuneID = rune.template_id;
this.raceType = mbEnums.RaceType.getRaceTypebyRuneID(raceRuneID);
this.name = rune.obj_name;
this.description = rune.rune_dsc;
this.strStart = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Strength, 0).shortValue();
this.strMin = 0;
this.strMax = rune.rune_max_attr_adj.getOrDefault(mbEnums.AttributeType.Strength, 0).shortValue();
this.dexStart = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Dexterity, 0).shortValue();
this.dexMin = 0;
this.dexMax = rune.rune_max_attr_adj.getOrDefault(mbEnums.AttributeType.Dexterity, 0).shortValue();
this.conStart = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Constitution, 0).shortValue();
this.conMin = 0;
this.conMax = rune.rune_max_attr_adj.getOrDefault(mbEnums.AttributeType.Constitution, 0).shortValue();
this.intStart = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Intelligence, 0).shortValue();
this.intMin = 0;
this.intMax = rune.rune_max_attr_adj.getOrDefault(mbEnums.AttributeType.Intelligence, 0).shortValue();
this.spiStart = rune.rune_attr_adj.getOrDefault(mbEnums.AttributeType.Spirit, 0).shortValue();
this.spiMin = 0;
this.spiMax = rune.rune_max_attr_adj.getOrDefault(mbEnums.AttributeType.Spirit, 0).shortValue();
this.token = Hasher.SBStringHash(rune.rune_sub_type);
this.healthBonus = (short) rune.rune_health;
this.manaBonus = (short) rune.rune_mana;
this.staminaBonus = (short) rune.rune_stamina;
this.startingPoints = (byte) (STARTING_POINT_POOL - rune.rune_creation_cost);
this.minHeight = dbRace.minHeight;
this.strHeightMod = dbRace.strHeightMod;
this.hairStyles = new HashSet<>(rune.rune_hair);
this.beardStyles = new HashSet<>(rune.rune_beard);
this.skinColors = DbManager.RaceQueries.SKIN_COLOR_FOR_RACE(raceRuneID);
this.beardColors = DbManager.RaceQueries.BEARD_COLORS_FOR_RACE(raceRuneID);
this.hairColors = DbManager.RaceQueries.HAIR_COLORS_FOR_RACE(raceRuneID);
this.baseClasses = getBaseClassesForRace(rune);
this.skillsGranted = DbManager.SkillReqQueries.GET_REQS_FOR_RUNE(raceRuneID);
this.powersGranted = PowerReq.getPowerReqsForRune(raceRuneID);
this.effectsList = DbManager.MobBaseQueries.GET_RUNEBASE_EFFECTS(this.raceRuneID);
// Races without hair styles (Aracoix, Shade) select style 0, which creation validates
if (this.hairStyles.isEmpty())
this.hairStyles.add(0);
}
// Base classes are the creation class runes whose item_race_req names this race's sub type.
// Every creation class rune's race list is a whitelist (restrict false).
private static ArrayList<BaseClass> getBaseClassesForRace(RuneTemplate rune) {
ArrayList<BaseClass> baseClasses = new ArrayList<>();
mbEnums.MonsterType monsterType;
BaseClass baseClass;
monsterType = CacheParserUtil.readEnum(mbEnums.MonsterType.class, rune.rune_sub_type, rune.template_id, "rune_sub_type");
for (RuneTemplate classRune : RuneTemplate._runes.values()) {
if (classRune.rune_type != mbEnums.RuneType.CLASS || !classRune.rune_is_standard_character_creation)
continue;
if (!classRune.item_race_req.contains(monsterType))
continue;
baseClass = DbManager.BaseClassQueries.GET_BASE_CLASS(classRune.template_id);
if (baseClass != null)
baseClasses.add(baseClass);
}
return baseClasses;
}
// Iterates the static_rune_race rows: no rune field separates 2018-2021 from the mob race runes,
// and each row still holds the server-only heights.
public static void loadAllRaces() {
ConcurrentHashMap<Integer, Race> dbRaces;
ConcurrentHashMap<Integer, Race> races;
RuneTemplate rune;
dbRaces = DbManager.RaceQueries.LOAD_ALL_RACES();
races = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
for (Race dbRace : dbRaces.values()) {
rune = RuneTemplate._runes.get(dbRace.raceRuneID);
if (rune == null || rune.rune_type != mbEnums.RuneType.RACE) {
Logger.warn("Race " + dbRace.raceRuneID + " has no race rune; loaded from static_rune_race");
races.put(dbRace.raceRuneID, dbRace);
continue;
}
races.put(dbRace.raceRuneID, new Race(rune, dbRace));
}
Race._raceByID = races;
Logger.info("Loaded " + races.size() + " races from runes");
Race._raceByID = DbManager.RaceQueries.LOAD_ALL_RACES();
}
public static Race getRace(int id) {
+4 -8
View File
@@ -19,7 +19,6 @@ import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
@@ -160,16 +159,13 @@ public class Resists {
private static float[] getArmorResists(Item armor, float[] phys) {
EnumMap<mbEnums.DamageType, Float> armorResists;
if (armor == null)
return phys;
if (armor.template.getItemType().equals(mbEnums.ItemType.ARMOR)) {
armorResists = armor.template.getCombatAttackResist();
phys[0] += armorResists.getOrDefault(mbEnums.DamageType.SLASHING, 0f);
phys[1] += armorResists.getOrDefault(mbEnums.DamageType.CRUSHING, 0f);
phys[2] += armorResists.getOrDefault(mbEnums.DamageType.PIERCING, 0f);
if (armor.template.item_type.equals(mbEnums.ItemType.ARMOR)) {
phys[0] += armor.template.combat_attack_resist.get("SLASHING");
phys[1] += armor.template.combat_attack_resist.get("CRUSHING");
phys[2] += armor.template.combat_attack_resist.get("PIERCING");
}
return phys;
+2 -2
View File
@@ -256,13 +256,13 @@ public class Shrine extends AbstractWorldObject implements Comparable<Shrine> {
if (!boonOwner.charItemManager.doesCharOwnThisItem(boonItem.getObjectUUID()))
return false;
for (ShrineType boonShrineType : boonItem.template.getItemOfferingInfo().keySet()) {
for (ShrineType boonShrineType : boonItem.template.item_offering_info.keySet()) {
if (boonShrineType != shrineType)
continue;
//Same Shrine Type, add favors and stop loop.
int amount = boonItem.template.getItemOfferingInfo().get(boonShrineType) * boonItem.getNumOfItems();
int amount = boonItem.template.item_offering_info.get(boonShrineType) * boonItem.getNumOfItems();
int oldAmount = this.favors;
if (!DbManager.ShrineQueries.updateFavors(this, this.favors + amount, oldAmount)) {
+6 -6
View File
@@ -12,7 +12,7 @@ package engine.objects;
import engine.mbEnums;
import engine.mbEnums.GameObjectType;
import engine.mbEnums.TransactionType;
import org.joda.time.DateTime;
import java.time.Instant;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -24,7 +24,7 @@ public class Transaction implements Comparable<Transaction> {
private final int warehouseUUID;
private final int targetUUID;
private final mbEnums.ResourceType resource;
private final DateTime date;
private final Instant date;
private final int amount;
private final TransactionType transactionType;
private GameObjectType targetType;
@@ -41,15 +41,15 @@ public class Transaction implements Comparable<Transaction> {
Date sqlDateTime = rs.getTimestamp("date");
if (sqlDateTime != null)
this.date = new DateTime(sqlDateTime);
this.date = sqlDateTime.toInstant();
else
this.date = DateTime.now();
this.date = Instant.now();
}
public Transaction(int warehouseUUID, GameObjectType targetType, int targetUUID, TransactionType transactionType, mbEnums.ResourceType resource, int amount,
DateTime date) {
Instant date) {
this.warehouseUUID = warehouseUUID;
this.targetUUID = targetUUID;
this.resource = resource;
@@ -75,7 +75,7 @@ public class Transaction implements Comparable<Transaction> {
}
public DateTime getDate() {
public Instant getDate() {
return date;
}
+9 -13
View File
@@ -17,9 +17,8 @@ import engine.mbEnums;
import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.*;
import engine.parsers.objects.CObjectTemplate;
import engine.server.MBServerStatics;
import org.joda.time.DateTime;
import java.time.Instant;
import org.json.JSONArray;
import org.json.JSONObject;
import org.pmw.tinylog.Logger;
@@ -32,9 +31,6 @@ import java.util.concurrent.ConcurrentHashMap;
public class Warehouse {
// Destroyed warehouses keyed by rubble building UUID; memory only so the rubble can be looted
public static final ConcurrentHashMap<Integer, Warehouse> destroyedWarehouses = new ConcurrentHashMap<>();
public EnumSet<mbEnums.ResourceType> locked = EnumSet.noneOf(mbEnums.ResourceType.class);
public Building building;
public City city;
@@ -305,10 +301,10 @@ public class Warehouse {
return false;
}
if (resource.template.getItemType().equals(mbEnums.ItemType.GOLD))
if (resource.template.item_type.equals(mbEnums.ItemType.GOLD))
resourceType = mbEnums.ResourceType.GOLD;
else
resourceType = mbEnums.ResourceType.valueOf(CObjectTemplate.lookup(resource.templateID).getItemBaseName().toUpperCase());
resourceType = mbEnums.ResourceType.valueOf(ItemTemplate.templates.get(resource.templateID).item_base_name.toUpperCase());
if (transaction)
AddTransactionToWarehouse(warehouse, playerCharacter.getObjectType(), playerCharacter.getObjectUUID(), mbEnums.TransactionType.DEPOSIT, resourceType, amount);
@@ -419,7 +415,7 @@ public class Warehouse {
if (playerCharacter == null)
return false;
CObjectTemplate template = CObjectTemplate.lookup(resourceType.templateID);
ItemTemplate template = ItemTemplate.templates.get(resourceType.templateID);
if (warehouse.resources.get(resourceType) == null)
return false;
@@ -433,7 +429,7 @@ public class Warehouse {
return false;
if (addToInventory)
if (!itemMan.hasRoomInventory(template.getItemWt())) {
if (!itemMan.hasRoomInventory(template.item_wt)) {
ChatManager.chatSystemInfo(playerCharacter, "You can not carry any more of that item.");
return false;
}
@@ -502,7 +498,7 @@ public class Warehouse {
if (playerCharacter == null)
return false;
CObjectTemplate template = CObjectTemplate.lookup(resourceType.templateID);
ItemTemplate template = ItemTemplate.templates.get(resourceType);
if (template == null)
return false;
@@ -518,7 +514,7 @@ public class Warehouse {
if (itemMan == null)
return false;
if (!itemMan.hasRoomInventory(template.getItemWt())) {
if (!itemMan.hasRoomInventory(template.item_wt)) {
ChatManager.chatSystemInfo(playerCharacter, "You can not carry any more of that item.");
return false;
}
@@ -580,10 +576,10 @@ public class Warehouse {
public static void AddTransactionToWarehouse(Warehouse warehouse, mbEnums.GameObjectType targetType, int targetUUID, mbEnums.TransactionType transactionType, mbEnums.ResourceType resource, int amount) {
if (!DbManager.WarehouseQueries.CREATE_TRANSACTION(warehouse.building.getObjectUUID(), targetType, targetUUID, transactionType, resource, amount, DateTime.now()))
if (!DbManager.WarehouseQueries.CREATE_TRANSACTION(warehouse.building.getObjectUUID(), targetType, targetUUID, transactionType, resource, amount, Instant.now()))
return;
Transaction transaction = new Transaction(warehouse.building.getObjectUUID(), targetType, targetUUID, transactionType, resource, amount, DateTime.now());
Transaction transaction = new Transaction(warehouse.building.getObjectUUID(), targetType, targetUUID, transactionType, resource, amount, Instant.now());
warehouse.transactions.add(transaction);
}
-235
View File
@@ -1,235 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.cache;
import engine.mbEnums;
import engine.parsers.objects.CObjectTemplate;
import engine.parsers.objects.DeedTemplate;
import engine.parsers.objects.ItemTemplate;
import engine.parsers.objects.PowerGrant;
import engine.parsers.objects.RuneTemplate;
import engine.parsers.objects.UserPowerAction;
import engine.util.Hasher;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
// Lookups across the ITEM, DEED and RUNE cache templates.
// The JSON references runes, skills and powers by name; the server and DB use ids and tokens.
// Build once after all three parsers have loaded. Read only afterwards.
public class CObjectIndex {
private static final EnumMap<mbEnums.MonsterType, ArrayList<Integer>> raceRuneIds = new EnumMap<>(mbEnums.MonsterType.class);
private static final EnumMap<mbEnums.ClassType, Integer> classRuneIds = new EnumMap<>(mbEnums.ClassType.class);
private static final EnumMap<mbEnums.DisciplineType, Integer> disciplineRuneIds = new EnumMap<>(mbEnums.DisciplineType.class);
private static final HashMap<Integer, ArrayList<RuneTemplate>> runesBySubTypeToken = new HashMap<>();
private static final HashMap<String, Integer> skillTokens = new HashMap<>();
private static final HashMap<Integer, String> skillNames = new HashMap<>();
private static final HashMap<String, Integer> powerTokens = new HashMap<>();
private static final HashMap<Integer, String> powerNames = new HashMap<>();
// Same order as the client's id space checks (JSON-Refactor-Plan D1).
public static CObjectTemplate lookup(int templateId) {
CObjectTemplate template;
template = ItemTemplate._items.get(templateId);
if (template == null)
template = DeedTemplate._deeds.get(templateId);
if (template == null)
template = RuneTemplate._runes.get(templateId);
return template;
}
// Male and female runes share a race, so most races return two ids.
public static ArrayList<Integer> getRaceRuneIds(mbEnums.MonsterType race) {
return raceRuneIds.getOrDefault(race, new ArrayList<>());
}
public static Integer getClassRuneId(mbEnums.ClassType classType) {
return classRuneIds.get(classType);
}
public static Integer getDisciplineRuneId(mbEnums.DisciplineType discipline) {
return disciplineRuneIds.get(discipline);
}
// DB race and class tokens are SBStringHash(rune_sub_type). Mob and talent runes share sub types.
public static ArrayList<RuneTemplate> getRunesBySubTypeToken(int token) {
return runesBySubTypeToken.getOrDefault(token, new ArrayList<>());
}
public static Integer getSkillToken(String skillName) {
return skillTokens.get(skillName);
}
public static String getSkillName(int token) {
return skillNames.get(token);
}
public static Integer getPowerToken(String powerName) {
return powerTokens.get(powerName);
}
public static String getPowerName(int token) {
return powerNames.get(token);
}
public static void build() {
int overlapCount = 0;
for (Integer templateId : RuneTemplate._runes.keySet())
if (ItemTemplate._items.containsKey(templateId) || DeedTemplate._deeds.containsKey(templateId))
overlapCount++;
for (Integer templateId : DeedTemplate._deeds.keySet())
if (ItemTemplate._items.containsKey(templateId))
overlapCount++;
if (overlapCount > 0)
Logger.warn(overlapCount + " template ids exist in more than one of ITEM/DEED/RUNE");
for (RuneTemplate rune : RuneTemplate._runes.values()) {
indexRuneName(rune);
indexSubTypeToken(rune);
indexRuneNames(rune);
}
for (ItemTemplate item : ItemTemplate._items.values()) {
addSkill(item.item_skill_used);
addSkill(item.item_skill_mastery_used);
indexItemFields(item.item_skill_req, item.item_user_power_action, item.item_power_grant, item.item_power_action);
}
for (DeedTemplate deed : DeedTemplate._deeds.values()) {
addSkill(deed.item_skill_used);
addSkill(deed.item_skill_mastery_used);
indexItemFields(deed.item_skill_req, deed.item_user_power_action, deed.item_power_grant, deed.item_power_action);
}
Logger.info("Indexed " + raceRuneIds.size() + " races, " + classRuneIds.size() + " classes, "
+ disciplineRuneIds.size() + " disciplines, " + runesBySubTypeToken.size() + " rune sub type tokens, "
+ skillTokens.size() + " skills, " + powerTokens.size() + " powers");
}
private static void indexRuneName(RuneTemplate rune) {
Integer previousId;
if (rune.rune_type == null || rune.rune_sub_type.isEmpty())
return;
try {
switch (rune.rune_type) {
case RACE:
// Mob runes reuse race sub types; only creation races map to player race ids
if (rune.rune_is_standard_character_creation)
raceRuneIds.computeIfAbsent(CacheParserUtil.readEnum(mbEnums.MonsterType.class, rune.rune_sub_type, rune.template_id, "rune_sub_type"),
k -> new ArrayList<>()).add(rune.template_id);
break;
case CLASS:
previousId = classRuneIds.put(CacheParserUtil.readEnum(mbEnums.ClassType.class, rune.rune_sub_type, rune.template_id, "rune_sub_type"), rune.template_id);
if (previousId != null)
Logger.warn(rune.template_id + ": class " + rune.rune_sub_type + " already indexed by " + previousId);
break;
case DISCIPLINE:
previousId = disciplineRuneIds.put(CacheParserUtil.readEnum(mbEnums.DisciplineType.class, rune.rune_sub_type, rune.template_id, "rune_sub_type"), rune.template_id);
if (previousId != null)
Logger.warn(rune.template_id + ": discipline " + rune.rune_sub_type + " already indexed by " + previousId);
break;
default:
break;
}
} catch (IllegalArgumentException e) {
// The Pet class rune has no ClassType
Logger.warn(e.getMessage());
}
}
private static void indexSubTypeToken(RuneTemplate rune) {
int token;
if (!rune.rune_sub_type.isEmpty())
token = Hasher.SBStringHash(rune.rune_sub_type);
else if (rune.rune_sub_type_hash != 0)
token = rune.rune_sub_type_hash;
else
return;
runesBySubTypeToken.computeIfAbsent(token, k -> new ArrayList<>()).add(rune);
}
private static void indexRuneNames(RuneTemplate rune) {
for (RuneTemplate.SkillGrant grant : rune.rune_skill_grant) {
addSkill(grant.skill_type);
grant.skill_granted_skills.keySet().forEach(CObjectIndex::addSkill);
grant.skill_granted_powers.keySet().forEach(CObjectIndex::addPower);
}
rune.rune_skill_adj.keySet().forEach(CObjectIndex::addSkill);
addSkill(rune.item_skill_used);
addSkill(rune.item_skill_mastery_used);
indexItemFields(rune.item_skill_req, rune.item_user_power_action, rune.item_power_grant, rune.item_power_action);
}
private static void indexItemFields(Map<String, Integer> skillReq, ArrayList<UserPowerAction> userPowerActions,
ArrayList<PowerGrant> powerGrants, Map<String, ArrayList<int[]>> powerActions) {
skillReq.keySet().forEach(CObjectIndex::addSkill);
for (UserPowerAction action : userPowerActions)
addPower(action.power);
for (PowerGrant grant : powerGrants) {
addPower(grant.power_type);
grant.power_granted_skills.keySet().forEach(CObjectIndex::addSkill);
grant.power_granted_powers.keySet().forEach(CObjectIndex::addPower);
}
powerActions.keySet().forEach(CObjectIndex::addPower);
}
private static void addSkill(String skillName) {
addName(skillName, skillTokens, skillNames, "skill");
}
private static void addPower(String powerName) {
addName(powerName, powerTokens, powerNames, "power");
}
private static void addName(String name, HashMap<String, Integer> tokens, HashMap<Integer, String> names, String kind) {
int token;
String previousName;
// readHashLabel keeps unresolved hashes as decimal strings; those are not names
if (name == null || name.isEmpty() || name.matches("-?\\d+") || tokens.containsKey(name))
return;
token = Hasher.SBStringHash(name);
tokens.put(name, token);
previousName = names.putIfAbsent(token, name);
if (previousName != null)
Logger.warn(kind + " token " + token + " shared by '" + previousName + "' and '" + name + "'");
}
}
-353
View File
@@ -1,353 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.cache;
import engine.math.Vector3fImmutable;
import engine.parsers.objects.PowerGrant;
import engine.parsers.objects.UserPowerAction;
import org.json.JSONArray;
import org.json.JSONObject;
import org.pmw.tinylog.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
// Shared JSON helpers for the COBJECTS cache parsers.
// Only generic reading lives here; each parser owns its own field mapping.
public class CacheParserUtil {
// Files are named <template id>.json
public static File[] listJsonFiles(String folderPath) {
File folder = new File(folderPath);
File[] jsonFiles = folder.listFiles((dir, name) -> name.endsWith(".json") && hasTemplateId(name));
if (jsonFiles == null) {
Logger.error("Cache folder not found: " + folder.getAbsolutePath());
return new File[0];
}
return jsonFiles;
}
// Template ids are 32-bit. The client cache has RUNE/10788957847552, which is
// 2512 << 32 (the Huntress id in the high word); files like it are skipped.
private static boolean hasTemplateId(String fileName) {
String idText = fileName.substring(0, fileName.length() - ".json".length());
try {
Integer.parseInt(idText);
return true;
} catch (NumberFormatException e) {
Logger.warn("Skipping " + fileName + ": name is not a 32-bit template id");
return false;
}
}
public static int templateIdFromFile(File jsonFile) {
String fileName = jsonFile.getName();
return Integer.parseInt(fileName.substring(0, fileName.length() - ".json".length()));
}
public static JSONObject readJsonFile(File jsonFile) throws IOException {
byte[] fileData = Files.readAllBytes(jsonFile.toPath());
return new JSONObject(new String(fileData, StandardCharsets.UTF_8));
}
// [x, y, z] -> vector. Returns null for an empty array.
public static Vector3fImmutable readVector3(JSONArray vectorJson) {
if (vectorJson.length() < 3)
return null;
return new Vector3fImmutable(vectorJson.getFloat(0), vectorJson.getFloat(1), vectorJson.getFloat(2));
}
// Client strings carry spaces, hyphens and commas that enum constants
// can't ("Half-Giant", "Battle Magus").
public static String enumName(String value) {
String name = value;
name = name.replaceAll("\\s", "");
name = name.replaceAll("-", "");
name = name.replaceAll(",", "");
return name;
}
// Exact match on the cleaned name first, then upper case (ResourceType).
// Unknown values throw so the template fails to load.
public static <E extends Enum<E>> E readEnum(Class<E> enumClass, String value, int templateId, String fieldName) {
String name = enumName(value);
try {
return Enum.valueOf(enumClass, name);
} catch (IllegalArgumentException e) {
// fall through to upper case
}
try {
return Enum.valueOf(enumClass, name.toUpperCase());
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(templateId + ": " + fieldName + " has no " + enumClass.getSimpleName() + " for '" + value + "'");
}
}
public static <E extends Enum<E>> EnumSet<E> readEnumSet(Class<E> enumClass, JSONArray valuesJson, int templateId, String fieldName) {
EnumSet<E> enumSet = EnumSet.noneOf(enumClass);
for (int i = 0; i < valuesJson.length(); i++)
enumSet.add(readEnum(enumClass, valuesJson.getString(i), templateId, fieldName));
return enumSet;
}
// [{keyName: "Strength", valueName: 40}, ...] -> enum map
public static <E extends Enum<E>> EnumMap<E, Integer> readEnumValueMap(Class<E> enumClass, JSONArray entriesJson,
String keyName, String valueName,
int templateId, String fieldName) {
EnumMap<E, Integer> enumMap = new EnumMap<>(enumClass);
JSONObject entry;
for (int i = 0; i < entriesJson.length(); i++) {
entry = entriesJson.getJSONObject(i);
enumMap.put(readEnum(enumClass, entry.getString(keyName), templateId, fieldName), entry.getInt(valueName));
}
return enumMap;
}
// [{keyName: "Sword", valueName: 20}, ...] -> map in file order
public static LinkedHashMap<String, Integer> readStringValueMap(JSONArray entriesJson, String keyName, String valueName) {
LinkedHashMap<String, Integer> valueMap = new LinkedHashMap<>();
JSONObject entry;
for (int i = 0; i < entriesJson.length(); i++) {
entry = entriesJson.getJSONObject(i);
valueMap.put(entry.getString(keyName), (int) entry.getLong(valueName));
}
return valueMap;
}
// {"SLASHING": 0.0, ...} -> enum map
public static <E extends Enum<E>> EnumMap<E, Float> readEnumFloatMap(Class<E> enumClass, JSONObject mapJson,
int templateId, String fieldName) {
EnumMap<E, Float> enumMap = new EnumMap<>(enumClass);
for (String key : mapJson.keySet())
enumMap.put(readEnum(enumClass, key, templateId, fieldName), mapJson.getFloat(key));
return enumMap;
}
// Hash and flag fields are still unsigned in the JSON; read as long and wrapped to int.
public static int[] readIntArray(JSONArray valuesJson) {
int[] values = new int[valuesJson.length()];
for (int i = 0; i < valuesJson.length(); i++)
values[i] = (int) valuesJson.getLong(i);
return values;
}
public static float[] readFloatArray(JSONArray valuesJson) {
float[] values = new float[valuesJson.length()];
for (int i = 0; i < valuesJson.length(); i++)
values[i] = valuesJson.getFloat(i);
return values;
}
public static ArrayList<Integer> readIntList(JSONArray valuesJson) {
ArrayList<Integer> values = new ArrayList<>();
for (int i = 0; i < valuesJson.length(); i++)
values.add((int) valuesJson.getLong(i));
return values;
}
// [[a, b], [a, b], ...] -> list of int[]
public static ArrayList<int[]> readIntArrays(JSONArray arraysJson) {
ArrayList<int[]> arrays = new ArrayList<>();
for (int i = 0; i < arraysJson.length(); i++)
arrays.add(readIntArray(arraysJson.getJSONArray(i)));
return arrays;
}
// Sparse data values are mixed bool/int/string; stored as strings.
public static HashMap<String, String> readSparseData(JSONObject sparseJson) {
HashMap<String, String> sparseData = new HashMap<>();
for (String key : sparseJson.keySet())
sparseData.put(key, sparseJson.get(key).toString());
return sparseData;
}
// Some fields are a name when set and the number 0 when not
// (obj_sound_table, item_skill_used). The number becomes "".
public static String readLabel(JSONObject json, String key) {
Object value = json.get(key);
if (value instanceof String)
return (String) value;
return "";
}
// Like readLabel, but a non-zero number is a hash the exporter could not
// name; it is kept as its decimal string rather than dropped.
public static String readHashLabel(JSONObject json, String key, int templateId) {
Object value = json.get(key);
long hash;
if (value instanceof String)
return (String) value;
hash = json.getLong(key);
if (hash == 0)
return "";
Logger.warn(templateId + ": " + key + " has unresolved hash " + hash);
return Long.toString(hash);
}
public static ArrayList<UserPowerAction> readUserPowerActions(JSONArray actionsJson) {
ArrayList<UserPowerAction> userPowerActions = new ArrayList<>();
JSONObject entry;
for (int i = 0; i < actionsJson.length(); i++) {
entry = actionsJson.getJSONObject(i);
userPowerActions.add(new UserPowerAction(entry.getString("power"), readIntArray(entry.getJSONArray("arguments"))));
}
return userPowerActions;
}
// [[key, value], ...] -> map in file order. Keys are names when the exporter
// knows the hash, otherwise the raw hash, which is kept as its decimal string.
public static LinkedHashMap<String, Integer> readGrantPairs(JSONArray pairsJson, int templateId, String fieldName) {
LinkedHashMap<String, Integer> grantPairs = new LinkedHashMap<>();
JSONArray pair;
Object key;
String keyName;
for (int i = 0; i < pairsJson.length(); i++) {
pair = pairsJson.getJSONArray(i);
key = pair.get(0);
if (key instanceof String) {
keyName = (String) key;
} else {
keyName = Long.toString(pair.getLong(0));
Logger.warn(templateId + ": " + fieldName + " has unresolved hash " + keyName);
}
grantPairs.put(keyName, pair.getInt(1));
}
return grantPairs;
}
public static ArrayList<PowerGrant> readPowerGrants(JSONArray grantsJson, int templateId) {
ArrayList<PowerGrant> powerGrants = new ArrayList<>();
JSONObject entry;
PowerGrant powerGrant;
for (int i = 0; i < grantsJson.length(); i++) {
entry = grantsJson.getJSONObject(i);
powerGrant = new PowerGrant();
powerGrant.power_type = entry.getString("power_type");
powerGrant.power_value = entry.getInt("power_value");
powerGrant.power_granted_attrs.putAll(readGrantPairs(entry.getJSONArray("power_granted_attrs"), templateId, "power_granted_attrs"));
powerGrant.power_granted_skills.putAll(readGrantPairs(entry.getJSONArray("power_granted_skills"), templateId, "power_granted_skills"));
powerGrant.power_granted_powers.putAll(readGrantPairs(entry.getJSONArray("power_granted_powers"), templateId, "power_granted_powers"));
powerGrant.power_monster_types = entry.getJSONArray("power_monster_types");
powerGrants.add(powerGrant);
}
return powerGrants;
}
// [{power_type: "X", power_actions: [{power_arguments: [a, b]}, ...]}, ...]
// -> power_type -> list of argument arrays (one per power_actions entry)
public static LinkedHashMap<String, ArrayList<int[]>> readPowerActions(JSONArray actionsJson) {
LinkedHashMap<String, ArrayList<int[]>> powerActions = new LinkedHashMap<>();
JSONObject entry;
JSONArray argumentsJson;
ArrayList<int[]> arguments;
for (int i = 0; i < actionsJson.length(); i++) {
entry = actionsJson.getJSONObject(i);
argumentsJson = entry.getJSONArray("power_actions");
arguments = new ArrayList<>();
for (int j = 0; j < argumentsJson.length(); j++)
arguments.add(readIntArray(argumentsJson.getJSONObject(j).getJSONArray("power_arguments")));
powerActions.put(entry.getString("power_type"), arguments);
}
return powerActions;
}
}
-186
View File
@@ -1,186 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.cache;
import engine.gameManager.ConfigManager;
import engine.mbEnums;
import engine.parsers.objects.DeedTemplate;
import org.json.JSONArray;
import org.json.JSONObject;
import org.pmw.tinylog.Logger;
import java.io.File;
import java.util.HashMap;
// Loads DEED templates from the client cache JSON (COBJECTS/DEED/<id>.json).
public class DeedParser {
private static final String deedPath = ConfigManager.DEFAULT_DATA_DIR + "COBJECTS/DEED/";
public static HashMap<Integer, DeedTemplate> parseDeedFolder() {
HashMap<Integer, DeedTemplate> deedTemplates = new HashMap<>();
File[] deedFiles = CacheParserUtil.listJsonFiles(deedPath);
int templateId;
JSONObject deedJson;
int failedCount = 0;
for (File deedFile : deedFiles) {
try {
templateId = CacheParserUtil.templateIdFromFile(deedFile);
deedJson = CacheParserUtil.readJsonFile(deedFile);
deedTemplates.put(templateId, parseDeedEntry(templateId, deedJson));
} catch (Exception e) {
Logger.error(deedFile.getName() + ": " + e);
failedCount++;
}
}
Logger.info("Loaded " + deedTemplates.size() + " of " + deedFiles.length + " deed templates");
// Partial deed data is never usable; null tells the caller to abort
if (failedCount > 0)
return null;
return deedTemplates;
}
private static DeedTemplate parseDeedEntry(int templateId, JSONObject deedJson) {
DeedTemplate deed = new DeedTemplate();
JSONObject raceReq;
JSONObject classReq;
JSONObject discReq;
JSONArray itemFlags;
String flag;
deed.template_id = templateId;
// obj_
deed.obj_name = deedJson.getString("obj_name");
deed.obj_pickable = deedJson.getBoolean("obj_pickable");
deed.obj_gravity = deedJson.getFloat("obj_gravity");
deed.obj_cull_distance = deedJson.getFloat("obj_cull_distance");
deed.obj_scale = CacheParserUtil.readVector3(deedJson.getJSONArray("obj_scale"));
deed.obj_render_object = deedJson.getInt("obj_render_object");
deed.obj_double_fusion = deedJson.getBoolean("obj_double_fusion");
deed.obj_forward_vector = CacheParserUtil.readVector3(deedJson.getJSONArray("obj_forward_vector"));
deed.obj_tracking_name = deedJson.getString("obj_tracking_name");
deed.obj_max_tracking_distance = deedJson.getFloat("obj_max_tracking_distance");
deed.obj_icon = deedJson.getInt("obj_icon");
deed.obj_gravity_f = deedJson.getFloat("obj_gravity_f");
deed.obj_sound_events.putAll(CacheParserUtil.readStringValueMap(deedJson.getJSONArray("obj_sound_events"), "sound_type", "sound_event"));
deed.obj_arc_hardpoint_list = deedJson.getJSONArray("obj_arc_hardpoint_list");
deed.obj_sparse_data.putAll(CacheParserUtil.readSparseData(deedJson.getJSONObject("obj_sparse_data")));
deed.obj_render_object_low_detail = deedJson.getInt("obj_render_object_low_detail");
deed.obj_default_alignment = CacheParserUtil.readVector3(deedJson.getJSONArray("obj_default_alignment"));
deed.obj_sound_table = CacheParserUtil.readLabel(deedJson, "obj_sound_table");
// combat_
deed.combat_health_current = deedJson.getFloat("combat_health_current");
deed.combat_health_full = deedJson.getFloat("combat_health_full");
deed.combat_attack_resist.putAll(CacheParserUtil.readEnumFloatMap(mbEnums.DamageType.class, deedJson.getJSONObject("combat_attack_resist"),
templateId, "combat_attack_resist"));
deed.combat_powers = deedJson.getJSONArray("combat_powers");
// item_
deed.item_type = CacheParserUtil.readEnum(mbEnums.ItemType.class, deedJson.getString("item_type"), templateId, "item_type");
deed.item_eq_slots_value = deedJson.getInt("item_eq_slots_value");
deed.item_eq_slots_type = deedJson.getBoolean("item_eq_slots_type");
// The exporter writes ["NONE"] for an empty slot mask
deed.item_eq_slots_or.addAll(CacheParserUtil.readEnumSet(mbEnums.EquipSlotType.class, deedJson.getJSONArray("item_eq_slots_or"), templateId, "item_eq_slots_or"));
deed.item_eq_slots_or.remove(mbEnums.EquipSlotType.NONE);
deed.item_eq_slots_and.addAll(CacheParserUtil.readEnumSet(mbEnums.EquipSlotType.class, deedJson.getJSONArray("item_eq_slots_and"), templateId, "item_eq_slots_and"));
deed.item_eq_slots_and.remove(mbEnums.EquipSlotType.NONE);
deed.item_takeable = deedJson.getBoolean("item_takeable");
deed.item_value = deedJson.getInt("item_value");
deed.item_wt = deedJson.getInt("item_wt");
deed.item_passive_defense_mod = deedJson.getFloat("item_passive_defense_mod");
deed.item_base_name = deedJson.getString("item_base_name");
deed.item_dsc = deedJson.getString("item_dsc");
deed.item_render_object_female = deedJson.getInt("item_render_object_female");
deed.item_health_full = deedJson.getFloat("item_health_full");
deed.item_skill_used = CacheParserUtil.readLabel(deedJson, "item_skill_used");
deed.item_skill_mastery_used = CacheParserUtil.readLabel(deedJson, "item_skill_mastery_used");
deed.item_parry_anim_id = deedJson.getInt("item_parry_anim_id");
deed.item_offering_info.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ShrineType.class, deedJson.getJSONArray("item_offering_info"),
"offering_type", "offering_value", templateId, "item_offering_info"));
// "None" is the client's empty marker, not a flag
itemFlags = deedJson.getJSONArray("item_flags");
for (int i = 0; i < itemFlags.length(); i++) {
flag = itemFlags.getString(i);
if (flag.equals("None"))
continue;
deed.item_flags.add(CacheParserUtil.readEnum(mbEnums.ItemFlags.class, flag, templateId, "item_flags"));
}
deed.item_use_flags.addAll(CacheParserUtil.readEnumSet(mbEnums.ItemUseFlags.class, deedJson.getJSONArray("item_use_flags"), templateId, "item_use_flags"));
deed.item_post_item_id = deedJson.getInt("item_post_item_id");
deed.item_initial_charges = deedJson.getInt("item_initial_charges");
deed.item_book_arcana = deedJson.getInt("item_book_arcana");
deed.item_skill_req.putAll(CacheParserUtil.readStringValueMap(deedJson.getJSONArray("item_skill_req"), "skill_type", "skill_level"));
raceReq = deedJson.getJSONObject("item_race_req");
deed.item_race_req_restrict = raceReq.getBoolean("restrict");
deed.item_race_req.addAll(CacheParserUtil.readEnumSet(mbEnums.MonsterType.class, raceReq.getJSONArray("races"), templateId, "item_race_req"));
classReq = deedJson.getJSONObject("item_class_req");
deed.item_class_req_restrict = classReq.getBoolean("restrict");
deed.item_class_req.addAll(CacheParserUtil.readEnumSet(mbEnums.ClassType.class, classReq.getJSONArray("classes"), templateId, "item_class_req"));
discReq = deedJson.getJSONObject("item_disc_req");
deed.item_disc_req_restrict = discReq.getBoolean("restrict");
deed.item_disc_req.addAll(CacheParserUtil.readEnumSet(mbEnums.DisciplineType.class, discReq.getJSONArray("discs"), templateId, "item_disc_req"));
deed.item_attr_req.putAll(CacheParserUtil.readEnumValueMap(mbEnums.AttributeType.class, deedJson.getJSONArray("item_attr_req"),
"attr_type", "attr_value", templateId, "item_attr_req"));
deed.item_level_req = deedJson.getInt("item_level_req");
deed.item_rank_req = deedJson.getInt("item_rank_req");
deed.item_sex_req = CacheParserUtil.readEnum(mbEnums.SexType.class, deedJson.getString("item_sex_req"), templateId, "item_sex_req");
deed.item_user_power_action.addAll(CacheParserUtil.readUserPowerActions(deedJson.getJSONArray("item_user_power_action")));
deed.item_power_grant.addAll(CacheParserUtil.readPowerGrants(deedJson.getJSONArray("item_power_grant"), templateId));
deed.item_power_action.putAll(CacheParserUtil.readPowerActions(deedJson.getJSONArray("item_power_action")));
deed.item_sheathable = deedJson.getBoolean("item_sheathable");
deed.item_has_stub = deedJson.getBoolean("item_has_stub");
deed.item_offering_adjustments.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ShrineType.class, deedJson.getJSONArray("item_offering_adjustments"),
"offering_type", "offering_value", templateId, "item_offering_adjustments"));
deed.item_resource_costs.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ResourceType.class, deedJson.getJSONArray("item_resource_costs"),
"resource_type", "resource_value", templateId, "item_resource_costs"));
deed.item_bane_rank = deedJson.getInt("item_bane_rank");
deed.item_ignore_saved_actions = deedJson.getBoolean("item_ignore_saved_actions");
// deed_
deed.deed_type = deedJson.getInt("deed_type");
deed.deed_furniture_id = deedJson.getInt("deed_furniture_id");
deed.deed_target_id = deedJson.getInt("deed_target_id");
deed.deed_employment = deedJson.getInt("deed_employment");
deed.deed_start_rank = deedJson.getInt("deed_start_rank");
deed.deed_name_lookup = deedJson.getInt("deed_name_lookup");
deed.deed_indoors = deedJson.getBoolean("deed_indoors");
deed.deed_is_fortress = deedJson.getBoolean("deed_is_fortress");
deed.deed_namelookup_val = deedJson.getFloat("deed_namelookup_val");
deed.deed_custom_city = deedJson.getBoolean("deed_custom_city");
deed.deed_structure_id = deedJson.getInt("deed_structure_id");
return deed;
}
}
-248
View File
@@ -1,248 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.cache;
import engine.gameManager.ConfigManager;
import engine.mbEnums;
import engine.parsers.objects.ItemTemplate;
import org.json.JSONArray;
import org.json.JSONObject;
import org.pmw.tinylog.Logger;
import java.io.File;
import java.util.HashMap;
// Loads ITEM templates from the client cache JSON (COBJECTS/ITEM/<id>.json).
public class ItemParser {
private static final String itemPath = ConfigManager.DEFAULT_DATA_DIR + "COBJECTS/ITEM/";
public static HashMap<Integer, ItemTemplate> parseItemFolder() {
HashMap<Integer, ItemTemplate> itemTemplates = new HashMap<>();
File[] itemFiles = CacheParserUtil.listJsonFiles(itemPath);
int templateId;
JSONObject itemJson;
int failedCount = 0;
for (File itemFile : itemFiles) {
try {
templateId = CacheParserUtil.templateIdFromFile(itemFile);
itemJson = CacheParserUtil.readJsonFile(itemFile);
itemTemplates.put(templateId, parseItemEntry(templateId, itemJson));
} catch (Exception e) {
Logger.error(itemFile.getName() + ": " + e);
failedCount++;
}
}
Logger.info("Loaded " + itemTemplates.size() + " of " + itemFiles.length + " item templates");
// Partial item data is never usable; null tells the caller to abort
if (failedCount > 0)
return null;
return itemTemplates;
}
private static ItemTemplate parseItemEntry(int templateId, JSONObject itemJson) {
ItemTemplate item = new ItemTemplate();
JSONObject raceReq;
JSONObject classReq;
JSONObject discReq;
JSONArray itemFlags;
JSONArray useFlags;
String flag;
Object stubJson;
JSONArray stubHolder;
item.template_id = templateId;
// obj_
item.obj_name = itemJson.getString("obj_name");
item.obj_pickable = itemJson.getBoolean("obj_pickable");
item.obj_gravity = itemJson.getFloat("obj_gravity");
item.obj_cull_distance = itemJson.getFloat("obj_cull_distance");
item.obj_scale = CacheParserUtil.readVector3(itemJson.getJSONArray("obj_scale"));
item.obj_render_object = itemJson.getInt("obj_render_object");
item.obj_double_fusion = itemJson.getBoolean("obj_double_fusion");
item.obj_forward_vector = CacheParserUtil.readVector3(itemJson.getJSONArray("obj_forward_vector"));
item.obj_tracking_name = itemJson.getString("obj_tracking_name");
item.obj_max_tracking_distance = itemJson.getFloat("obj_max_tracking_distance");
item.obj_icon = itemJson.getInt("obj_icon");
item.obj_gravity_f = itemJson.getFloat("obj_gravity_f");
item.obj_sound_events.putAll(CacheParserUtil.readStringValueMap(itemJson.getJSONArray("obj_sound_events"), "sound_type", "sound_event"));
item.obj_arc_hardpoint_list = itemJson.getJSONArray("obj_arc_hardpoint_list");
item.obj_sparse_data.putAll(CacheParserUtil.readSparseData(itemJson.getJSONObject("obj_sparse_data")));
item.obj_render_object_low_detail = itemJson.getInt("obj_render_object_low_detail");
item.obj_default_alignment = CacheParserUtil.readVector3(itemJson.getJSONArray("obj_default_alignment"));
item.obj_sound_table = CacheParserUtil.readHashLabel(itemJson, "obj_sound_table", templateId);
// combat_
item.combat_health_current = itemJson.getFloat("combat_health_current");
item.combat_health_full = itemJson.getFloat("combat_health_full");
item.combat_attack_resist.putAll(CacheParserUtil.readEnumFloatMap(mbEnums.DamageType.class, itemJson.getJSONObject("combat_attack_resist"),
templateId, "combat_attack_resist"));
item.combat_powers = itemJson.getJSONArray("combat_powers");
// item_
item.item_type = CacheParserUtil.readEnum(mbEnums.ItemType.class, itemJson.getString("item_type"), templateId, "item_type");
item.item_eq_slots_value = itemJson.getInt("item_eq_slots_value");
item.item_eq_slots_type = itemJson.getBoolean("item_eq_slots_type");
// The exporter writes ["NONE"] for an empty slot mask
item.item_eq_slots_or.addAll(CacheParserUtil.readEnumSet(mbEnums.EquipSlotType.class, itemJson.getJSONArray("item_eq_slots_or"), templateId, "item_eq_slots_or"));
item.item_eq_slots_or.remove(mbEnums.EquipSlotType.NONE);
item.item_eq_slots_and.addAll(CacheParserUtil.readEnumSet(mbEnums.EquipSlotType.class, itemJson.getJSONArray("item_eq_slots_and"), templateId, "item_eq_slots_and"));
item.item_eq_slots_and.remove(mbEnums.EquipSlotType.NONE);
item.item_takeable = itemJson.getBoolean("item_takeable");
item.item_value = itemJson.getInt("item_value");
item.item_wt = itemJson.getInt("item_wt");
item.item_passive_defense_mod = itemJson.getFloat("item_passive_defense_mod");
item.item_base_name = itemJson.getString("item_base_name");
item.item_dsc = itemJson.getString("item_dsc");
item.item_render_object_female = itemJson.getInt("item_render_object_female");
item.item_health_full = itemJson.getFloat("item_health_full");
item.item_skill_used = CacheParserUtil.readHashLabel(itemJson, "item_skill_used", templateId);
item.item_skill_mastery_used = CacheParserUtil.readHashLabel(itemJson, "item_skill_mastery_used", templateId);
item.item_parry_anim_id = itemJson.getInt("item_parry_anim_id");
item.item_offering_info.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ShrineType.class, itemJson.getJSONArray("item_offering_info"),
"offering_type", "offering_value", templateId, "item_offering_info"));
// The client reads these blocks by item type, not by key presence
if (item.item_type == mbEnums.ItemType.WEAPON) {
item.item_weapon = parseWeapon(templateId, itemJson.getJSONObject("item_weapon"));
item.item_primary_attr = CacheParserUtil.readEnum(mbEnums.AttributeType.class, itemJson.getString("item_primary_attr"), templateId, "item_primary_attr");
item.item_secondary_attr = CacheParserUtil.readEnum(mbEnums.AttributeType.class, itemJson.getString("item_secondary_attr"), templateId, "item_secondary_attr");
}
if (item.item_type == mbEnums.ItemType.ARMOR) {
item.item_bulk_factor = itemJson.getFloat("item_bulk_factor");
item.item_defense_rating = itemJson.getInt("item_defense_rating");
}
// "None" is bit 0 in the client's flag tables, not a real flag
itemFlags = itemJson.getJSONArray("item_flags");
for (int i = 0; i < itemFlags.length(); i++) {
flag = itemFlags.getString(i);
if (flag.equals("None"))
continue;
item.item_flags.add(CacheParserUtil.readEnum(mbEnums.ItemFlags.class, flag, templateId, "item_flags"));
}
useFlags = itemJson.getJSONArray("item_use_flags");
for (int i = 0; i < useFlags.length(); i++) {
flag = useFlags.getString(i);
if (flag.equals("NONE"))
continue;
item.item_use_flags.add(CacheParserUtil.readEnum(mbEnums.ItemUseFlags.class, flag, templateId, "item_use_flags"));
}
item.item_post_item_id = itemJson.getInt("item_post_item_id");
item.item_initial_charges = itemJson.getInt("item_initial_charges");
item.item_book_arcana = itemJson.getInt("item_book_arcana");
item.item_skill_req.putAll(CacheParserUtil.readStringValueMap(itemJson.getJSONArray("item_skill_req"), "skill_type", "skill_level"));
raceReq = itemJson.getJSONObject("item_race_req");
item.item_race_req_restrict = raceReq.getBoolean("restrict");
item.item_race_req.addAll(CacheParserUtil.readEnumSet(mbEnums.MonsterType.class, raceReq.getJSONArray("races"), templateId, "item_race_req"));
classReq = itemJson.getJSONObject("item_class_req");
item.item_class_req_restrict = classReq.getBoolean("restrict");
item.item_class_req.addAll(CacheParserUtil.readEnumSet(mbEnums.ClassType.class, classReq.getJSONArray("classes"), templateId, "item_class_req"));
discReq = itemJson.getJSONObject("item_disc_req");
item.item_disc_req_restrict = discReq.getBoolean("restrict");
item.item_disc_req.addAll(CacheParserUtil.readEnumSet(mbEnums.DisciplineType.class, discReq.getJSONArray("discs"), templateId, "item_disc_req"));
item.item_attr_req.putAll(CacheParserUtil.readEnumValueMap(mbEnums.AttributeType.class, itemJson.getJSONArray("item_attr_req"),
"attr_type", "attr_value", templateId, "item_attr_req"));
item.item_level_req = itemJson.getInt("item_level_req");
item.item_rank_req = itemJson.getInt("item_rank_req");
item.item_sex_req = CacheParserUtil.readEnum(mbEnums.SexType.class, itemJson.getString("item_sex_req"), templateId, "item_sex_req");
item.item_user_power_action.addAll(CacheParserUtil.readUserPowerActions(itemJson.getJSONArray("item_user_power_action")));
item.item_power_grant.addAll(CacheParserUtil.readPowerGrants(itemJson.getJSONArray("item_power_grant"), templateId));
item.item_power_action.putAll(CacheParserUtil.readPowerActions(itemJson.getJSONArray("item_power_action")));
item.item_sheathable = itemJson.getBoolean("item_sheathable");
if (item.item_sheathable) {
item.item_sheath_slot = CacheParserUtil.readEnum(mbEnums.SheathSlot.class, itemJson.getString("item_sheath_slot"), templateId, "item_sheath_slot");
item.item_sheath_offset = CacheParserUtil.readVector3(itemJson.getJSONArray("item_sheath_offset"));
item.item_sheath_rotation = CacheParserUtil.readVector3(itemJson.getJSONArray("item_sheath_rotation"));
}
stubJson = itemJson.get("item_has_stub");
if (stubJson instanceof JSONArray) {
stubHolder = (JSONArray) stubJson;
item.item_has_stub = true;
item.item_stub_flag = stubHolder.getBoolean(0);
item.item_stub_id = stubHolder.getInt(1);
} else {
item.item_has_stub = itemJson.getBoolean("item_has_stub");
}
item.item_offering_adjustments.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ShrineType.class, itemJson.getJSONArray("item_offering_adjustments"),
"offering_type", "offering_value", templateId, "item_offering_adjustments"));
item.item_resource_costs.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ResourceType.class, itemJson.getJSONArray("item_resource_costs"),
"resource_type", "resource_value", templateId, "item_resource_costs"));
item.item_bane_rank = itemJson.getInt("item_bane_rank");
item.item_ignore_saved_actions = itemJson.getBoolean("item_ignore_saved_actions");
return item;
}
private static ItemTemplate.Weapon parseWeapon(int templateId, JSONObject weaponJson) {
ItemTemplate.Weapon weapon = new ItemTemplate.Weapon();
JSONArray damageJson;
JSONObject damageEntry;
ItemTemplate.Damage damage;
weapon.weapon_wepspeed = weaponJson.getFloat("weapon_wepspeed");
weapon.weapon_max_range = weaponJson.getFloat("weapon_max_range");
weapon.weapon_projectile_id = weaponJson.getInt("weapon_projectile_id");
weapon.weapon_projectile_speed = weaponJson.getFloat("weapon_projectile_speed");
weapon.weapon_combat_idle_anim = weaponJson.getInt("weapon_combat_idle_anim");
damageJson = weaponJson.getJSONArray("weapon_damage");
for (int i = 0; i < damageJson.length(); i++) {
damageEntry = damageJson.getJSONObject(i);
damage = new ItemTemplate.Damage();
damage.damage_type = CacheParserUtil.readEnum(mbEnums.DamageType.class, damageEntry.getString("damage_type"), templateId, "weapon_damage");
damage.damage_min = damageEntry.getInt("damage_min");
damage.damage_max = damageEntry.getInt("damage_max");
weapon.weapon_damage.add(damage);
}
weapon.weapon_attack_anim_right.addAll(CacheParserUtil.readIntArrays(weaponJson.getJSONArray("weapon_attack_anim_right")));
weapon.weapon_attack_anim_left.addAll(CacheParserUtil.readIntArrays(weaponJson.getJSONArray("weapon_attack_anim_left")));
return weapon;
}
}
-84
View File
@@ -1,84 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.cache;
import engine.gameManager.ConfigManager;
import org.pmw.tinylog.Logger;
import java.util.LinkedHashMap;
import java.util.Objects;
import java.util.function.Consumer;
// Dev-only check that compares DB-built objects with the cache JSON before a loader is switched.
// Enabled by the optional env var MB_PARITY_CHECK; not in the ConfigManager enum, which requires every entry.
public class ParityCheck {
private static final String FLAG_NAME = "MB_PARITY_CHECK";
private static final LinkedHashMap<String, Consumer<ParityCheck>> comparators = new LinkedHashMap<>();
private final String table;
private int comparedCount = 0;
private int differenceCount = 0;
private int missingCount = 0;
private ParityCheck(String table) {
this.table = table;
}
public static boolean isEnabled() {
return ConfigManager.configMap.getOrDefault(FLAG_NAME, "false").equalsIgnoreCase("true");
}
public static void register(String table, Consumer<ParityCheck> comparator) {
comparators.put(table, comparator);
}
public static void run() {
ParityCheck check;
for (String table : comparators.keySet()) {
check = new ParityCheck(table);
try {
comparators.get(table).accept(check);
} catch (Exception e) {
Logger.error("Parity: " + table + ": comparator failed: " + e);
}
Logger.info("Parity: " + table + ": " + check.comparedCount + " compared, "
+ check.differenceCount + " differences, " + check.missingCount + " missing in json");
}
}
// Returns false when the row has no JSON counterpart, so the comparator can skip its fields.
public boolean compareRow(int id, Object jsonObject) {
comparedCount++;
if (jsonObject == null) {
missingCount++;
Logger.warn("Parity: " + table + "/" + id + ": missing in json");
return false;
}
return true;
}
public void compareField(int id, String field, Object dbValue, Object jsonValue) {
if (Objects.equals(dbValue, jsonValue))
return;
differenceCount++;
Logger.warn("Parity: " + table + "/" + id + "/" + field + ": db=" + dbValue + " json=" + jsonValue);
}
}
-338
View File
@@ -1,338 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.cache;
import engine.gameManager.ConfigManager;
import engine.mbEnums;
import engine.parsers.objects.RuneTemplate;
import org.json.JSONArray;
import org.json.JSONObject;
import org.pmw.tinylog.Logger;
import java.io.File;
import java.util.HashMap;
// Loads RUNE templates from the client cache JSON (COBJECTS/RUNE/<id>.json).
public class RuneParser {
private static final String runePath = ConfigManager.DEFAULT_DATA_DIR + "COBJECTS/RUNE/";
public static HashMap<Integer, RuneTemplate> parseRuneFolder() {
HashMap<Integer, RuneTemplate> runeTemplates = new HashMap<>();
File[] runeFiles = CacheParserUtil.listJsonFiles(runePath);
int templateId;
JSONObject runeJson;
int failedCount = 0;
for (File runeFile : runeFiles) {
try {
templateId = CacheParserUtil.templateIdFromFile(runeFile);
runeJson = CacheParserUtil.readJsonFile(runeFile);
runeTemplates.put(templateId, parseRuneEntry(templateId, runeJson));
} catch (Exception e) {
Logger.error(runeFile.getName() + ": " + e);
failedCount++;
}
}
Logger.info("Loaded " + runeTemplates.size() + " of " + runeFiles.length + " rune templates");
// Partial rune data is never usable; null tells the caller to abort
if (failedCount > 0)
return null;
return runeTemplates;
}
private static RuneTemplate parseRuneEntry(int templateId, JSONObject runeJson) {
RuneTemplate rune = new RuneTemplate();
JSONObject raceReq;
JSONObject classReq;
JSONObject discReq;
JSONArray itemFlags;
String flag;
Object subType;
JSONObject speedJson;
JSONObject groupJson;
JSONArray skillGrantsJson;
JSONObject skillGrantJson;
RuneTemplate.SkillGrant skillGrant;
JSONArray skillAdjJson;
JSONObject skillAdjEntry;
JSONArray naturalAttacksJson;
JSONArray inventoryJson;
JSONObject inventoryEntryJson;
RuneTemplate.InventoryEntry inventoryEntry;
JSONArray bodyPartsJson;
JSONObject bodyPartJson;
RuneTemplate.BodyPart bodyPart;
rune.template_id = templateId;
// obj_
rune.obj_name = runeJson.getString("obj_name");
rune.obj_pickable = runeJson.getBoolean("obj_pickable");
rune.obj_gravity = runeJson.getFloat("obj_gravity");
rune.obj_cull_distance = runeJson.getFloat("obj_cull_distance");
rune.obj_scale = CacheParserUtil.readVector3(runeJson.getJSONArray("obj_scale"));
rune.obj_render_object = runeJson.getInt("obj_render_object");
rune.obj_double_fusion = runeJson.getBoolean("obj_double_fusion");
rune.obj_forward_vector = CacheParserUtil.readVector3(runeJson.getJSONArray("obj_forward_vector"));
rune.obj_tracking_name = runeJson.getString("obj_tracking_name");
rune.obj_max_tracking_distance = runeJson.getFloat("obj_max_tracking_distance");
rune.obj_icon = runeJson.getInt("obj_icon");
rune.obj_gravity_f = runeJson.getFloat("obj_gravity_f");
rune.obj_sound_events.putAll(CacheParserUtil.readStringValueMap(runeJson.getJSONArray("obj_sound_events"), "sound_type", "sound_event"));
rune.obj_arc_hardpoint_list = runeJson.getJSONArray("obj_arc_hardpoint_list");
rune.obj_sparse_data.putAll(CacheParserUtil.readSparseData(runeJson.getJSONObject("obj_sparse_data")));
rune.obj_render_object_low_detail = runeJson.getInt("obj_render_object_low_detail");
rune.obj_default_alignment = CacheParserUtil.readVector3(runeJson.getJSONArray("obj_default_alignment"));
rune.obj_sound_table = CacheParserUtil.readLabel(runeJson, "obj_sound_table");
// combat_
rune.combat_health_current = runeJson.getFloat("combat_health_current");
rune.combat_health_full = runeJson.getFloat("combat_health_full");
rune.combat_attack_resist.putAll(CacheParserUtil.readEnumFloatMap(mbEnums.DamageType.class, runeJson.getJSONObject("combat_attack_resist"),
templateId, "combat_attack_resist"));
rune.combat_powers = runeJson.getJSONArray("combat_powers");
// item_
rune.item_type = CacheParserUtil.readEnum(mbEnums.ItemType.class, runeJson.getString("item_type"), templateId, "item_type");
rune.item_eq_slots_value = runeJson.getInt("item_eq_slots_value");
rune.item_eq_slots_type = runeJson.getBoolean("item_eq_slots_type");
// The exporter writes ["NONE"] for an empty slot mask
rune.item_eq_slots_or.addAll(CacheParserUtil.readEnumSet(mbEnums.EquipSlotType.class, runeJson.getJSONArray("item_eq_slots_or"), templateId, "item_eq_slots_or"));
rune.item_eq_slots_or.remove(mbEnums.EquipSlotType.NONE);
rune.item_eq_slots_and.addAll(CacheParserUtil.readEnumSet(mbEnums.EquipSlotType.class, runeJson.getJSONArray("item_eq_slots_and"), templateId, "item_eq_slots_and"));
rune.item_eq_slots_and.remove(mbEnums.EquipSlotType.NONE);
rune.item_takeable = runeJson.getBoolean("item_takeable");
rune.item_value = runeJson.getInt("item_value");
rune.item_wt = runeJson.getInt("item_wt");
rune.item_passive_defense_mod = runeJson.getFloat("item_passive_defense_mod");
rune.item_base_name = runeJson.getString("item_base_name");
rune.item_dsc = runeJson.getString("item_dsc");
rune.item_render_object_female = runeJson.getInt("item_render_object_female");
rune.item_health_full = runeJson.getFloat("item_health_full");
rune.item_skill_used = CacheParserUtil.readLabel(runeJson, "item_skill_used");
rune.item_skill_mastery_used = CacheParserUtil.readLabel(runeJson, "item_skill_mastery_used");
rune.item_parry_anim_id = runeJson.getInt("item_parry_anim_id");
rune.item_offering_info.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ShrineType.class, runeJson.getJSONArray("item_offering_info"),
"offering_type", "offering_value", templateId, "item_offering_info"));
// "None" is the client's empty marker, not a flag
itemFlags = runeJson.getJSONArray("item_flags");
for (int i = 0; i < itemFlags.length(); i++) {
flag = itemFlags.getString(i);
if (flag.equals("None"))
continue;
rune.item_flags.add(CacheParserUtil.readEnum(mbEnums.ItemFlags.class, flag, templateId, "item_flags"));
}
rune.item_use_flags.addAll(CacheParserUtil.readEnumSet(mbEnums.ItemUseFlags.class, runeJson.getJSONArray("item_use_flags"), templateId, "item_use_flags"));
rune.item_post_item_id = runeJson.getInt("item_post_item_id");
rune.item_initial_charges = runeJson.getInt("item_initial_charges");
rune.item_book_arcana = runeJson.getInt("item_book_arcana");
rune.item_skill_req.putAll(CacheParserUtil.readStringValueMap(runeJson.getJSONArray("item_skill_req"), "skill_type", "skill_level"));
raceReq = runeJson.getJSONObject("item_race_req");
rune.item_race_req_restrict = raceReq.getBoolean("restrict");
rune.item_race_req.addAll(CacheParserUtil.readEnumSet(mbEnums.MonsterType.class, raceReq.getJSONArray("races"), templateId, "item_race_req"));
classReq = runeJson.getJSONObject("item_class_req");
rune.item_class_req_restrict = classReq.getBoolean("restrict");
rune.item_class_req.addAll(CacheParserUtil.readEnumSet(mbEnums.ClassType.class, classReq.getJSONArray("classes"), templateId, "item_class_req"));
discReq = runeJson.getJSONObject("item_disc_req");
rune.item_disc_req_restrict = discReq.getBoolean("restrict");
rune.item_disc_req.addAll(CacheParserUtil.readEnumSet(mbEnums.DisciplineType.class, discReq.getJSONArray("discs"), templateId, "item_disc_req"));
rune.item_attr_req.putAll(CacheParserUtil.readEnumValueMap(mbEnums.AttributeType.class, runeJson.getJSONArray("item_attr_req"),
"attr_type", "attr_value", templateId, "item_attr_req"));
rune.item_level_req = runeJson.getInt("item_level_req");
rune.item_rank_req = runeJson.getInt("item_rank_req");
rune.item_sex_req = CacheParserUtil.readEnum(mbEnums.SexType.class, runeJson.getString("item_sex_req"), templateId, "item_sex_req");
rune.item_user_power_action.addAll(CacheParserUtil.readUserPowerActions(runeJson.getJSONArray("item_user_power_action")));
rune.item_power_grant.addAll(CacheParserUtil.readPowerGrants(runeJson.getJSONArray("item_power_grant"), templateId));
rune.item_power_action.putAll(CacheParserUtil.readPowerActions(runeJson.getJSONArray("item_power_action")));
rune.item_sheathable = runeJson.getBoolean("item_sheathable");
rune.item_has_stub = runeJson.getBoolean("item_has_stub");
rune.item_offering_adjustments.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ShrineType.class, runeJson.getJSONArray("item_offering_adjustments"),
"offering_type", "offering_value", templateId, "item_offering_adjustments"));
rune.item_resource_costs.putAll(CacheParserUtil.readEnumValueMap(mbEnums.ResourceType.class, runeJson.getJSONArray("item_resource_costs"),
"resource_type", "resource_value", templateId, "item_resource_costs"));
rune.item_bane_rank = runeJson.getInt("item_bane_rank");
rune.item_ignore_saved_actions = runeJson.getBoolean("item_ignore_saved_actions");
// rune_
rune.rune_type = CacheParserUtil.readEnum(mbEnums.RuneType.class, runeJson.getString("rune_type"), templateId, "rune_type");
subType = runeJson.get("rune_sub_type");
if (subType instanceof String) {
rune.rune_sub_type = (String) subType;
} else {
rune.rune_sub_type = "";
rune.rune_sub_type_hash = (int) runeJson.getLong("rune_sub_type");
}
rune.rune_is_standard_character_creation = runeJson.getBoolean("rune_is_standard_character_creation");
rune.rune_creation_cost = runeJson.getInt("rune_creation_cost");
rune.rune_rank = runeJson.getInt("rune_rank");
rune.rune_pracs_per_level = runeJson.getInt("rune_pracs_per_level");
rune.rune_exp_req_to_level = runeJson.getFloat("rune_exp_req_to_level");
rune.rune_sex = CacheParserUtil.readEnum(mbEnums.SexType.class, runeJson.getString("rune_sex"), templateId, "rune_sex");
rune.rune_class_icon = runeJson.getInt("rune_class_icon");
rune.rune_health = runeJson.getInt("rune_health");
rune.rune_mana = runeJson.getInt("rune_mana");
rune.rune_stamina = runeJson.getInt("rune_stamina");
rune.rune_min_damage = runeJson.getFloat("rune_min_damage");
rune.rune_max_damage = runeJson.getFloat("rune_max_damage");
rune.rune_attack = runeJson.getInt("rune_attack");
rune.rune_defense = runeJson.getInt("rune_defense");
rune.rune_level = runeJson.getInt("rune_level");
speedJson = runeJson.getJSONObject("rune_speed");
for (String speedKey : speedJson.keySet())
rune.rune_speed.put(CacheParserUtil.readEnum(mbEnums.MovementType.class, speedKey, templateId, "rune_speed"), speedJson.getFloat(speedKey));
groupJson = runeJson.getJSONObject("rune_group");
rune.rune_group_type = groupJson.getInt("group_type");
rune.rune_group_is_faction = groupJson.getBoolean("group_is_faction");
rune.rune_group_is_guild = groupJson.getBoolean("group_is_guild");
rune.rune_dsc = runeJson.getString("rune_dsc");
rune.rune_fx_txt = runeJson.getString("rune_fx_txt");
rune.rune_group_tactics = runeJson.getLong("rune_group_tactics");
rune.rune_group_role_set = runeJson.getLong("rune_group_role_set");
rune.rune_enemy_monster_types.addAll(CacheParserUtil.readEnumSet(mbEnums.MonsterType.class, runeJson.getJSONArray("rune_enemy_monster_types"),
templateId, "rune_enemy_monster_types"));
rune.rune_groupee_monster_types.addAll(CacheParserUtil.readIntList(runeJson.getJSONArray("rune_groupee_monster_types")));
rune.rune_helper_monster_types.addAll(CacheParserUtil.readIntList(runeJson.getJSONArray("rune_helper_monster_types")));
rune.rune_not_enemy_monster_types.addAll(CacheParserUtil.readEnumSet(mbEnums.MonsterType.class, runeJson.getJSONArray("rune_not_enemy_monster_types"),
templateId, "rune_not_enemy_monster_types"));
rune.rune_enemy_gender = runeJson.getJSONArray("rune_enemy_gender");
skillGrantsJson = runeJson.getJSONArray("rune_skill_grant");
for (int i = 0; i < skillGrantsJson.length(); i++) {
skillGrantJson = skillGrantsJson.getJSONObject(i);
skillGrant = new RuneTemplate.SkillGrant();
skillGrant.skill_type = skillGrantJson.getString("skill_type");
skillGrant.skill_value = skillGrantJson.getInt("skill_value");
skillGrant.skill_granted_attrs.putAll(CacheParserUtil.readGrantPairs(skillGrantJson.getJSONArray("skill_granted_attrs"),
templateId, "skill_granted_attrs"));
skillGrant.skill_granted_skills.putAll(CacheParserUtil.readGrantPairs(skillGrantJson.getJSONArray("skill_granted_skills"),
templateId, "skill_granted_skills"));
skillGrant.skill_granted_powers.putAll(CacheParserUtil.readGrantPairs(skillGrantJson.getJSONArray("skill_granted_powers"),
templateId, "skill_granted_powers"));
skillGrant.skill_monster_types = skillGrantJson.getJSONArray("skill_monster_types");
rune.rune_skill_grant.add(skillGrant);
}
skillAdjJson = runeJson.getJSONArray("rune_skill_adj");
for (int i = 0; i < skillAdjJson.length(); i++) {
skillAdjEntry = skillAdjJson.getJSONObject(i);
rune.rune_skill_adj.put(skillAdjEntry.getString("skill_type"),
CacheParserUtil.readIntArrays(skillAdjEntry.getJSONArray("skill_adjusts")));
}
rune.rune_attr_adj.putAll(CacheParserUtil.readEnumValueMap(mbEnums.AttributeType.class, runeJson.getJSONArray("rune_attr_adj"),
"attr_type", "attr_value", templateId, "rune_attr_adj"));
rune.rune_max_attr_adj.putAll(CacheParserUtil.readEnumValueMap(mbEnums.AttributeType.class, runeJson.getJSONArray("rune_max_attr_adj"),
"attr_type", "attr_value", templateId, "rune_max_attr_adj"));
naturalAttacksJson = runeJson.getJSONArray("rune_naturalattacks");
for (int i = 0; i < naturalAttacksJson.length(); i++)
rune.rune_naturalattacks.add(CacheParserUtil.readFloatArray(naturalAttacksJson.getJSONArray(i)));
rune.rune_enchantment_type = runeJson.getJSONArray("rune_enchantment_type");
inventoryJson = runeJson.getJSONArray("rune_inventory_contents");
for (int i = 0; i < inventoryJson.length(); i++) {
inventoryEntryJson = inventoryJson.getJSONObject(i);
inventoryEntry = new RuneTemplate.InventoryEntry();
inventoryEntry.type = inventoryEntryJson.getString("type");
if (inventoryEntryJson.has("gold"))
inventoryEntry.values = CacheParserUtil.readFloatArray(inventoryEntryJson.getJSONArray("gold"));
else if (inventoryEntryJson.has("table"))
inventoryEntry.values = CacheParserUtil.readFloatArray(inventoryEntryJson.getJSONArray("table"));
else
Logger.error(templateId + ": rune_inventory_contents entry of type " + inventoryEntry.type + " has no values");
rune.rune_inventory_contents.add(inventoryEntry);
}
rune.rune_renderable = runeJson.getBoolean("rune_renderable");
// Render fields are absent on some runes
if (runeJson.has("rune_scale_factor"))
rune.rune_scale_factor = CacheParserUtil.readVector3(runeJson.getJSONArray("rune_scale_factor"));
if (runeJson.has("rune_skeleton"))
rune.rune_skeleton = runeJson.getInt("rune_skeleton");
if (runeJson.has("rune_slope_hugger"))
rune.rune_slope_hugger = runeJson.getBoolean("rune_slope_hugger");
if (runeJson.has("rune_can_fly"))
rune.rune_can_fly = runeJson.getBoolean("rune_can_fly");
if (runeJson.has("rune_death_effect"))
rune.rune_death_effect = runeJson.getInt("rune_death_effect");
if (runeJson.has("rune_tombstone_id"))
rune.rune_tombstone_id = runeJson.getInt("rune_tombstone_id");
if (runeJson.has("rune_body_parts")) {
bodyPartsJson = runeJson.getJSONArray("rune_body_parts");
for (int i = 0; i < bodyPartsJson.length(); i++) {
bodyPartJson = bodyPartsJson.getJSONObject(i);
bodyPart = new RuneTemplate.BodyPart();
bodyPart.body_part_render = bodyPartJson.getInt("body_part_render");
bodyPart.body_part_position = CacheParserUtil.readVector3(bodyPartJson.getJSONArray("body_part_position"));
rune.rune_body_parts.add(bodyPart);
}
}
if (runeJson.has("rune_hair"))
rune.rune_hair.addAll(CacheParserUtil.readIntList(runeJson.getJSONArray("rune_hair")));
if (runeJson.has("rune_beard"))
rune.rune_beard.addAll(CacheParserUtil.readIntList(runeJson.getJSONArray("rune_beard")));
rune.rune_natural_power_attack = runeJson.getInt("rune_natural_power_attack");
rune.rune_sparse_data.putAll(CacheParserUtil.readSparseData(runeJson.getJSONObject("rune_sparse_data")));
return rune;
}
}
@@ -1,99 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.objects;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import engine.parsers.cache.CObjectIndex;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
// Common type for ITEM, DEED and RUNE cache templates, which share one id space.
// Getters cover only the obj_/combat_/item_ fields all three define (JSON-Refactor-Plan D1).
// Returned collections are the template's own; never modify them.
public interface CObjectTemplate {
static CObjectTemplate lookup(int templateId) {
return CObjectIndex.lookup(templateId);
}
int getTemplateId();
String getObjName();
boolean getObjPickable();
float getObjGravity();
float getObjCullDistance();
Vector3fImmutable getObjScale();
int getObjRenderObject();
boolean getObjDoubleFusion();
Vector3fImmutable getObjForwardVector();
String getObjTrackingName();
float getObjMaxTrackingDistance();
int getObjIcon();
float getObjGravityF();
LinkedHashMap<String, Integer> getObjSoundEvents();
JSONArray getObjArcHardpointList();
HashMap<String, String> getObjSparseData();
int getObjRenderObjectLowDetail();
Vector3fImmutable getObjDefaultAlignment();
String getObjSoundTable();
float getCombatHealthCurrent();
float getCombatHealthFull();
EnumMap<mbEnums.DamageType, Float> getCombatAttackResist();
JSONArray getCombatPowers();
mbEnums.ItemType getItemType();
int getItemEqSlotsValue();
boolean getItemEqSlotsType();
EnumSet<mbEnums.EquipSlotType> getItemEqSlotsOr();
EnumSet<mbEnums.EquipSlotType> getItemEqSlotsAnd();
boolean getItemTakeable();
int getItemValue();
int getItemWt();
float getItemPassiveDefenseMod();
String getItemBaseName();
String getItemDsc();
int getItemRenderObjectFemale();
float getItemHealthFull();
String getItemSkillUsed();
String getItemSkillMasteryUsed();
int getItemParryAnimId();
EnumMap<mbEnums.ShrineType, Integer> getItemOfferingInfo();
EnumSet<mbEnums.ItemFlags> getItemFlags();
EnumSet<mbEnums.ItemUseFlags> getItemUseFlags();
int getItemPostItemId();
int getItemInitialCharges();
int getItemBookArcana();
LinkedHashMap<String, Integer> getItemSkillReq();
boolean getItemRaceReqRestrict();
EnumSet<mbEnums.MonsterType> getItemRaceReq();
boolean getItemClassReqRestrict();
EnumSet<mbEnums.ClassType> getItemClassReq();
boolean getItemDiscReqRestrict();
EnumSet<mbEnums.DisciplineType> getItemDiscReq();
EnumMap<mbEnums.AttributeType, Integer> getItemAttrReq();
int getItemLevelReq();
int getItemRankReq();
mbEnums.SexType getItemSexReq();
ArrayList<UserPowerAction> getItemUserPowerAction();
ArrayList<PowerGrant> getItemPowerGrant();
LinkedHashMap<String, ArrayList<int[]>> getItemPowerAction();
boolean getItemSheathable();
boolean getItemHasStub();
EnumMap<mbEnums.ShrineType, Integer> getItemOfferingAdjustments();
EnumMap<mbEnums.ResourceType, Integer> getItemResourceCosts();
int getItemBaneRank();
boolean getItemIgnoreSavedActions();
}
@@ -1,447 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.objects;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
// Deed template as defined by the client's cache data
// (MBDATA/data/COBJECTS/DEED). Field names match the JSON keys.
//
// Values are kept as the client defines them: no req/res splitting,
// no defaults substituted. Strings with a matching enum in mbEnums
// are stored as that enum; everything else stays a String.
//
// Read only once loaded.
public class DeedTemplate implements CObjectTemplate {
public static HashMap<Integer, DeedTemplate> _deeds = new HashMap<>();
public int template_id;
// obj_
public String obj_name;
public boolean obj_pickable;
public float obj_gravity;
public float obj_cull_distance;
public Vector3fImmutable obj_scale;
public int obj_render_object;
public boolean obj_double_fusion;
public Vector3fImmutable obj_forward_vector;
public String obj_tracking_name;
public float obj_max_tracking_distance;
public int obj_icon;
public float obj_gravity_f;
public final LinkedHashMap<String, Integer> obj_sound_events = new LinkedHashMap<>();
public JSONArray obj_arc_hardpoint_list;
public final HashMap<String, String> obj_sparse_data = new HashMap<>();
public int obj_render_object_low_detail;
public Vector3fImmutable obj_default_alignment;
public String obj_sound_table;
// combat_
public float combat_health_current;
public float combat_health_full;
public final EnumMap<mbEnums.DamageType, Float> combat_attack_resist = new EnumMap<>(mbEnums.DamageType.class);
public JSONArray combat_powers;
// item_
public mbEnums.ItemType item_type;
public int item_eq_slots_value;
public boolean item_eq_slots_type;
public final EnumSet<mbEnums.EquipSlotType> item_eq_slots_or = EnumSet.noneOf(mbEnums.EquipSlotType.class);
public final EnumSet<mbEnums.EquipSlotType> item_eq_slots_and = EnumSet.noneOf(mbEnums.EquipSlotType.class);
public boolean item_takeable;
public int item_value;
public int item_wt;
public float item_passive_defense_mod;
public String item_base_name;
public String item_dsc;
public int item_render_object_female;
public float item_health_full;
public String item_skill_used;
public String item_skill_mastery_used;
public int item_parry_anim_id;
public final EnumMap<mbEnums.ShrineType, Integer> item_offering_info = new EnumMap<>(mbEnums.ShrineType.class);
public final EnumSet<mbEnums.ItemFlags> item_flags = EnumSet.noneOf(mbEnums.ItemFlags.class);
public final EnumSet<mbEnums.ItemUseFlags> item_use_flags = EnumSet.noneOf(mbEnums.ItemUseFlags.class);
public int item_post_item_id;
public int item_initial_charges;
public int item_book_arcana;
public final LinkedHashMap<String, Integer> item_skill_req = new LinkedHashMap<>();
public boolean item_race_req_restrict;
public final EnumSet<mbEnums.MonsterType> item_race_req = EnumSet.noneOf(mbEnums.MonsterType.class);
public boolean item_class_req_restrict;
public final EnumSet<mbEnums.ClassType> item_class_req = EnumSet.noneOf(mbEnums.ClassType.class);
public boolean item_disc_req_restrict;
public final EnumSet<mbEnums.DisciplineType> item_disc_req = EnumSet.noneOf(mbEnums.DisciplineType.class);
public final EnumMap<mbEnums.AttributeType, Integer> item_attr_req = new EnumMap<>(mbEnums.AttributeType.class);
public int item_level_req;
public int item_rank_req;
public mbEnums.SexType item_sex_req;
public final ArrayList<UserPowerAction> item_user_power_action = new ArrayList<>();
public final ArrayList<PowerGrant> item_power_grant = new ArrayList<>();
public final LinkedHashMap<String, ArrayList<int[]>> item_power_action = new LinkedHashMap<>();
public boolean item_sheathable;
public boolean item_has_stub;
public final EnumMap<mbEnums.ShrineType, Integer> item_offering_adjustments = new EnumMap<>(mbEnums.ShrineType.class);
public final EnumMap<mbEnums.ResourceType, Integer> item_resource_costs = new EnumMap<>(mbEnums.ResourceType.class);
public int item_bane_rank;
public boolean item_ignore_saved_actions;
// deed_
public int deed_type;
public int deed_furniture_id;
public int deed_target_id;
public int deed_employment;
public int deed_start_rank;
public int deed_name_lookup;
public boolean deed_indoors;
public boolean deed_is_fortress;
public float deed_namelookup_val;
public boolean deed_custom_city;
public int deed_structure_id;
@Override
public int getTemplateId() {
return template_id;
}
@Override
public String getObjName() {
return obj_name;
}
@Override
public boolean getObjPickable() {
return obj_pickable;
}
@Override
public float getObjGravity() {
return obj_gravity;
}
@Override
public float getObjCullDistance() {
return obj_cull_distance;
}
@Override
public Vector3fImmutable getObjScale() {
return obj_scale;
}
@Override
public int getObjRenderObject() {
return obj_render_object;
}
@Override
public boolean getObjDoubleFusion() {
return obj_double_fusion;
}
@Override
public Vector3fImmutable getObjForwardVector() {
return obj_forward_vector;
}
@Override
public String getObjTrackingName() {
return obj_tracking_name;
}
@Override
public float getObjMaxTrackingDistance() {
return obj_max_tracking_distance;
}
@Override
public int getObjIcon() {
return obj_icon;
}
@Override
public float getObjGravityF() {
return obj_gravity_f;
}
@Override
public LinkedHashMap<String, Integer> getObjSoundEvents() {
return obj_sound_events;
}
@Override
public JSONArray getObjArcHardpointList() {
return obj_arc_hardpoint_list;
}
@Override
public HashMap<String, String> getObjSparseData() {
return obj_sparse_data;
}
@Override
public int getObjRenderObjectLowDetail() {
return obj_render_object_low_detail;
}
@Override
public Vector3fImmutable getObjDefaultAlignment() {
return obj_default_alignment;
}
@Override
public String getObjSoundTable() {
return obj_sound_table;
}
@Override
public float getCombatHealthCurrent() {
return combat_health_current;
}
@Override
public float getCombatHealthFull() {
return combat_health_full;
}
@Override
public EnumMap<mbEnums.DamageType, Float> getCombatAttackResist() {
return combat_attack_resist;
}
@Override
public JSONArray getCombatPowers() {
return combat_powers;
}
@Override
public mbEnums.ItemType getItemType() {
return item_type;
}
@Override
public int getItemEqSlotsValue() {
return item_eq_slots_value;
}
@Override
public boolean getItemEqSlotsType() {
return item_eq_slots_type;
}
@Override
public EnumSet<mbEnums.EquipSlotType> getItemEqSlotsOr() {
return item_eq_slots_or;
}
@Override
public EnumSet<mbEnums.EquipSlotType> getItemEqSlotsAnd() {
return item_eq_slots_and;
}
@Override
public boolean getItemTakeable() {
return item_takeable;
}
@Override
public int getItemValue() {
return item_value;
}
@Override
public int getItemWt() {
return item_wt;
}
@Override
public float getItemPassiveDefenseMod() {
return item_passive_defense_mod;
}
@Override
public String getItemBaseName() {
return item_base_name;
}
@Override
public String getItemDsc() {
return item_dsc;
}
@Override
public int getItemRenderObjectFemale() {
return item_render_object_female;
}
@Override
public float getItemHealthFull() {
return item_health_full;
}
@Override
public String getItemSkillUsed() {
return item_skill_used;
}
@Override
public String getItemSkillMasteryUsed() {
return item_skill_mastery_used;
}
@Override
public int getItemParryAnimId() {
return item_parry_anim_id;
}
@Override
public EnumMap<mbEnums.ShrineType, Integer> getItemOfferingInfo() {
return item_offering_info;
}
@Override
public EnumSet<mbEnums.ItemFlags> getItemFlags() {
return item_flags;
}
@Override
public EnumSet<mbEnums.ItemUseFlags> getItemUseFlags() {
return item_use_flags;
}
@Override
public int getItemPostItemId() {
return item_post_item_id;
}
@Override
public int getItemInitialCharges() {
return item_initial_charges;
}
@Override
public int getItemBookArcana() {
return item_book_arcana;
}
@Override
public LinkedHashMap<String, Integer> getItemSkillReq() {
return item_skill_req;
}
@Override
public boolean getItemRaceReqRestrict() {
return item_race_req_restrict;
}
@Override
public EnumSet<mbEnums.MonsterType> getItemRaceReq() {
return item_race_req;
}
@Override
public boolean getItemClassReqRestrict() {
return item_class_req_restrict;
}
@Override
public EnumSet<mbEnums.ClassType> getItemClassReq() {
return item_class_req;
}
@Override
public boolean getItemDiscReqRestrict() {
return item_disc_req_restrict;
}
@Override
public EnumSet<mbEnums.DisciplineType> getItemDiscReq() {
return item_disc_req;
}
@Override
public EnumMap<mbEnums.AttributeType, Integer> getItemAttrReq() {
return item_attr_req;
}
@Override
public int getItemLevelReq() {
return item_level_req;
}
@Override
public int getItemRankReq() {
return item_rank_req;
}
@Override
public mbEnums.SexType getItemSexReq() {
return item_sex_req;
}
@Override
public ArrayList<UserPowerAction> getItemUserPowerAction() {
return item_user_power_action;
}
@Override
public ArrayList<PowerGrant> getItemPowerGrant() {
return item_power_grant;
}
@Override
public LinkedHashMap<String, ArrayList<int[]>> getItemPowerAction() {
return item_power_action;
}
@Override
public boolean getItemSheathable() {
return item_sheathable;
}
@Override
public boolean getItemHasStub() {
return item_has_stub;
}
@Override
public EnumMap<mbEnums.ShrineType, Integer> getItemOfferingAdjustments() {
return item_offering_adjustments;
}
@Override
public EnumMap<mbEnums.ResourceType, Integer> getItemResourceCosts() {
return item_resource_costs;
}
@Override
public int getItemBaneRank() {
return item_bane_rank;
}
@Override
public boolean getItemIgnoreSavedActions() {
return item_ignore_saved_actions;
}
}
@@ -1,501 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.objects;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
// Item template as defined by the client's cache data
// (MBDATA/data/COBJECTS/ITEM). Field names match the JSON keys.
// Field layout follows ArcItemTemplate_Load (sb.exe 0x4AABD0).
//
// Values are kept as the client defines them: no req/res splitting,
// no defaults substituted. Strings with a matching enum in mbEnums
// are stored as that enum; everything else stays a String.
// Read only once loaded.
public class ItemTemplate implements CObjectTemplate {
public static HashMap<Integer, ItemTemplate> _items = new HashMap<>();
// Legacy templates zero-filled the weapon block on non-weapons; held shields and the like rely on it.
private static final Weapon NO_WEAPON = new Weapon();
public int template_id;
// obj_
public String obj_name;
public boolean obj_pickable;
public float obj_gravity;
public float obj_cull_distance;
public Vector3fImmutable obj_scale;
public int obj_render_object;
public boolean obj_double_fusion;
public Vector3fImmutable obj_forward_vector;
public String obj_tracking_name;
public float obj_max_tracking_distance;
public int obj_icon;
public float obj_gravity_f;
public final LinkedHashMap<String, Integer> obj_sound_events = new LinkedHashMap<>();
public JSONArray obj_arc_hardpoint_list;
public final HashMap<String, String> obj_sparse_data = new HashMap<>();
public int obj_render_object_low_detail;
public Vector3fImmutable obj_default_alignment;
public String obj_sound_table;
// combat_
public float combat_health_current;
public float combat_health_full;
public final EnumMap<mbEnums.DamageType, Float> combat_attack_resist = new EnumMap<>(mbEnums.DamageType.class);
public JSONArray combat_powers;
// item_
public mbEnums.ItemType item_type;
// Index into the client's equip slot names; the leading slot of EQSLOTAND.
public int item_eq_slots_value;
// true: any one of item_eq_slots_or; false: all of item_eq_slots_and (sb.exe 0x4AC430).
public boolean item_eq_slots_type;
public final EnumSet<mbEnums.EquipSlotType> item_eq_slots_or = EnumSet.noneOf(mbEnums.EquipSlotType.class);
public final EnumSet<mbEnums.EquipSlotType> item_eq_slots_and = EnumSet.noneOf(mbEnums.EquipSlotType.class);
public boolean item_takeable;
public int item_value;
public int item_wt;
public float item_passive_defense_mod;
public String item_base_name;
public String item_dsc;
public int item_render_object_female;
public float item_health_full;
public String item_skill_used;
public String item_skill_mastery_used;
public int item_parry_anim_id;
public final EnumMap<mbEnums.ShrineType, Integer> item_offering_info = new EnumMap<>(mbEnums.ShrineType.class);
// WEAPON only; null otherwise.
public Weapon item_weapon;
public mbEnums.AttributeType item_primary_attr;
public mbEnums.AttributeType item_secondary_attr;
// ARMOR only.
public float item_bulk_factor;
public int item_defense_rating;
public final EnumSet<mbEnums.ItemFlags> item_flags = EnumSet.noneOf(mbEnums.ItemFlags.class);
public final EnumSet<mbEnums.ItemUseFlags> item_use_flags = EnumSet.noneOf(mbEnums.ItemUseFlags.class);
public int item_post_item_id;
public int item_initial_charges;
// Read as an unsigned value, possibly a hash; 0 in every ITEM file.
public int item_book_arcana;
public final LinkedHashMap<String, Integer> item_skill_req = new LinkedHashMap<>();
// For race, class and disc: restrict true means the list is excluded
// (RACERESTRICT), false means it is required (RACEREQ).
public boolean item_race_req_restrict;
public final EnumSet<mbEnums.MonsterType> item_race_req = EnumSet.noneOf(mbEnums.MonsterType.class);
public boolean item_class_req_restrict;
public final EnumSet<mbEnums.ClassType> item_class_req = EnumSet.noneOf(mbEnums.ClassType.class);
public boolean item_disc_req_restrict;
public final EnumSet<mbEnums.DisciplineType> item_disc_req = EnumSet.noneOf(mbEnums.DisciplineType.class);
public final EnumMap<mbEnums.AttributeType, Integer> item_attr_req = new EnumMap<>(mbEnums.AttributeType.class);
public int item_level_req;
public int item_rank_req;
public mbEnums.SexType item_sex_req;
public final ArrayList<UserPowerAction> item_user_power_action = new ArrayList<>();
public final ArrayList<PowerGrant> item_power_grant = new ArrayList<>();
public final LinkedHashMap<String, ArrayList<int[]>> item_power_action = new LinkedHashMap<>();
// Sheath fields are only present when item_sheathable is true.
public boolean item_sheathable;
public mbEnums.SheathSlot item_sheath_slot;
public Vector3fImmutable item_sheath_offset;
public Vector3fImmutable item_sheath_rotation;
// The JSON holds false, or [flag, id] when the stub is present (ArcItemStubHolder2, sb.exe 0x4A8D40).
// Meaning of the flag is not known.
public boolean item_has_stub;
public boolean item_stub_flag;
public int item_stub_id;
public final EnumMap<mbEnums.ShrineType, Integer> item_offering_adjustments = new EnumMap<>(mbEnums.ShrineType.class);
public final EnumMap<mbEnums.ResourceType, Integer> item_resource_costs = new EnumMap<>(mbEnums.ResourceType.class);
public int item_bane_rank;
public boolean item_ignore_saved_actions;
@Override
public int getTemplateId() {
return template_id;
}
@Override
public String getObjName() {
return obj_name;
}
@Override
public boolean getObjPickable() {
return obj_pickable;
}
@Override
public float getObjGravity() {
return obj_gravity;
}
@Override
public float getObjCullDistance() {
return obj_cull_distance;
}
@Override
public Vector3fImmutable getObjScale() {
return obj_scale;
}
@Override
public int getObjRenderObject() {
return obj_render_object;
}
@Override
public boolean getObjDoubleFusion() {
return obj_double_fusion;
}
@Override
public Vector3fImmutable getObjForwardVector() {
return obj_forward_vector;
}
@Override
public String getObjTrackingName() {
return obj_tracking_name;
}
@Override
public float getObjMaxTrackingDistance() {
return obj_max_tracking_distance;
}
@Override
public int getObjIcon() {
return obj_icon;
}
@Override
public float getObjGravityF() {
return obj_gravity_f;
}
@Override
public LinkedHashMap<String, Integer> getObjSoundEvents() {
return obj_sound_events;
}
@Override
public JSONArray getObjArcHardpointList() {
return obj_arc_hardpoint_list;
}
@Override
public HashMap<String, String> getObjSparseData() {
return obj_sparse_data;
}
@Override
public int getObjRenderObjectLowDetail() {
return obj_render_object_low_detail;
}
@Override
public Vector3fImmutable getObjDefaultAlignment() {
return obj_default_alignment;
}
@Override
public String getObjSoundTable() {
return obj_sound_table;
}
@Override
public float getCombatHealthCurrent() {
return combat_health_current;
}
@Override
public float getCombatHealthFull() {
return combat_health_full;
}
@Override
public EnumMap<mbEnums.DamageType, Float> getCombatAttackResist() {
return combat_attack_resist;
}
@Override
public JSONArray getCombatPowers() {
return combat_powers;
}
@Override
public mbEnums.ItemType getItemType() {
return item_type;
}
@Override
public int getItemEqSlotsValue() {
return item_eq_slots_value;
}
@Override
public boolean getItemEqSlotsType() {
return item_eq_slots_type;
}
@Override
public EnumSet<mbEnums.EquipSlotType> getItemEqSlotsOr() {
return item_eq_slots_or;
}
@Override
public EnumSet<mbEnums.EquipSlotType> getItemEqSlotsAnd() {
return item_eq_slots_and;
}
@Override
public boolean getItemTakeable() {
return item_takeable;
}
@Override
public int getItemValue() {
return item_value;
}
@Override
public int getItemWt() {
return item_wt;
}
@Override
public float getItemPassiveDefenseMod() {
return item_passive_defense_mod;
}
@Override
public String getItemBaseName() {
return item_base_name;
}
@Override
public String getItemDsc() {
return item_dsc;
}
@Override
public int getItemRenderObjectFemale() {
return item_render_object_female;
}
@Override
public float getItemHealthFull() {
return item_health_full;
}
@Override
public String getItemSkillUsed() {
return item_skill_used;
}
@Override
public String getItemSkillMasteryUsed() {
return item_skill_mastery_used;
}
@Override
public int getItemParryAnimId() {
return item_parry_anim_id;
}
@Override
public EnumMap<mbEnums.ShrineType, Integer> getItemOfferingInfo() {
return item_offering_info;
}
@Override
public EnumSet<mbEnums.ItemFlags> getItemFlags() {
return item_flags;
}
@Override
public EnumSet<mbEnums.ItemUseFlags> getItemUseFlags() {
return item_use_flags;
}
@Override
public int getItemPostItemId() {
return item_post_item_id;
}
@Override
public int getItemInitialCharges() {
return item_initial_charges;
}
@Override
public int getItemBookArcana() {
return item_book_arcana;
}
@Override
public LinkedHashMap<String, Integer> getItemSkillReq() {
return item_skill_req;
}
@Override
public boolean getItemRaceReqRestrict() {
return item_race_req_restrict;
}
@Override
public EnumSet<mbEnums.MonsterType> getItemRaceReq() {
return item_race_req;
}
@Override
public boolean getItemClassReqRestrict() {
return item_class_req_restrict;
}
@Override
public EnumSet<mbEnums.ClassType> getItemClassReq() {
return item_class_req;
}
@Override
public boolean getItemDiscReqRestrict() {
return item_disc_req_restrict;
}
@Override
public EnumSet<mbEnums.DisciplineType> getItemDiscReq() {
return item_disc_req;
}
@Override
public EnumMap<mbEnums.AttributeType, Integer> getItemAttrReq() {
return item_attr_req;
}
@Override
public int getItemLevelReq() {
return item_level_req;
}
@Override
public int getItemRankReq() {
return item_rank_req;
}
@Override
public mbEnums.SexType getItemSexReq() {
return item_sex_req;
}
@Override
public ArrayList<UserPowerAction> getItemUserPowerAction() {
return item_user_power_action;
}
@Override
public ArrayList<PowerGrant> getItemPowerGrant() {
return item_power_grant;
}
@Override
public LinkedHashMap<String, ArrayList<int[]>> getItemPowerAction() {
return item_power_action;
}
@Override
public boolean getItemSheathable() {
return item_sheathable;
}
@Override
public boolean getItemHasStub() {
return item_has_stub;
}
@Override
public EnumMap<mbEnums.ShrineType, Integer> getItemOfferingAdjustments() {
return item_offering_adjustments;
}
@Override
public EnumMap<mbEnums.ResourceType, Integer> getItemResourceCosts() {
return item_resource_costs;
}
@Override
public int getItemBaneRank() {
return item_bane_rank;
}
@Override
public boolean getItemIgnoreSavedActions() {
return item_ignore_saved_actions;
}
public static Weapon getWeapon(int templateID) {
ItemTemplate template = _items.get(templateID);
if (template == null || template.item_weapon == null)
return NO_WEAPON;
return template.item_weapon;
}
// item_weapon (ArcAttackInfo_LoadWeapon, sb.exe 0x61FA60).
public static class Weapon {
public float weapon_wepspeed;
public float weapon_max_range;
public int weapon_projectile_id;
public float weapon_projectile_speed;
public int weapon_combat_idle_anim;
public final ArrayList<Damage> weapon_damage = new ArrayList<>();
// [animation, duration] pairs in file order; names from the old static_item_templates export, not the client.
public final ArrayList<int[]> weapon_attack_anim_right = new ArrayList<>();
public final ArrayList<int[]> weapon_attack_anim_left = new ArrayList<>();
}
// One entry of weapon_damage.
public static class Damage {
public mbEnums.DamageType damage_type;
public int damage_min;
public int damage_max;
}
}
@@ -1,27 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.objects;
import org.json.JSONArray;
import java.util.LinkedHashMap;
// One entry of item_power_grant.
// The granted lists are [key, value] pairs, unsigned key and signed value (sb.exe 0x6D7640).
// power_monster_types is empty in every DEED and RUNE file, so it is kept as raw JSON.
public class PowerGrant {
public String power_type;
public int power_value;
public final LinkedHashMap<String, Integer> power_granted_attrs = new LinkedHashMap<>();
public final LinkedHashMap<String, Integer> power_granted_skills = new LinkedHashMap<>();
public final LinkedHashMap<String, Integer> power_granted_powers = new LinkedHashMap<>();
public JSONArray power_monster_types;
}
@@ -1,550 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.objects;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
// Rune template as defined by the client's cache data
// (MBDATA/data/COBJECTS/RUNE). Field names match the JSON keys.
//
// Covers every rune the client knows about: player races, classes,
// disciplines, talents and mob/pet/npc runes alike.
//
// Values are kept as the client defines them: no req/res splitting,
// no defaults substituted. Strings with a matching enum in mbEnums
// are stored as that enum; everything else stays a String.
//
// Read only once loaded.
public class RuneTemplate implements CObjectTemplate {
public static HashMap<Integer, RuneTemplate> _runes = new HashMap<>();
public int template_id;
// obj_
public String obj_name;
public boolean obj_pickable;
public float obj_gravity;
public float obj_cull_distance;
public Vector3fImmutable obj_scale;
public int obj_render_object;
public boolean obj_double_fusion;
public Vector3fImmutable obj_forward_vector;
public String obj_tracking_name;
public float obj_max_tracking_distance;
public int obj_icon;
public float obj_gravity_f;
public final LinkedHashMap<String, Integer> obj_sound_events = new LinkedHashMap<>();
public JSONArray obj_arc_hardpoint_list;
public final HashMap<String, String> obj_sparse_data = new HashMap<>();
public int obj_render_object_low_detail;
public Vector3fImmutable obj_default_alignment;
public String obj_sound_table;
// combat_
public float combat_health_current;
public float combat_health_full;
public final EnumMap<mbEnums.DamageType, Float> combat_attack_resist = new EnumMap<>(mbEnums.DamageType.class);
public JSONArray combat_powers;
// item_
public mbEnums.ItemType item_type;
public int item_eq_slots_value;
public boolean item_eq_slots_type;
public final EnumSet<mbEnums.EquipSlotType> item_eq_slots_or = EnumSet.noneOf(mbEnums.EquipSlotType.class);
public final EnumSet<mbEnums.EquipSlotType> item_eq_slots_and = EnumSet.noneOf(mbEnums.EquipSlotType.class);
public boolean item_takeable;
public int item_value;
public int item_wt;
public float item_passive_defense_mod;
public String item_base_name;
public String item_dsc;
public int item_render_object_female;
public float item_health_full;
public String item_skill_used;
public String item_skill_mastery_used;
public int item_parry_anim_id;
public final EnumMap<mbEnums.ShrineType, Integer> item_offering_info = new EnumMap<>(mbEnums.ShrineType.class);
public final EnumSet<mbEnums.ItemFlags> item_flags = EnumSet.noneOf(mbEnums.ItemFlags.class);
public final EnumSet<mbEnums.ItemUseFlags> item_use_flags = EnumSet.noneOf(mbEnums.ItemUseFlags.class);
public int item_post_item_id;
public int item_initial_charges;
public int item_book_arcana;
public final LinkedHashMap<String, Integer> item_skill_req = new LinkedHashMap<>();
public boolean item_race_req_restrict;
public final EnumSet<mbEnums.MonsterType> item_race_req = EnumSet.noneOf(mbEnums.MonsterType.class);
public boolean item_class_req_restrict;
public final EnumSet<mbEnums.ClassType> item_class_req = EnumSet.noneOf(mbEnums.ClassType.class);
public boolean item_disc_req_restrict;
public final EnumSet<mbEnums.DisciplineType> item_disc_req = EnumSet.noneOf(mbEnums.DisciplineType.class);
public final EnumMap<mbEnums.AttributeType, Integer> item_attr_req = new EnumMap<>(mbEnums.AttributeType.class);
public int item_level_req;
public int item_rank_req;
public mbEnums.SexType item_sex_req;
public final ArrayList<UserPowerAction> item_user_power_action = new ArrayList<>();
public final ArrayList<PowerGrant> item_power_grant = new ArrayList<>();
public final LinkedHashMap<String, ArrayList<int[]>> item_power_action = new LinkedHashMap<>();
public boolean item_sheathable;
public boolean item_has_stub;
public final EnumMap<mbEnums.ShrineType, Integer> item_offering_adjustments = new EnumMap<>(mbEnums.ShrineType.class);
public final EnumMap<mbEnums.ResourceType, Integer> item_resource_costs = new EnumMap<>(mbEnums.ResourceType.class);
public int item_bane_rank;
public boolean item_ignore_saved_actions;
// rune_
public mbEnums.RuneType rune_type;
public String rune_sub_type;
// A handful of runes carry a number instead of a name in rune_sub_type.
// These look like string hashes the cache converter could not resolve.
// Stored here (wrapped to int) with rune_sub_type left empty.
public int rune_sub_type_hash;
public boolean rune_is_standard_character_creation;
public int rune_creation_cost;
public int rune_rank;
public int rune_pracs_per_level;
public float rune_exp_req_to_level;
public mbEnums.SexType rune_sex;
public int rune_class_icon;
public int rune_health;
public int rune_mana;
public int rune_stamina;
public float rune_min_damage;
public float rune_max_damage;
public int rune_attack;
public int rune_defense;
public int rune_level;
public final EnumMap<mbEnums.MovementType, Float> rune_speed = new EnumMap<>(mbEnums.MovementType.class);
public int rune_group_type;
public boolean rune_group_is_faction;
public boolean rune_group_is_guild;
public String rune_dsc;
public String rune_fx_txt;
// Bit vectors. The old static_item_templates export decoded these as MobBehaviourType.
public long rune_group_tactics;
public long rune_group_role_set;
public final EnumSet<mbEnums.MonsterType> rune_enemy_monster_types = EnumSet.noneOf(mbEnums.MonsterType.class);
public final ArrayList<Integer> rune_groupee_monster_types = new ArrayList<>();
public final ArrayList<Integer> rune_helper_monster_types = new ArrayList<>();
public final EnumSet<mbEnums.MonsterType> rune_not_enemy_monster_types = EnumSet.noneOf(mbEnums.MonsterType.class);
// Empty in every RUNE file; shape unknown.
public JSONArray rune_enemy_gender;
public final ArrayList<SkillGrant> rune_skill_grant = new ArrayList<>();
// skill_type -> list of [value, value] pairs, in file order.
public final LinkedHashMap<String, ArrayList<int[]>> rune_skill_adj = new LinkedHashMap<>();
public final EnumMap<mbEnums.AttributeType, Integer> rune_attr_adj = new EnumMap<>(mbEnums.AttributeType.class);
public final EnumMap<mbEnums.AttributeType, Integer> rune_max_attr_adj = new EnumMap<>(mbEnums.AttributeType.class);
// One float[10] per natural attack. Same "attack info" struct as a weapon
// (see MBDATA/docs/client-map.md): [0] attack speed, [1] range, [2] unknown,
// [3] equip slot (1 = RHELD, 2 = LHELD), [4] projectile template id,
// [5] projectile speed, [6] swing anim, [7] damage type, [8] min damage,
// [9] max damage
public final ArrayList<float[]> rune_naturalattacks = new ArrayList<>();
// Empty in every RUNE file; shape unknown.
public JSONArray rune_enchantment_type;
public final ArrayList<InventoryEntry> rune_inventory_contents = new ArrayList<>();
public boolean rune_renderable;
// The following fields are only present when the rune is renderable
// (missing from 315 of 2695 files). They keep their defaults otherwise.
public Vector3fImmutable rune_scale_factor;
public int rune_skeleton;
public boolean rune_slope_hugger;
public boolean rune_can_fly;
public int rune_death_effect;
public int rune_tombstone_id;
public final ArrayList<BodyPart> rune_body_parts = new ArrayList<>();
public final ArrayList<Integer> rune_hair = new ArrayList<>();
public final ArrayList<Integer> rune_beard = new ArrayList<>();
public int rune_natural_power_attack;
public final HashMap<String, String> rune_sparse_data = new HashMap<>();
@Override
public int getTemplateId() {
return template_id;
}
@Override
public String getObjName() {
return obj_name;
}
@Override
public boolean getObjPickable() {
return obj_pickable;
}
@Override
public float getObjGravity() {
return obj_gravity;
}
@Override
public float getObjCullDistance() {
return obj_cull_distance;
}
@Override
public Vector3fImmutable getObjScale() {
return obj_scale;
}
@Override
public int getObjRenderObject() {
return obj_render_object;
}
@Override
public boolean getObjDoubleFusion() {
return obj_double_fusion;
}
@Override
public Vector3fImmutable getObjForwardVector() {
return obj_forward_vector;
}
@Override
public String getObjTrackingName() {
return obj_tracking_name;
}
@Override
public float getObjMaxTrackingDistance() {
return obj_max_tracking_distance;
}
@Override
public int getObjIcon() {
return obj_icon;
}
@Override
public float getObjGravityF() {
return obj_gravity_f;
}
@Override
public LinkedHashMap<String, Integer> getObjSoundEvents() {
return obj_sound_events;
}
@Override
public JSONArray getObjArcHardpointList() {
return obj_arc_hardpoint_list;
}
@Override
public HashMap<String, String> getObjSparseData() {
return obj_sparse_data;
}
@Override
public int getObjRenderObjectLowDetail() {
return obj_render_object_low_detail;
}
@Override
public Vector3fImmutable getObjDefaultAlignment() {
return obj_default_alignment;
}
@Override
public String getObjSoundTable() {
return obj_sound_table;
}
@Override
public float getCombatHealthCurrent() {
return combat_health_current;
}
@Override
public float getCombatHealthFull() {
return combat_health_full;
}
@Override
public EnumMap<mbEnums.DamageType, Float> getCombatAttackResist() {
return combat_attack_resist;
}
@Override
public JSONArray getCombatPowers() {
return combat_powers;
}
@Override
public mbEnums.ItemType getItemType() {
return item_type;
}
@Override
public int getItemEqSlotsValue() {
return item_eq_slots_value;
}
@Override
public boolean getItemEqSlotsType() {
return item_eq_slots_type;
}
@Override
public EnumSet<mbEnums.EquipSlotType> getItemEqSlotsOr() {
return item_eq_slots_or;
}
@Override
public EnumSet<mbEnums.EquipSlotType> getItemEqSlotsAnd() {
return item_eq_slots_and;
}
@Override
public boolean getItemTakeable() {
return item_takeable;
}
@Override
public int getItemValue() {
return item_value;
}
@Override
public int getItemWt() {
return item_wt;
}
@Override
public float getItemPassiveDefenseMod() {
return item_passive_defense_mod;
}
@Override
public String getItemBaseName() {
return item_base_name;
}
@Override
public String getItemDsc() {
return item_dsc;
}
@Override
public int getItemRenderObjectFemale() {
return item_render_object_female;
}
@Override
public float getItemHealthFull() {
return item_health_full;
}
@Override
public String getItemSkillUsed() {
return item_skill_used;
}
@Override
public String getItemSkillMasteryUsed() {
return item_skill_mastery_used;
}
@Override
public int getItemParryAnimId() {
return item_parry_anim_id;
}
@Override
public EnumMap<mbEnums.ShrineType, Integer> getItemOfferingInfo() {
return item_offering_info;
}
@Override
public EnumSet<mbEnums.ItemFlags> getItemFlags() {
return item_flags;
}
@Override
public EnumSet<mbEnums.ItemUseFlags> getItemUseFlags() {
return item_use_flags;
}
@Override
public int getItemPostItemId() {
return item_post_item_id;
}
@Override
public int getItemInitialCharges() {
return item_initial_charges;
}
@Override
public int getItemBookArcana() {
return item_book_arcana;
}
@Override
public LinkedHashMap<String, Integer> getItemSkillReq() {
return item_skill_req;
}
@Override
public boolean getItemRaceReqRestrict() {
return item_race_req_restrict;
}
@Override
public EnumSet<mbEnums.MonsterType> getItemRaceReq() {
return item_race_req;
}
@Override
public boolean getItemClassReqRestrict() {
return item_class_req_restrict;
}
@Override
public EnumSet<mbEnums.ClassType> getItemClassReq() {
return item_class_req;
}
@Override
public boolean getItemDiscReqRestrict() {
return item_disc_req_restrict;
}
@Override
public EnumSet<mbEnums.DisciplineType> getItemDiscReq() {
return item_disc_req;
}
@Override
public EnumMap<mbEnums.AttributeType, Integer> getItemAttrReq() {
return item_attr_req;
}
@Override
public int getItemLevelReq() {
return item_level_req;
}
@Override
public int getItemRankReq() {
return item_rank_req;
}
@Override
public mbEnums.SexType getItemSexReq() {
return item_sex_req;
}
@Override
public ArrayList<UserPowerAction> getItemUserPowerAction() {
return item_user_power_action;
}
@Override
public ArrayList<PowerGrant> getItemPowerGrant() {
return item_power_grant;
}
@Override
public LinkedHashMap<String, ArrayList<int[]>> getItemPowerAction() {
return item_power_action;
}
@Override
public boolean getItemSheathable() {
return item_sheathable;
}
@Override
public boolean getItemHasStub() {
return item_has_stub;
}
@Override
public EnumMap<mbEnums.ShrineType, Integer> getItemOfferingAdjustments() {
return item_offering_adjustments;
}
@Override
public EnumMap<mbEnums.ResourceType, Integer> getItemResourceCosts() {
return item_resource_costs;
}
@Override
public int getItemBaneRank() {
return item_bane_rank;
}
@Override
public boolean getItemIgnoreSavedActions() {
return item_ignore_saved_actions;
}
// One entry of rune_skill_grant; same layout as PowerGrant.
// skill_monster_types is empty in every RUNE file, so it is kept as raw JSON.
public static class SkillGrant {
public String skill_type;
public int skill_value;
public final LinkedHashMap<String, Integer> skill_granted_attrs = new LinkedHashMap<>();
public final LinkedHashMap<String, Integer> skill_granted_skills = new LinkedHashMap<>();
public final LinkedHashMap<String, Integer> skill_granted_powers = new LinkedHashMap<>();
public JSONArray skill_monster_types;
}
// One entry of rune_body_parts.
public static class BodyPart {
public int body_part_render;
public Vector3fImmutable body_part_position;
}
// One entry of rune_inventory_contents.
// type is GOLD or BOOTYTABLE.
// GOLD carries "gold": three floats (meaning not yet confirmed).
// BOOTYTABLE carries "table": two numbers (meaning not yet confirmed).
public static class InventoryEntry {
public String type;
public float[] values;
}
}
@@ -1,24 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.parsers.objects;
// One entry of item_user_power_action.
// The same power can appear more than once on a single template,
// so these are kept in a list rather than a map keyed by power.
public class UserPowerAction {
public String power;
public int[] arguments;
public UserPowerAction(String power, int[] arguments) {
this.power = power;
this.arguments = arguments;
}
}
-11
View File
@@ -1,11 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
// Parsers for the client's .wpak configuration files (powers, effects, etc).
package engine.parsers.wpak;
@@ -246,9 +246,7 @@ public class ApplyEffectPowerAction extends AbstractPowerAction {
if (this.effectID.equals("TAUNT")) {
// siege engines only switch targets on damage, see AbstractCharacter.modifyHealth
if (awo != null && awo.getObjectType() == GameObjectType.Mob && !((Mob) awo).isSiege()) {
if (awo != null && awo.getObjectType() == GameObjectType.Mob) {
((Mob) awo).setCombatTarget(source);
ChatSystemMsg msg = ChatManager.CombatInfo(source, awo);
DispatchManager.sendToAllInRange(source, msg);
Loaded 100 of 105 files, more files were not shown because too many files have changed in this diff. Show more