Files
lakebane/src/engine/objects/Zone.java
T

319 lines
9.5 KiB
Java
Raw Normal View History

2022-04-30 09:41:17 -04:00
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.objects;
import engine.Enum;
2023-10-08 09:18:43 -04:00
import engine.InterestManagement.Terrain;
2022-04-30 09:41:17 -04:00
import engine.db.archive.DataWarehouse;
import engine.gameManager.ZoneManager;
import engine.math.Bounds;
import engine.math.Vector2f;
import engine.math.Vector3fImmutable;
import engine.net.ByteBufferWriter;
import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
2023-10-18 08:03:47 -04:00
public class Zone extends AbstractWorldObject {
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
public final Set<Building> zoneBuildingSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
public final Set<NPC> zoneNPCSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
public final Set<Mob> zoneMobSet = Collections.newSetFromMap(new ConcurrentHashMap<>());
2023-10-20 17:22:57 -04:00
2023-10-20 17:01:42 -04:00
public ZoneTemplate template;
2023-09-20 15:53:41 -04:00
public final int playerCityUUID;
2023-09-20 15:43:01 -04:00
public final String zoneName;
2024-01-04 12:43:30 -05:00
public float major_radius;
public float minor_radius;
2023-09-20 15:53:41 -04:00
public final float xOffset;
public final float zOffset;
public final float yOffset;
public final int templateID;
2023-09-20 16:05:57 -04:00
public final byte peace_zone;
2023-09-20 16:07:50 -04:00
public final String icon1;
public final String icon2;
public final String icon3;
2023-07-15 09:23:48 -04:00
public float absX = 0.0f;
public float absY = 0.0f;
public float absZ = 0.0f;
2023-09-20 16:07:50 -04:00
public int min_level;
public int max_level;
2023-10-23 00:43:23 -04:00
public boolean wasHotzonw = false;
2023-10-18 09:08:41 -04:00
public ArrayList<Zone> nodes = new ArrayList<>();
2023-09-20 15:43:01 -04:00
public int parentZoneID;
public Zone parent = null;
public Bounds bounds;
public boolean isNPCCity = false;
2023-09-20 16:05:57 -04:00
public boolean guild_zone;
2023-09-20 15:43:01 -04:00
public String hash;
2023-10-12 06:19:22 -04:00
public float global_height = 0;
2023-09-20 16:24:00 -04:00
public float sea_level;
2023-09-17 07:42:46 -04:00
2023-10-08 09:49:49 -04:00
public Terrain terrain = null;
2023-07-15 09:23:48 -04:00
/**
* ResultSet Constructor
*/
public Zone(ResultSet rs) throws SQLException {
2023-10-08 23:05:41 -04:00
super(rs);
2023-07-15 09:23:48 -04:00
2023-10-18 08:42:40 -04:00
this.parentZoneID = rs.getInt("parent");
2023-10-20 17:22:57 -04:00
this.templateID = rs.getInt("template");
2023-10-18 08:42:40 -04:00
this.zoneName = rs.getString("zone_name");
2023-10-20 17:22:57 -04:00
this.peace_zone = rs.getByte("peace_zone");
2023-10-18 08:42:40 -04:00
this.xOffset = rs.getFloat("xOffset");
this.zOffset = rs.getFloat("zOffset");
this.yOffset = rs.getFloat("yOffset");
2023-10-20 17:22:57 -04:00
this.playerCityUUID = rs.getInt("playerCityUUID");
this.guild_zone = this.playerCityUUID != 0;
2023-10-18 08:42:40 -04:00
this.icon1 = rs.getString("icon1");
this.icon2 = rs.getString("icon2");
this.icon3 = rs.getString("icon3");
2023-10-20 17:22:57 -04:00
2023-10-18 08:42:40 -04:00
this.min_level = rs.getInt("min_level");
this.max_level = rs.getInt("max_level");
2023-07-15 09:23:48 -04:00
// If zone doesn't yet hava a hash then write it back to the zone table
if (hash == null)
setHash();
}
public static void serializeForClientMsg(Zone zone, ByteBufferWriter writer) {
if (zone.templateID == 0 && zone.playerCityUUID == 0)
2023-07-15 09:23:48 -04:00
Logger.warn("Warning! WorldServerMap with ID " + zone.getObjectUUID() + " has a loadnum of 0 (player city) and no city linked. This will probably crash the client!");
// Player City Terraform values serialized here.
2023-09-20 15:53:41 -04:00
if (zone.playerCityUUID > 0) {
2023-07-15 09:23:48 -04:00
writer.put((byte) 1); // Player City - True
2023-09-17 12:23:06 -04:00
writer.putFloat(Enum.CityBoundsType.ZONE.halfExtents);
writer.putFloat(Enum.CityBoundsType.ZONE.halfExtents);
2023-07-15 09:23:48 -04:00
} else
writer.put((byte) 0); // Player City - False
2023-09-20 15:53:41 -04:00
writer.putFloat(zone.xOffset);
writer.putFloat(zone.zOffset);
writer.putFloat(zone.yOffset);
2023-07-15 09:23:48 -04:00
writer.putInt(0);
writer.putInt(0);
writer.putInt(zone.templateID);
2023-07-15 09:23:48 -04:00
2023-09-20 15:53:41 -04:00
if (zone.playerCityUUID > 0) {
City k = City.getCity(zone.playerCityUUID);
2023-07-15 09:23:48 -04:00
if (k != null) {
writer.putInt(k.getObjectType().ordinal());
writer.putInt(k.getObjectUUID());
} else
writer.putLong(0x0);
} else {
writer.putInt(zone.getObjectType().ordinal());
writer.putInt(zone.getObjectUUID());
}
writer.putInt(zone.nodes.size());
2023-09-20 15:53:41 -04:00
City city = City.getCity(zone.playerCityUUID);
2023-07-15 09:23:48 -04:00
if (city != null)
writer.putString(city.getCityName());
else
writer.putString(zone.zoneName);
2023-09-20 16:05:57 -04:00
writer.put(zone.peace_zone);
2023-09-20 16:07:50 -04:00
writer.putString(zone.icon1);
writer.putString(zone.icon2);
writer.putString(zone.icon3);
2023-07-15 09:23:48 -04:00
writer.put((byte) 0); // Pad
2023-05-23 10:27:03 -04:00
2023-07-15 09:23:48 -04:00
for (Zone child : zone.nodes) {
Zone.serializeForClientMsg(child, writer);
}
}
2023-05-23 10:27:03 -04:00
2023-10-18 08:42:40 -04:00
@Override
public void runAfterLoad() {
2023-10-20 17:01:42 -04:00
this.template = ZoneManager._zone_templates.get(this.templateID);
2023-10-18 08:42:40 -04:00
// First zone is always the seafloor
if (ZoneManager.seaFloor == null)
ZoneManager.seaFloor = this;
2024-01-09 12:55:08 -05:00
// Guild zones use the enum CityBoundsType to adjust
// city size. All other zones derive from the JSON
// stored within its template.
2024-01-04 12:43:30 -05:00
2024-01-09 12:55:08 -05:00
if (this.template == null) {
2024-01-04 12:43:30 -05:00
this.minor_radius = Enum.CityBoundsType.ZONE.halfExtents;
this.major_radius = Enum.CityBoundsType.ZONE.halfExtents;
2024-01-09 12:55:08 -05:00
} else {
this.minor_radius = this.template.minor_radius;
this.major_radius = this.template.major_radius;
2024-01-04 12:43:30 -05:00
}
2023-10-22 12:05:06 -04:00
this.setParent();
this.setBounds();
2023-10-20 17:01:42 -04:00
if (this.template.terrain_type.equals("NONE"))
2023-10-18 08:42:40 -04:00
this.terrain = null;
else
this.terrain = new Terrain(this);
2023-10-22 12:05:06 -04:00
this.global_height = ZoneManager.calculateGlobalZoneHeight(this);
setSeaLevel();
2023-10-18 08:42:40 -04:00
if (this.min_level == 0 && this.parent != null) {
this.min_level = this.parent.min_level;
this.max_level = this.parent.max_level;
}
ZoneManager.populateZoneCollections(this);
}
2023-07-15 09:23:48 -04:00
/* Method sets a default value for player cities
* otherwise using values derived from the loadnum
* field in the obj_zone database table.
*/
public void setBounds() {
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
// Set initial bounds object
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
this.bounds = Bounds.borrow();
2024-01-04 12:43:30 -05:00
this.bounds.setBounds(new Vector2f(this.absX, this.absZ), new Vector2f(this.major_radius, this.minor_radius), 0.0f);
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
}
2022-04-30 09:41:17 -04:00
2023-10-18 08:42:40 -04:00
public void setParent() {
2023-05-23 10:27:03 -04:00
2023-10-18 08:51:46 -04:00
this.parent = ZoneManager.getZoneByUUID(parentZoneID);
2023-05-23 10:27:03 -04:00
2023-10-18 09:13:11 -04:00
if (parent != null)
parent.addNode(this);
2023-09-12 15:06:26 -04:00
// Seafloor
2023-10-18 08:42:40 -04:00
if (ZoneManager.seaFloor.equals(this)) {
2023-09-20 15:53:41 -04:00
this.absX = this.xOffset;
2023-09-12 15:09:52 -04:00
this.absY = MBServerStatics.SEA_FLOOR_ALTITUDE;
2023-10-15 15:57:58 -04:00
this.global_height = MBServerStatics.SEA_FLOOR_ALTITUDE;
2023-09-20 15:53:41 -04:00
this.absZ = this.zOffset;
2023-10-20 17:01:42 -04:00
this.sea_level = 0;
2023-09-17 23:53:06 -04:00
this.setBounds();
2023-09-12 14:57:47 -04:00
return;
}
2023-09-20 15:53:41 -04:00
this.absX = this.xOffset + parent.absX;
this.absY = this.yOffset + parent.absY;
this.absZ = this.zOffset + parent.absZ;
2023-09-12 15:09:52 -04:00
2023-09-20 16:07:50 -04:00
if (this.min_level == 0 || this.max_level == 0) {
this.min_level = this.parent.min_level;
this.max_level = this.parent.max_level;
2023-09-12 15:09:52 -04:00
}
2023-10-08 09:59:13 -04:00
}
private void setSeaLevel() {
int world_sea_level = 0;
2023-09-20 15:43:01 -04:00
if (this.parent == null) {
2023-10-08 09:59:13 -04:00
this.sea_level = world_sea_level;
2023-09-14 09:13:02 -04:00
return;
}
2023-10-20 17:01:42 -04:00
switch (this.template.sea_level_type) {
2023-10-08 09:59:13 -04:00
case "WORLD":
2023-10-20 17:01:42 -04:00
this.sea_level = world_sea_level + this.template.sea_level;
2023-10-08 09:59:13 -04:00
break;
case "PARENT":
2023-10-20 17:01:42 -04:00
this.sea_level = this.parent.sea_level + this.template.sea_level;
2023-10-08 09:59:13 -04:00
break;
case "SELF":
2023-10-20 17:01:42 -04:00
this.sea_level = this.global_height + this.template.sea_level;
2023-10-08 09:59:13 -04:00
break;
2023-09-14 09:13:02 -04:00
}
2023-07-15 09:23:48 -04:00
}
2023-05-23 10:27:03 -04:00
2023-07-15 09:23:48 -04:00
public boolean isMacroZone() {
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
// Macro zones have icons.
2022-04-30 09:41:17 -04:00
2023-10-18 08:42:40 -04:00
if (this.guild_zone)
2023-07-15 09:23:48 -04:00
return false;
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
if (this.parent == null)
return false;
2022-04-30 09:41:17 -04:00
2023-09-20 16:07:50 -04:00
return !icon1.equals("");
2023-07-15 09:23:48 -04:00
}
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
public Vector3fImmutable getLoc() {
return new Vector3fImmutable(this.absX, this.absY, this.absZ);
}
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
public int getParentZoneID() {
return this.parentZoneID;
}
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
/*
* Serializing
*/
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
public void addNode(Zone child) {
this.nodes.add(child);
}
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
@Override
public void updateDatabase() {
// TODO Auto-generated method stub
}
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
public boolean isContinent() {
2022-04-30 09:41:17 -04:00
2023-10-09 06:16:25 -04:00
if (this.equals(ZoneManager.seaFloor))
2023-07-15 09:23:48 -04:00
return false;
2023-03-21 03:20:57 -04:00
2023-10-18 08:33:49 -04:00
if (this.nodes.isEmpty())
2023-07-15 09:23:48 -04:00
return false;
2022-04-30 09:41:17 -04:00
2023-10-18 08:33:49 -04:00
if (this.nodes.get(0).isMacroZone())
2023-07-15 09:23:48 -04:00
return true;
2023-03-21 03:20:57 -04:00
2023-10-09 06:16:25 -04:00
return this.parent.equals(ZoneManager.seaFloor);
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
}
2023-10-18 08:42:40 -04:00
2023-07-15 09:23:48 -04:00
public void setHash() {
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
this.hash = DataWarehouse.hasher.encrypt(this.getObjectUUID());
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
// Write hash to player character table
2022-04-30 09:41:17 -04:00
2023-07-15 09:23:48 -04:00
DataWarehouse.writeHash(Enum.DataRecordType.ZONE, this.getObjectUUID());
}
2022-04-30 09:41:17 -04:00
}