release-1.3 #13

Merged
MagicBot merged 40 commits from release-1.3 into master 2 years ago
  1. 65
      README.md
  2. 3
      src/discord/MagicBot.java
  3. 6
      src/engine/Enum.java
  4. 1
      src/engine/ai/MobileFSM.java
  5. 2
      src/engine/ai/MobileFSMManager.java
  6. 139
      src/engine/ai/utilities/CombatUtilities.java
  7. 2
      src/engine/db/archive/DataWarehouse.java
  8. 10
      src/engine/gameManager/ConfigManager.java
  9. 2
      src/engine/gameManager/MaintenanceManager.java
  10. 98
      src/engine/gameManager/MovementManager.java
  11. 40
      src/engine/jobs/FlightJob.java
  12. 16
      src/engine/net/client/handlers/AbandonAssetMsgHandler.java
  13. 19
      src/engine/net/client/handlers/DestroyBuildingHandler.java
  14. 393
      src/engine/net/client/handlers/PlaceAssetMsgHandler.java
  15. 12
      src/engine/objects/City.java
  16. 13
      src/engine/objects/Mob.java
  17. 5
      src/engine/objects/PlayerCharacter.java
  18. 171
      src/engine/powers/poweractions/AbstractPowerAction.java
  19. 10
      src/engine/server/MBServerStatics.java
  20. 4
      src/engine/server/login/LoginServer.java
  21. 2
      src/engine/server/login/LoginServerMsgHandler.java
  22. 4
      src/engine/server/world/WorldServer.java
  23. 60
      src/engine/util/MiscUtils.java

65
README.md

@ -20,70 +20,11 @@ The Magicbane Team has wanted to open source Shadowbane for half a decade. We a
## Contributing ## Contributing
- Project is released under an MIT license. Please see the LICENSE file.
- Inbound == Outbound. - Inbound == Outbound.
- IntelliJ is the supported IDE. - IntelliJ is the supported IDE.
- Write code today see it running on the Magicbane production server tomorrow. - Write code today see it running on the Magicbane production server tomorrow.
## Project setup ## Support
**Prerequisites**: Documentation is available through the Magicbane [Wiki](http://repo.magicbane.com/MagicBane/Server/wiki) and [Discord server](www.magicbane.com).
- Git
- IntelliJ
- Java 8 JDK
- Account on the Magicbane [Public Repository](http://repo.magicbane.com)
Copy the HTTP link if you haven't yet installed a public key:
![CopyUrl](https://www.magicbane.com/Development/images/repo.png)
- Clone the Magicbane public repo to your local machine using the copied URL.
![CloneURL](https://www.magicbane.com/Development/images/intellij1.png)
- Under Settings->VersionControl->Git make sure to turn off these two settings.
![CommitOff](https://www.magicbane.com/Development/images/commit.png)
- Select the Project Structure settings within the IDE.
![ProjectStructure](https://www.magicbane.com/Development/images/projectstructure.png)
- Select Java 8 as the IDE target as shown.
![Java8](https://www.magicbane.com/Development/images/project.png)
- Delete and recreate content root pointing at the **Server** directory.
- Make sure the Language Level still reflects Java 8.
- The IDE should now autodetect the cloned source.
![hmm](https://www.magicbane.com/Development/images/module.png)
Magicbane currently has the following dependencies.
<br>
- [EnumBitSet](https://github.com/claudemartin/enum-bit-set)
- [HikariCP](https://github.com/brettwooldridge/HikariCP)
- [JDA](https://github.com/DV8FromTheWorld/JDA)
- [JodaTime](https://github.com/JodaOrg/joda-time)
- [TinyLog](https://github.com/tinylog-org/tinylog/tree/v1.3)
- [MySqlConnector](https://dev.mysql.com/downloads/connector/j/)
They are all directly obtainable from a running MagicBox instance.
``` docker cp magicbox:/usr/share/java/EnumBitSet.jar Dependencies/```
Add the jar files as project libraries as shown.
![Libs](https://www.magicbane.com/Development/images/libraries.png)
You should now be able to build the game!
![Build](https://magicbane.com/Development/images/buildproject.png)
### Next Steps
You can now move onto the [Development Workflow](http://repo.magicbane.com/MagicBane/Server/wiki/Development-workflow) or [MagicBox Setup](http://repo.magicbane.com/MagicBane/Server/wiki/MagicBox-:-Magicbane-in-a-Box) pages for further information.
Support is also available through the Magicbane [Discord server](www.magicbane.com). Feel free to stop in and pick Magicbot's brain!

3
src/discord/MagicBot.java

@ -10,7 +10,6 @@
package discord; package discord;
import discord.handlers.*; import discord.handlers.*;
import engine.Enum;
import engine.gameManager.ConfigManager; import engine.gameManager.ConfigManager;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.JDABuilder;
@ -29,8 +28,6 @@ import org.pmw.tinylog.writers.RollingFileWriter;
import javax.security.auth.login.LoginException; import javax.security.auth.login.LoginException;
import java.io.*; import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;

6
src/engine/Enum.java

@ -2416,9 +2416,9 @@ public class Enum {
public enum CityBoundsType { public enum CityBoundsType {
GRID(576), GRID(512),
ZONE(640), ZONE(576),
SIEGE(814); SIEGE(1040);
public final float extents; public final float extents;

1
src/engine/ai/MobileFSM.java

@ -1130,7 +1130,6 @@ public class MobileFSM {
} }
HashMap<Integer, Integer> staticPowers = aiAgent.getMobBase().getStaticPowers(); HashMap<Integer, Integer> staticPowers = aiAgent.getMobBase().getStaticPowers();
if (staticPowers != null && !staticPowers.isEmpty()) { if (staticPowers != null && !staticPowers.isEmpty()) {
int chance = ThreadLocalRandom.current().nextInt(100); int chance = ThreadLocalRandom.current().nextInt(100);

2
src/engine/ai/MobileFSMManager.java

@ -16,8 +16,6 @@ import engine.server.MBServerStatics;
import engine.util.ThreadUtils; import engine.util.ThreadUtils;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.util.HashSet;
public class MobileFSMManager { public class MobileFSMManager {

139
src/engine/ai/utilities/CombatUtilities.java

@ -15,13 +15,19 @@ import engine.Enum.*;
import engine.ai.MobileFSM.STATE; import engine.ai.MobileFSM.STATE;
import engine.gameManager.ChatManager; import engine.gameManager.ChatManager;
import engine.gameManager.CombatManager; import engine.gameManager.CombatManager;
import engine.gameManager.PowersManager;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.net.DispatchMessage; import engine.net.DispatchMessage;
import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.TargetedActionMsg; import engine.net.client.msg.TargetedActionMsg;
import engine.objects.*; import engine.objects.*;
import engine.powers.ActionsBase;
import engine.powers.PowersBase;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import org.pmw.tinylog.Logger; import org.pmw.tinylog.Logger;
import java.util.Map;
import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
@ -237,7 +243,6 @@ public class CombatUtilities {
speed = agent.getSpeedHandOne(); speed = agent.getSpeedHandOne();
else else
speed = agent.getSpeedHandTwo(); speed = agent.getSpeedHandTwo();
DamageType dt = DamageType.Crush; DamageType dt = DamageType.Crush;
if (agent.isSiege()) if (agent.isSiege())
dt = DamageType.Siege; dt = DamageType.Siege;
@ -271,15 +276,85 @@ public class CombatUtilities {
int passiveAnim = CombatManager.getSwingAnimation(wb, null,mainHand); int passiveAnim = CombatManager.getSwingAnimation(wb, null,mainHand);
if(canSwing(agent)) { if(canSwing(agent)) {
if(triggerDefense(agent,target)) if(triggerDefense(agent,target)) {
swingIsMiss(agent,target, passiveAnim); swingIsMiss(agent, target, passiveAnim);
else if(triggerDodge(agent,target)) return;
swingIsDodge(agent,target, passiveAnim); }
else if(triggerParry(agent,target)) else if(triggerDodge(agent,target)) {
swingIsParry(agent,target, passiveAnim); swingIsDodge(agent, target, passiveAnim);
else if(triggerBlock(agent,target)) return;
swingIsBlock(agent,target, passiveAnim); }
else if (triggerParry(agent, target)){
swingIsParry(agent, target, passiveAnim);
return;
}
else if(triggerBlock(agent,target)) {
swingIsBlock(agent, target, passiveAnim);
return;
}
else else
//check for a cast here?
//agent.mobPowers = DbManager.MobBaseQueries.LOAD_STATIC_POWERS(agent.getMobBaseID());
if(agent.mobPowers.size() > 0 && agent.mobPowers != null)
{
//get cast chance 33% cast 67% mele
int random = ThreadLocalRandom.current().nextInt(agent.mobPowers.size() * 10);
//allow casting of spell
if(random <= agent.mobPowers.size())
{
int powerToken;
int powerRank;
//cast a spell
Map<Integer,Integer> entries = agent.mobPowers;
int count = 0;
for(Map.Entry<Integer,Integer> entry : entries.entrySet())
{
count += 1;
if(count == random)
{
powerToken = entry.getKey();
//powerRank = entry.getValue();
switch(agent.getLevel())
{
default:
powerRank = 1;
break;
case 10:
powerRank = 5;
break;
case 20:
powerRank = 10;
break;
case 30:
powerRank = 15;
break;
case 40:
powerRank = 25;
break;
case 50:
powerRank = 30;
break;
case 60:
powerRank = 35;
break;
case 70:
powerRank = 40;
break;
}
//System.out.println(agent.getMobBase().getFirstName() + " is casting: " + PowersManager.getPowerByToken(powerToken).skillName);
PowersManager.applyPower(agent,target,target.getLoc(),powerToken,powerRank, false);
//PerformActionMsg msg = new PerformActionMsg();
//PowersManager.sendPowerMsg((PlayerCharacter)target,0,msg);
//return;
}
}
return;
}
}
//finished with casting check
swingIsDamage(agent,target, determineDamage(agent,target, mainHand, speed, dt), anim); swingIsDamage(agent,target, determineDamage(agent,target, mainHand, speed, dt), anim);
if (agent.getWeaponPower() != null) if (agent.getWeaponPower() != null)
@ -380,11 +455,46 @@ public class CombatUtilities {
public static float determineDamage(Mob agent,AbstractWorldObject target, boolean mainHand, float speed, DamageType dt) { public static float determineDamage(Mob agent,AbstractWorldObject target, boolean mainHand, float speed, DamageType dt) {
float min = (mainHand) ? agent.getMinDamageHandOne() : agent.getMinDamageHandTwo(); float min = (mainHand) ? agent.getMinDamageHandOne() : agent.getMinDamageHandTwo();
float max = (mainHand) ? agent.getMaxDamageHandOne() : agent.getMaxDamageHandTwo();; float max = (mainHand) ? agent.getMaxDamageHandOne() : agent.getMaxDamageHandTwo();
if(agent.isSummonedPet() == true)
{
min = 40 * (1 + (agent.getLevel()/10));
max = 60 * (1 + (agent.getLevel()/8));
//check if we have powers to cast
if(agent.mobPowers.isEmpty() == false) {
//check for power usage
Random random = new Random();
int value = random.nextInt(0 + (agent.mobPowers.size() + (agent.mobPowers.size() * 5))) + 0;
if (value <= agent.mobPowers.size())
{
//do power
int powerId = agent.mobPowers.get(value);
PowersManager.runPowerAction(agent,target,target.getLoc(),new ActionsBase(),40, PowersManager.getPowerByToken(powerId));
}
else
{
//do mele damage
float range = max - min;
float damage = min + ((ThreadLocalRandom.current().nextFloat() * range) + (ThreadLocalRandom.current().nextFloat() * range)) / 2;
if (AbstractWorldObject.IsAbstractCharacter(target))
if (((AbstractCharacter) target).isSit())
damage *= 2.5f; //increase damage if sitting
if (AbstractWorldObject.IsAbstractCharacter(target))
return ((AbstractCharacter) target).getResists().getResistedDamage(agent, (AbstractCharacter) target, dt, damage, 0);
if (target.getObjectType() == GameObjectType.Building) {
Building building = (Building) target;
Resists resists = building.getResists();
return damage * (1 - (resists.getResist(dt, 0) / 100));
}
}
}
}
float range = max - min; float range = max - min;
float damage = min + ((ThreadLocalRandom.current().nextFloat()*range)+(ThreadLocalRandom.current().nextFloat()*range))/2; float damage = min + ((ThreadLocalRandom.current().nextFloat()*range)+(ThreadLocalRandom.current().nextFloat()*range))/2;
//DAMAGE FORMULA FOR PET
if (AbstractWorldObject.IsAbstractCharacter(target)) if (AbstractWorldObject.IsAbstractCharacter(target))
if (((AbstractCharacter)target).isSit()) if (((AbstractCharacter)target).isSit())
damage *= 2.5f; //increase damage if sitting damage *= 2.5f; //increase damage if sitting
@ -404,10 +514,7 @@ public class CombatUtilities {
public static boolean RunAIRandom(){ public static boolean RunAIRandom(){
int random = ThreadLocalRandom.current().nextInt(4); int random = ThreadLocalRandom.current().nextInt(4);
if (random == 0) return random == 0;
return true;
return false;
} }
} }

2
src/engine/db/archive/DataWarehouse.java

@ -39,7 +39,7 @@ public class DataWarehouse implements Runnable {
// If WarehousePush is disabled // If WarehousePush is disabled
// then early exit // then early exit
if ( ConfigManager.MB_WORLD_WAREHOUSE_PUSH.getValue().equals("false")) { if ( ConfigManager.MB_WORLD_WAREHOUSE_PUSH.getValue().equalsIgnoreCase("false")) {
Logger.info("Warehouse Remote Connection disabled along with push"); Logger.info("Warehouse Remote Connection disabled along with push");
return; return;
} }

10
src/engine/gameManager/ConfigManager.java

@ -20,6 +20,7 @@ import org.pmw.tinylog.Logger;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern;
public enum ConfigManager { public enum ConfigManager {
@ -47,6 +48,8 @@ public enum ConfigManager {
MB_LOGIN_PORT, MB_LOGIN_PORT,
MB_LOGIN_AUTOREG, MB_LOGIN_AUTOREG,
MB_LOGIN_FNAME_REGEX,
MB_MAJOR_VER, MB_MAJOR_VER,
MB_MINOR_VER, MB_MINOR_VER,
@ -87,6 +90,7 @@ public enum ConfigManager {
public static NetMsgHandler handler; public static NetMsgHandler handler;
public static WorldServer worldServer; public static WorldServer worldServer;
public static LoginServer loginServer; public static LoginServer loginServer;
public static Map<ConfigManager, Pattern> regex = new HashMap<>();
// Called at bootstrap: ensures that all config values are loaded. // Called at bootstrap: ensures that all config values are loaded.
@ -99,9 +103,15 @@ public enum ConfigManager {
Logger.info(configSetting.name() + ":" + configSetting.getValue()); Logger.info(configSetting.name() + ":" + configSetting.getValue());
else { else {
Logger.error("Missing Config: " + configSetting.name()); Logger.error("Missing Config: " + configSetting.name());
Logger.error("This codebase requires >= MagicBox v1.3");
Logger.error("docker pull magicbane/magicbox:latest");
return false; return false;
} }
// compile regex here
regex.put(MB_LOGIN_FNAME_REGEX, Pattern.compile(MB_LOGIN_FNAME_REGEX.getValue()));
return true; return true;
} }

2
src/engine/gameManager/MaintenanceManager.java

@ -349,7 +349,7 @@ public enum MaintenanceManager {
// Run maintenance on player buildings // Run maintenance on player buildings
if ((boolean) ConfigManager.MB_WORLD_MAINTENANCE.getValue().equals("true")) if ((boolean) ConfigManager.MB_WORLD_MAINTENANCE.getValue().equalsIgnoreCase("true"))
processBuildingMaintenance(); processBuildingMaintenance();
else else
Logger.info("Maintenance Costings: DISABLED"); Logger.info("Maintenance Costings: DISABLED");

98
src/engine/gameManager/MovementManager.java

@ -15,16 +15,11 @@ import engine.Enum.SourceType;
import engine.InterestManagement.InterestManager; import engine.InterestManagement.InterestManager;
import engine.InterestManagement.WorldGrid; import engine.InterestManagement.WorldGrid;
import engine.exception.MsgSendException; import engine.exception.MsgSendException;
import engine.job.JobContainer;
import engine.job.JobScheduler;
import engine.jobs.ChangeAltitudeJob;
import engine.jobs.FlightJob;
import engine.math.Bounds; import engine.math.Bounds;
import engine.math.Vector3f; import engine.math.Vector3f;
import engine.math.Vector3fImmutable; import engine.math.Vector3fImmutable;
import engine.net.DispatchMessage; import engine.net.DispatchMessage;
import engine.net.client.ClientConnection; import engine.net.client.ClientConnection;
import engine.net.client.msg.ChangeAltitudeMsg;
import engine.net.client.msg.MoveToPointMsg; import engine.net.client.msg.MoveToPointMsg;
import engine.net.client.msg.TeleportToPointMsg; import engine.net.client.msg.TeleportToPointMsg;
import engine.net.client.msg.UpdateStateMsg; import engine.net.client.msg.UpdateStateMsg;
@ -339,61 +334,7 @@ public enum MovementManager {
} }
//Update for when the character is in flight
public static void updateFlight(PlayerCharacter pc, ChangeAltitudeMsg msg, int duration) {
if (pc == null)
return;
// clear flight timer job as we are about to update stuff and submit a new job
pc.clearTimer(flightTimerJobName);
if (!pc.isActive()) {
pc.setAltitude(0);
pc.setDesiredAltitude(0);
pc.setTakeOffTime(0);
return;
}
// Check to see if we are mid height change
JobContainer cjc = pc.getTimers().get(changeAltitudeTimerJobName);
if (cjc != null) {
addFlightTimer(pc, msg, MBServerStatics.FLY_FREQUENCY_MS);
return;
}
// Altitude is zero, do nothing
if (pc.getAltitude() < 1)
return;
//make sure player is still allowed to fly
boolean canFly = false;
PlayerBonuses bonus = pc.getBonuses();
if (bonus != null && !bonus.getBool(ModType.NoMod, SourceType.Fly) && bonus.getBool(ModType.Fly, SourceType.None) && pc.isAlive())
canFly = true;
// if stam less that 2 - time to force a landing
if (pc.getStamina() < 10f || !canFly) {
// dont call stop movement here as we want to
// preserve endloc
//pc.stopMovement();
// sync world location
pc.setLoc(pc.getLoc());
// force a landing
msg.setStartAlt(pc.getAltitude());
msg.setTargetAlt(0);
msg.setAmountToMove(pc.getAltitude());
msg.setUp(false);
DispatchMessage.dispatchMsgToInterestArea(pc, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
MovementManager.addChangeAltitudeTimer(pc, msg.getStartAlt(), msg.getTargetAlt(), (int) (MBServerStatics.HEIGHT_CHANGE_TIMER_MS * pc.getAltitude()));
pc.setAltitude(msg.getStartAlt() - 10);
} else //Add a new flight timer to check stam / force land
if (pc.getAltitude() > 0)
addFlightTimer(pc, msg, MBServerStatics.FLY_FREQUENCY_MS);
}
public static void finishChangeAltitude(AbstractCharacter ac, float targetAlt) { public static void finishChangeAltitude(AbstractCharacter ac, float targetAlt) {
@ -529,27 +470,6 @@ public enum MovementManager {
member.setEndLoc(destination); member.setEndLoc(destination);
} }
} }
//Getting rid of flgith timer.
public static void addFlightTimer(PlayerCharacter pc, ChangeAltitudeMsg msg, int duration) {
if (pc == null || pc.getTimers() == null)
return;
if (!pc.getTimers().containsKey(flightTimerJobName)) {
FlightJob ftj = new FlightJob(pc, msg, duration);
JobContainer jc = JobScheduler.getInstance().scheduleJob(ftj, duration);
pc.getTimers().put(flightTimerJobName, jc);
}
}
public static void addChangeAltitudeTimer(PlayerCharacter pc, float startAlt, float targetAlt, int duration) {
if (pc == null || pc.getTimers() == null)
return;
ChangeAltitudeJob catj = new ChangeAltitudeJob(pc, startAlt, targetAlt);
JobContainer jc = JobScheduler.getInstance().scheduleJob(catj, duration);
pc.getTimers().put(changeAltitudeTimerJobName, jc);
}
public static void translocate(AbstractCharacter teleporter, Vector3fImmutable targetLoc, Regions region) { public static void translocate(AbstractCharacter teleporter, Vector3fImmutable targetLoc, Regions region) {
@ -557,15 +477,10 @@ public enum MovementManager {
if (targetLoc == null) if (targetLoc == null)
return; return;
Vector3fImmutable oldLoc = new Vector3fImmutable(teleporter.getLoc()); Vector3fImmutable oldLoc = new Vector3fImmutable(teleporter.getLoc());
teleporter.stopMovement(targetLoc); teleporter.stopMovement(targetLoc);
teleporter.setRegion(region); teleporter.setRegion(region);
//mobs ignore region sets for now. //mobs ignore region sets for now.
if (teleporter.getObjectType().equals(GameObjectType.Mob)){ if (teleporter.getObjectType().equals(GameObjectType.Mob)){
@ -588,17 +503,11 @@ public enum MovementManager {
public static void translocateToObject(AbstractCharacter teleporter, AbstractWorldObject worldObject) { public static void translocateToObject(AbstractCharacter teleporter, AbstractWorldObject worldObject) {
Vector3fImmutable targetLoc = teleporter.getLoc(); Vector3fImmutable targetLoc = teleporter.getLoc();
Vector3fImmutable oldLoc = new Vector3fImmutable(teleporter.getLoc()); Vector3fImmutable oldLoc = new Vector3fImmutable(teleporter.getLoc());
teleporter.stopMovement(teleporter.getLoc()); teleporter.stopMovement(teleporter.getLoc());
//mobs ignore region sets for now. //mobs ignore region sets for now.
if (teleporter.getObjectType().equals(GameObjectType.Mob)){ if (teleporter.getObjectType().equals(GameObjectType.Mob)){
@ -609,6 +518,7 @@ public enum MovementManager {
DispatchMessage.dispatchMsgToInterestArea(oldLoc, teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false); DispatchMessage.dispatchMsgToInterestArea(oldLoc, teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
return; return;
} }
boolean collide = false; boolean collide = false;
int maxFloor = -1; int maxFloor = -1;
int buildingID = 0; int buildingID = 0;
@ -619,6 +529,7 @@ public enum MovementManager {
if (collide) if (collide)
break; break;
} }
if (!collide) { if (!collide) {
teleporter.setInBuildingID(0); teleporter.setInBuildingID(0);
teleporter.setInBuilding(-1); teleporter.setInBuilding(-1);
@ -633,7 +544,6 @@ public enum MovementManager {
} }
} }
TeleportToPointMsg msg = new TeleportToPointMsg(teleporter, targetLoc.getX(), targetLoc.getY(), targetLoc.getZ(), 0, -1, -1); TeleportToPointMsg msg = new TeleportToPointMsg(teleporter, targetLoc.getX(), targetLoc.getY(), targetLoc.getZ(), 0, -1, -1);
//we shouldnt need to send teleport message to new area, as loadjob should pick it up. //we shouldnt need to send teleport message to new area, as loadjob should pick it up.
// DispatchMessage.dispatchMsgToInterestArea(teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false); // DispatchMessage.dispatchMsgToInterestArea(teleporter, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);

40
src/engine/jobs/FlightJob.java

@ -1,40 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.jobs;
import engine.gameManager.MovementManager;
import engine.job.AbstractScheduleJob;
import engine.net.client.msg.ChangeAltitudeMsg;
import engine.objects.PlayerCharacter;
public class FlightJob extends AbstractScheduleJob {
private final PlayerCharacter pc;
private final ChangeAltitudeMsg msg;
private final int duration;
public FlightJob(PlayerCharacter pc, ChangeAltitudeMsg msg, int duration) {
super();
this.msg = msg;
this.duration = duration;
this.pc = pc;
}
@Override
protected void doJob() {
if (this.pc != null && this.msg != null)
MovementManager.updateFlight(pc, msg, duration);
}
@Override
protected void _cancelJob() {
}
}

16
src/engine/net/client/handlers/AbandonAssetMsgHandler.java

@ -92,7 +92,23 @@ public class AbandonAssetMsgHandler extends AbstractClientMsgHandler {
// Trees require special handling beyond an individual building // Trees require special handling beyond an individual building
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.TOL)) if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.TOL))
{
// CHECK IF GUILD HAS A BANE DROPPED
City city = ZoneManager.getCityAtLocation(building.getLoc());
if(city.getGuild().getSubGuildList().isEmpty() == false)
{
//nations cant abandon their tree
ErrorPopupMsg.sendErrorMsg(player, "Nations Cannot Abandon Their Capital!");
return true;
}
if(Bane.getBaneByAttackerGuild(city.getGuild()) != null)
{
ErrorPopupMsg.sendErrorMsg(player, "You Cannot Abandon Your Tree With An Active Siege!");
return true;
}
AbandonAllCityObjects(player, building); AbandonAllCityObjects(player, building);
}
else else
AbandonSingleAsset(player, building); AbandonSingleAsset(player, building);

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

@ -8,10 +8,8 @@ import engine.gameManager.BuildingManager;
import engine.net.client.ClientConnection; import engine.net.client.ClientConnection;
import engine.net.client.msg.ClientNetMsg; import engine.net.client.msg.ClientNetMsg;
import engine.net.client.msg.DestroyBuildingMsg; import engine.net.client.msg.DestroyBuildingMsg;
import engine.objects.Blueprint; import engine.net.client.msg.ErrorPopupMsg;
import engine.objects.Building; import engine.objects.*;
import engine.objects.City;
import engine.objects.PlayerCharacter;
/* /*
* @Author: * @Author:
@ -43,7 +41,7 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler {
Blueprint blueprint; Blueprint blueprint;
blueprint = building.getBlueprint(); blueprint = building.getBlueprint();
City city = building.getCity();
// Can't destroy buildings without a blueprint. // Can't destroy buildings without a blueprint.
if (blueprint == null) if (blueprint == null)
@ -57,7 +55,11 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler {
if (!BuildingManager.PlayerCanControlNotOwner(building, pc)) if (!BuildingManager.PlayerCanControlNotOwner(building, pc))
return true; return true;
Bane bane = city.getBane();
if(bane.getSiegePhase() == Enum.SiegePhase.WAR && bane != null) {
ErrorPopupMsg.sendErrorPopup(pc, 171);
return true;
}
// Can't destroy a tree of life // Can't destroy a tree of life
if (blueprint.getBuildingGroup() == BuildingGroup.TOL) if (blueprint.getBuildingGroup() == BuildingGroup.TOL)
return true; return true;
@ -71,15 +73,12 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler {
if (blueprint.getBuildingGroup() == BuildingGroup.RUNEGATE) if (blueprint.getBuildingGroup() == BuildingGroup.RUNEGATE)
return true; return true;
//stop if active siege
// Turn off spire if destoying // Turn off spire if destoying
if (blueprint.getBuildingGroup() == BuildingGroup.SPIRE) if (blueprint.getBuildingGroup() == BuildingGroup.SPIRE)
building.disableSpire(true); building.disableSpire(true);
if (blueprint.getBuildingGroup() == BuildingGroup.WAREHOUSE) { if (blueprint.getBuildingGroup() == BuildingGroup.WAREHOUSE) {
City city = building.getCity();
if (city != null) if (city != null)
city.setWarehouseBuildingID(0); city.setWarehouseBuildingID(0);
} }

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

@ -92,7 +92,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
if (buildingList == null) { if (buildingList == null) {
Logger.error("Player " + playerCharacter.getCombinedName() Logger.error("Player " + playerCharacter.getCombinedName()
+ " null building list on deed use"); + " null building list on deed use");
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
closePlaceAssetWindow(origin); closePlaceAssetWindow(origin);
return true; return true;
@ -115,7 +115,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
if (buildingBlueprint == null) { if (buildingBlueprint == null) {
Logger.error("Player " + playerCharacter.getCombinedName() Logger.error("Player " + playerCharacter.getCombinedName()
+ " null blueprint UUID: " + buildingList.getBlueprintUUID() + " on deed use"); + " null blueprint UUID: " + buildingList.getBlueprintUUID() + " on deed use");
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
closePlaceAssetWindow(origin); closePlaceAssetWindow(origin);
return true; return true;
@ -130,66 +130,66 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
boolean close = true; boolean close = true;
lock.writeLock().lock(); lock.writeLock().lock();
boolean isSiege = false;
try { try {
switch (buildingBlueprint.getBuildingGroup()) { switch (buildingBlueprint.getBuildingGroup()) {
case TOL: case TOL:
if (contract == null) if (contract == null)
break; break;
buildingCreated = placeTreeOfLife(playerCharacter, origin, msg); buildingCreated = placeTreeOfLife(playerCharacter, origin, msg);
break;
case WAREHOUSE:
if (contract == null)
break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID()))
break;
buildingCreated = placeWarehouse(playerCharacter, origin, msg);
break;
case SIEGETENT:
case BULWARK:
if (contract == null)
break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID()))
break;
buildingCreated = placeSiegeEquip(playerCharacter, origin, msg);
break;
case SPIRE:
if (contract == null)
break; break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID())) case WAREHOUSE:
if (contract == null)
break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID()))
break;
buildingCreated = placeWarehouse(playerCharacter, origin, msg);
break; break;
buildingCreated = placeSpire(playerCharacter, origin, msg); case SIEGETENT:
break; case BULWARK:
case SHRINE: if (contract == null)
if (contract == null) break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID()))
break;
buildingCreated = placeSiegeEquip(playerCharacter, origin, msg);
break; break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID())) case SPIRE:
if (contract == null)
break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID()))
break;
buildingCreated = placeSpire(playerCharacter, origin, msg);
break; break;
buildingCreated = placeShrine(playerCharacter, origin, msg); case SHRINE:
break; if (contract == null)
case BARRACK: break;
if (contract == null) if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID()))
break;
buildingCreated = placeShrine(playerCharacter, origin, msg);
break; break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID())) case BARRACK:
if (contract == null)
break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID()))
break;
buildingCreated = placeBarrack(playerCharacter, origin, msg);
break; break;
buildingCreated = placeBarrack(playerCharacter, origin, msg); case WALLSTRAIGHT:
break; case WALLCORNER:
case WALLSTRAIGHT: case SMALLGATE:
case WALLCORNER: case ARTYTOWER:
case SMALLGATE: case WALLSTAIRS:
case ARTYTOWER: buildingCreated = placeCityWalls(playerCharacter, origin, msg);
case WALLSTAIRS: close = false;
buildingCreated = placeCityWalls(playerCharacter, origin, msg);
close = false;
break;
default:
if (contract == null)
break; break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID())) default:
if (contract == null)
break;
if (!playerCharacter.getCharItemManager().doesCharOwnThisItem(contract.getObjectUUID()))
break;
buildingCreated = placeSingleBuilding(playerCharacter, origin, msg);
break; break;
buildingCreated = placeSingleBuilding(playerCharacter, origin, msg);
break;
} }
} catch (Exception e) { } catch (Exception e) {
Logger.error("PlaceAssetHandler", e.getMessage()); Logger.error("PlaceAssetHandler", e.getMessage());
@ -230,7 +230,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
buildingList = msg.getFirstPlacementInfo(); buildingList = msg.getFirstPlacementInfo();
serverZone = ZoneManager.findSmallestZone(buildingList.getLoc()); serverZone = ZoneManager.findSmallestZone(buildingList.getLoc());
// Early exit if something went horribly wrong // Early exit if something went horribly wrong
// with locating the current or zone // with locating the current or zone
@ -346,125 +345,125 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
City attackerCity = null; City attackerCity = null;
if (bane != null) if (bane != null)
attackerCity = bane.getCity(); attackerCity = bane.getCity();
if (attackerCity != null) if (attackerCity != null)
if (buildingList.getLoc().isInsideCircle(attackerCity.getLoc(), Enum.CityBoundsType.SIEGE.extents)) if (buildingList.getLoc().isInsideCircle(attackerCity.getLoc(), Enum.CityBoundsType.SIEGE.extents))
serverCity = attackerCity; serverCity = attackerCity;
} }
//no city found for attacker city, //no city found for attacker city,
//check if defender city //check if defender city
if (serverCity == null){ if (serverCity == null){
if (player.getGuild().getOwnedCity() != null) if (player.getGuild().getOwnedCity() != null)
if (buildingList.getLoc().isInsideCircle(player.getGuild().getOwnedCity().getLoc(), Enum.CityBoundsType.SIEGE.extents)) if (buildingList.getLoc().isInsideCircle(player.getGuild().getOwnedCity().getLoc(), Enum.CityBoundsType.SIEGE.extents))
serverCity = player.getGuild().getOwnedCity(); serverCity = player.getGuild().getOwnedCity();
} }
if ((serverCity != null) && if ((serverCity != null) &&
(serverCity.getBane() != null)) { (serverCity.getBane() != null)) {
// Set the server zone to the city zone in order to account for being inside // Set the server zone to the city zone in order to account for being inside
// the siege bounds buffer area // the siege bounds buffer area
serverZone = serverCity.getParent(); serverZone = serverCity.getParent();
if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild()) == false) if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild()) == false)
&& (player.getGuild().equals(serverCity.getGuild()) == false)) { && (player.getGuild().equals(serverCity.getGuild()) == false)) {
PlaceAssetMsg.sendPlaceAssetError(origin, 54, ""); // Must belong to attacker or defender PlaceAssetMsg.sendPlaceAssetError(origin, 54, ""); // Must belong to attacker or defender
return false; return false;
} }
} }
// cant place siege equipment off city zone. // cant place siege equipment off city zone.
// Create the siege Building // Create the siege Building
siegeBuilding = createStructure(player, msg.getFirstPlacementInfo(), serverZone); siegeBuilding = createStructure(player, msg.getFirstPlacementInfo(), serverZone);
if (serverCity == null) if (serverCity == null)
return true; return true;
// Oops something went really wrong // Oops something went really wrong
if (siegeBuilding == null) if (siegeBuilding == null)
return false; return false;
if (serverCity.getBane() == null)
return true;
if (serverCity.getBane() == null)
return true;
// If there is an bane placed, we protect 2x the stone rank's worth of attacker assets // If there is an bane placed, we protect 2x the stone rank's worth of attacker assets
// and 1x the tree rank's worth of assets automatically // and 1x the tree rank's worth of assets automatically
HashSet<AbstractWorldObject> awoList = WorldGrid.getObjectsInRangePartial(serverCity, 1000, MBServerStatics.MASK_BUILDING);
HashSet<AbstractWorldObject> awoList = WorldGrid.getObjectsInRangePartial(serverCity, 1000, MBServerStatics.MASK_BUILDING);
for (AbstractWorldObject awo : awoList) { for (AbstractWorldObject awo : awoList) {
Building building = (Building)awo; Building building = (Building)awo;
if (building.getBlueprint() != null) if (building.getBlueprint() != null)
if (!building.getBlueprint().isSiegeEquip()) if (!building.getBlueprint().isSiegeEquip())
continue; continue;
if (!building.getLoc().isInsideCircle(serverCity.getLoc(), Enum.CityBoundsType.SIEGE.extents)) if (!building.getLoc().isInsideCircle(serverCity.getLoc(), Enum.CityBoundsType.SIEGE.extents))
continue; continue;
if (building.getGuild() == null) if (building.getGuild() == null)
continue; continue;
if (building.getGuild().isErrant()) if (building.getGuild().isErrant())
continue; continue;
if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild())) if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
continue; continue;
// Only count auto protected buildings // Only count auto protected buildings
if (building.getProtectionState() != ProtectionState.PROTECTED) if (building.getProtectionState() != ProtectionState.PROTECTED)
continue; continue;
if (building.getGuild().equals(serverCity.getGuild()))
numDefenderBuildings++;
else
if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
numAttackerBuildings++;
if (building.getGuild().equals(serverCity.getGuild()))
numDefenderBuildings++;
else
if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
numAttackerBuildings++;
} }
// Validate bane limits on siege assets // Validate bane limits on siege assets
if (serverCity.getBane() != null) if (serverCity.getBane() != null)
if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild())) && if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild())) &&
(numAttackerBuildings >= serverCity.getBane().getStone().getRank() * 2)) { (numAttackerBuildings >= serverCity.getBane().getStone().getRank() * 2)) {
return true; return true;
} }
if ((player.getGuild().equals(serverCity.getGuild())) && if ((player.getGuild().equals(serverCity.getGuild())) &&
(numDefenderBuildings >= serverCity.getTOL().getRank())) { (numDefenderBuildings >= serverCity.getTOL().getRank())) {
return true; return true;
} }
// passes validation: can assign auto-protection to war asset // passes validation: can assign auto-protection to war asset
if (serverCity.getBane() != null) if (serverCity.getBane() != null)
if (serverCity.isLocationOnCityGrid(siegeBuilding.getBounds())) if (serverCity.isLocationOnCityGrid(siegeBuilding.getBounds()))
if (player.getGuild().equals(serverCity.getBane().getOwner().getGuild())) if (player.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
return true; return true;
siegeBuilding.setProtectionState(ProtectionState.PROTECTED); siegeBuilding.setProtectionState(ProtectionState.PROTECTED);
// No bane placed. We're done! // No bane placed. We're done!
return true; return true;
} }
@ -507,8 +506,8 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
} }
Vector3fImmutable plantLoc = new Vector3fImmutable(treeInfo.getLoc().x, Vector3fImmutable plantLoc = new Vector3fImmutable(treeInfo.getLoc().x,
serverZone.getHeightMap().getInterpolatedTerrainHeight(treeInfo.getLoc()), serverZone.getHeightMap().getInterpolatedTerrainHeight(treeInfo.getLoc()),
treeInfo.getLoc().z); treeInfo.getLoc().z);
cityObjects = DbManager.CityQueries.CREATE_CITY(playerCharacter.getObjectUUID(), serverZone.getObjectUUID(), cityObjects = DbManager.CityQueries.CREATE_CITY(playerCharacter.getObjectUUID(), serverZone.getObjectUUID(),
serverRealm.getRealmID(), serverRealm.getRealmID(),
@ -527,18 +526,18 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
for (AbstractGameObject gameObject : cityObjects) { for (AbstractGameObject gameObject : cityObjects) {
switch (gameObject.getObjectType()) { switch (gameObject.getObjectType()) {
case Building: case Building:
treeObject = (Building) gameObject; treeObject = (Building) gameObject;
treeObject.runAfterLoad(); treeObject.runAfterLoad();
break; break;
case City: case City:
cityObject = (City) gameObject; cityObject = (City) gameObject;
break; break;
case Zone: case Zone:
cityZone = (Zone) gameObject; cityZone = (Zone) gameObject;
break; break;
default: default:
// log some error here? *** Refactor // log some error here? *** Refactor
} }
} }
@ -562,7 +561,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
ZoneManager.addZone(cityZone.getObjectUUID(), cityZone); ZoneManager.addZone(cityZone.getObjectUUID(), cityZone);
ZoneManager.addPlayerCityZone(cityZone); ZoneManager.addPlayerCityZone(cityZone);
serverZone.addNode(cityZone); serverZone.addNode(cityZone);
cityZone.generateWorldAltitude(); cityZone.generateWorldAltitude();
cityObject.setParent(cityZone); cityObject.setParent(cityZone);
@ -708,7 +707,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
} }
blueprint = Blueprint.getBlueprint(msg.getFirstPlacementInfo().getBlueprintUUID()); blueprint = Blueprint.getBlueprint(msg.getFirstPlacementInfo().getBlueprintUUID());
if (blueprint == null){ if (blueprint == null){
return false; return false;
} }
@ -716,7 +715,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
for (Building building : serverZone.zoneBuildingSet) { for (Building building : serverZone.zoneBuildingSet) {
if (building.getBlueprint() == null) if (building.getBlueprint() == null)
continue; continue;
if (building.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE) { if (building.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE) {
if (building.getBlueprintUUID() == blueprint.getMeshForRank(0)) { if (building.getBlueprintUUID() == blueprint.getMeshForRank(0)) {
PlaceAssetMsg.sendPlaceAssetError(origin, 43, ""); // "shrine of that type exists" PlaceAssetMsg.sendPlaceAssetError(origin, 43, ""); // "shrine of that type exists"
@ -811,13 +810,13 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
if (serverZone == null) if (serverZone == null)
return false; return false;
if (player.getCharItemManager().getGoldTrading() > 0){ if (player.getCharItemManager().getGoldTrading() > 0){
ErrorPopupMsg.sendErrorPopup(player, 195); ErrorPopupMsg.sendErrorPopup(player, 195);
return false; return false;
} }
// Method checks validation conditions arising when placing // Method checks validation conditions arising when placing
// buildings. Player must be on a city grid, must be // buildings. Player must be on a city grid, must be
@ -956,7 +955,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
// Method validates the location we have selected for our new city // Method validates the location we have selected for our new city
private static boolean validateTreeOfLifePlacement(PlayerCharacter playerCharacter, Realm serverRealm, Zone serverZone, private static boolean validateTreeOfLifePlacement(PlayerCharacter playerCharacter, Realm serverRealm, Zone serverZone,
ClientConnection origin, PlaceAssetMsg msg) { ClientConnection origin, PlaceAssetMsg msg) {
PlacementInfo placementInfo = msg.getFirstPlacementInfo(); PlacementInfo placementInfo = msg.getFirstPlacementInfo();
@ -995,7 +994,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
if ( if (
(realmType.equals(RealmType.MAELSTROM)) || (realmType.equals(RealmType.MAELSTROM)) ||
(realmType.equals(RealmType.OBLIVION))) { (realmType.equals(RealmType.OBLIVION))) {
PlaceAssetMsg.sendPlaceAssetError(origin, 57, playerCharacter.getName()); // No building may be placed within this territory PlaceAssetMsg.sendPlaceAssetError(origin, 57, playerCharacter.getName()); // No building may be placed within this territory
return false; return false;
} }
@ -1107,7 +1106,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
float buildingRotation = buildingInfo.getRot().y; float buildingRotation = buildingInfo.getRot().y;
float vendorRotation = buildingInfo.getW(); float vendorRotation = buildingInfo.getW();
ArrayList<AbstractGameObject> shrineObjects = DbManager.ShrineQueries.CREATE_SHRINE( ArrayList<AbstractGameObject> shrineObjects = DbManager.ShrineQueries.CREATE_SHRINE(
currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0), currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0),
localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.PROTECTED, 0, 0, localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.PROTECTED, 0, 0,
@ -1121,20 +1120,20 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
for (AbstractGameObject ago : shrineObjects) { for (AbstractGameObject ago : shrineObjects) {
switch (ago.getObjectType()) { switch (ago.getObjectType()) {
case Building: case Building:
newMesh = (Building) ago; newMesh = (Building) ago;
newMesh.runAfterLoad(); newMesh.runAfterLoad();
newMesh.setObjectTypeMask(MBServerStatics.MASK_BUILDING); newMesh.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
MaintenanceManager.setMaintDateTime(newMesh, LocalDateTime.now().plusDays(7)); MaintenanceManager.setMaintDateTime(newMesh, LocalDateTime.now().plusDays(7));
WorldGrid.addObject(newMesh, player); WorldGrid.addObject(newMesh, player);
break; break;
case Shrine: case Shrine:
newShrine = (Shrine) ago; newShrine = (Shrine) ago;
newShrine.getShrineType().addShrineToServerList(newShrine); newShrine.getShrineType().addShrineToServerList(newShrine);
break; break;
default: default:
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
break; break;
} }
} }
@ -1172,7 +1171,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
float vendorRotation = buildingInfo.getW(); float vendorRotation = buildingInfo.getW();
DateTime completionDate = DateTime.now().plusHours(blueprint.getRankTime(1)); DateTime completionDate = DateTime.now().plusHours(blueprint.getRankTime(1));
newMesh = DbManager.BuildingQueries.CREATE_BUILDING( newMesh = DbManager.BuildingQueries.CREATE_BUILDING(
currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0), currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0),
localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.PROTECTED, 0, 0, localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.PROTECTED, 0, 0,
@ -1249,6 +1248,85 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
RealmType currentRealm; RealmType currentRealm;
if(Blueprint.getBlueprint(placementInfo.getBlueprintUUID()).isSiegeEquip() == false)
{
if (serverZone.isPlayerCity() == false) {
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
City city = ZoneManager.getCityAtLocation(placementInfo.getLoc());
if (player.getGuild().equals(city.getGuild()) == false) {
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
if (city.isLocationOnCityGrid(placementInfo.getLoc()) == false) {
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
}
else
{
City city = ZoneManager.getCityAtLocation(placementInfo.getLoc());
if(city == null)
{
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
Bane bane = city.getBane();
//check if player is owner/IC of tree or bane
if (player.getGuild().equals(city.getGuild()) == true)
{
//is from owners guild
if(GuildStatusController.isGuildLeader(player.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
{
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
}
else
{
//is not from owners guild
if(bane == null)
{
//bane was null
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
if(city == null)
{
//city was null
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
//check if player is from siege guild
if(player.getGuild().equals(bane.getOwner().getGuild()) == false)
{
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
//check if player is GL or IC of the bane guild
if(GuildStatusController.isGuildLeader(player.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
{
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
//cannot place on grid until bane is live
if(bane.getSiegePhase() != SiegePhase.WAR && city.isLocationOnCityGrid(placementInfo.getLoc()) == true)
{
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
if(city.isLocationWithinSiegeBounds(placementInfo.getLoc()) == false && city.isLocationOnCityZone(placementInfo.getLoc()) == false)
{
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
return false;
}
}
}
// Retrieve the building details we're placing // Retrieve the building details we're placing
if (serverZone.isNPCCity() == true) { if (serverZone.isNPCCity() == true) {
@ -1259,7 +1337,14 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
// Errant guilds cannot place assets // Errant guilds cannot place assets
if (player.getGuild().getGuildState() == GuildState.Errant) { if (player.getGuild().getGuildState() == GuildState.Errant) {
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "Only soverign or sworn guilds may place assets."); PlaceAssetMsg.sendPlaceAssetError(origin, 1, "Only sovereign or sworn guilds may place assets.");
return false;
}
// Player must be GL or IC of a guild to place buildings.
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false) {
PlaceAssetMsg.sendPlaceAssetError(origin, 10, ""); // You must be a guild leader
return false; return false;
} }
@ -1282,7 +1367,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
if ( if (
(currentRealm.equals(RealmType.MAELSTROM)) || (currentRealm.equals(RealmType.MAELSTROM)) ||
(currentRealm.equals(RealmType.OBLIVION))) { (currentRealm.equals(RealmType.OBLIVION))) {
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName()); // No building may be placed within this territory PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName()); // No building may be placed within this territory
return false; return false;
} }
@ -1373,8 +1458,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
PlaceAssetMsg.sendPlaceAssetError(origin, 9, ""); //You must be a guild member to place this asset PlaceAssetMsg.sendPlaceAssetError(origin, 9, ""); //You must be a guild member to place this asset
return false; return false;
} }
return true; return true;
} }
}
}

12
src/engine/objects/City.java

@ -999,11 +999,9 @@ public class City extends AbstractWorldObject {
HashSet<Integer> currentMemory; HashSet<Integer> currentMemory;
PlayerCharacter player; PlayerCharacter player;
// Gather current list of players within a distance defined by the x extent of the // Gather current list of players within a distance defined by the seige bounds
// city zone. As we want to grab all players with even a remote possibility of
// being in the zone, we might have to increase this distance.
currentPlayers = WorldGrid.getObjectsInRangePartial(this.location, this.parentZone.getBounds().getHalfExtents().x * 1.41421356237, MBServerStatics.MASK_PLAYER); currentPlayers = WorldGrid.getObjectsInRangePartial(this.location, CityBoundsType.SIEGE.extents, MBServerStatics.MASK_PLAYER);
currentMemory = new HashSet<>(); currentMemory = new HashSet<>();
for (AbstractWorldObject playerObject : currentPlayers) { for (AbstractWorldObject playerObject : currentPlayers) {
@ -1019,9 +1017,8 @@ public class City extends AbstractWorldObject {
if (_playerMemory.contains(player.getObjectUUID())) if (_playerMemory.contains(player.getObjectUUID()))
continue; continue;
if (!this.isLocationOnCityZone(player.getLoc())) if (!this.isLocationWithinSiegeBounds(player.getLoc()))
continue; continue;
// Apply safehold affect to player if needed // Apply safehold affect to player if needed
if ((this.isSafeHold == 1)) if ((this.isSafeHold == 1))
@ -1065,7 +1062,8 @@ public class City extends AbstractWorldObject {
player = PlayerCharacter.getFromCache(playerUUID); player = PlayerCharacter.getFromCache(playerUUID);
if (this.isLocationOnCityZone(player.getLoc()))
if (this.isLocationWithinSiegeBounds(player.getLoc()))
continue; continue;
// Remove players safezone status if warranted // Remove players safezone status if warranted

13
src/engine/objects/Mob.java

@ -111,7 +111,7 @@ public class Mob extends AbstractIntelligenceAgent {
public boolean despawned = false; public boolean despawned = false;
public Vector3fImmutable destination = Vector3fImmutable.ZERO; public Vector3fImmutable destination = Vector3fImmutable.ZERO;
public Vector3fImmutable localLoc = Vector3fImmutable.ZERO; public Vector3fImmutable localLoc = Vector3fImmutable.ZERO;
public HashMap<Integer,Integer> mobPowers;
/** /**
* No Id Constructor * No Id Constructor
*/ */
@ -365,6 +365,7 @@ public class Mob extends AbstractIntelligenceAgent {
this.setObjectTypeMask(MBServerStatics.MASK_PET | this.getTypeMasks()); this.setObjectTypeMask(MBServerStatics.MASK_PET | this.getTypeMasks());
if (ConfigManager.serverType.equals(ServerType.LOGINSERVER)) if (ConfigManager.serverType.equals(ServerType.LOGINSERVER))
this.setLoc(this.getLoc()); this.setLoc(this.getLoc());
mobPowers = DbManager.MobBaseQueries.LOAD_STATIC_POWERS(this.getMobBaseID());
} }
if (!isPet && this.contract == null) { if (!isPet && this.contract == null) {
this.level = (short) this.mobBase.getLevel(); this.level = (short) this.mobBase.getLevel();
@ -393,10 +394,10 @@ public class Mob extends AbstractIntelligenceAgent {
//TODO set these correctly later //TODO set these correctly later
this.rangeHandOne = 8; this.rangeHandOne = 8;
this.rangeHandTwo = -1; this.rangeHandTwo = -1;
this.minDamageHandOne = 0; this.minDamageHandOne = 0;
this.maxDamageHandOne = 0; this.maxDamageHandOne = 0;
this.minDamageHandTwo = 1; this.minDamageHandTwo = 1;
this.maxDamageHandTwo = 4; this.maxDamageHandTwo = 4;
this.atrHandOne = 300; this.atrHandOne = 300;
this.atrHandOne = 300; this.atrHandOne = 300;
this.defenseRating = (short) this.mobBase.getDefenseRating(); this.defenseRating = (short) this.mobBase.getDefenseRating();
@ -2201,7 +2202,7 @@ public class Mob extends AbstractIntelligenceAgent {
} catch(Exception e){ } catch(Exception e){
Logger.error( e.getMessage()); Logger.error( e.getMessage());
} }
mobPowers = DbManager.MobBaseQueries.LOAD_STATIC_POWERS(this.getMobBaseID());
if (this.equip == null) { if (this.equip == null) {
Logger.error("Null equipset returned for uuid " + currentID); Logger.error("Null equipset returned for uuid " + currentID);
this.equip = new HashMap<>(0); this.equip = new HashMap<>(0);

5
src/engine/objects/PlayerCharacter.java

@ -4781,8 +4781,11 @@ public void dismissNecroPets() {
}finally{ }finally{
this.updateLock.writeLock().unlock(); this.updateLock.writeLock().unlock();
} }
} //temp removal
if(AbstractCharacter.CanFly(this) == false && this.altitude > 0)
GroundPlayer(this);
}
} }
@Override @Override
public void updateFlight() { public void updateFlight() {

171
src/engine/powers/poweractions/AbstractPowerAction.java

@ -76,75 +76,108 @@ public abstract class AbstractPowerAction {
int token = DbManager.hasher.SBStringHash(IDString); int token = DbManager.hasher.SBStringHash(IDString);
//cache token, used for applying effects. //cache token, used for applying effects.
PowersManager.ActionTokenByIDString.put(IDString, token); PowersManager.ActionTokenByIDString.put(IDString, token);
if (type.equals("ApplyEffect")) apa = null;
apa = new ApplyEffectPowerAction(rs, effects); switch (type)
else if (type.equals("ApplyEffects")) {
apa = new ApplyEffectsPowerAction(rs, effects); default:
else if (type.equals("DeferredPower")) Logger.error("valid type not found for poweraction of ID" + rs.getInt("ID"));
apa = new DeferredPowerPowerAction(rs, effects); break;
else if (type.equals("DamageOverTime")) case "ApplyEffect":
apa = new DamageOverTimePowerAction(rs, effects); apa = new ApplyEffectPowerAction(rs, effects);
else if (type.equals("Peek")) break;
apa = new PeekPowerAction(rs); case "ApplyEffects":
else if (type.equals("Charm")) apa = new ApplyEffectsPowerAction(rs, effects);
apa = new CharmPowerAction(rs); break;
else if (type.equals("Fear")) case "DeferredPower":
apa = new FearPowerAction(rs); apa = new DeferredPowerPowerAction(rs, effects);
else if (type.equals("Confusion")) break;
apa = new ConfusionPowerAction(rs); case "DamageOverTime":
else if (type.equals("RemoveEffect")) apa = new DamageOverTimePowerAction(rs, effects);
apa = new RemoveEffectPowerAction(rs); break;
else if (type.equals("Track")) case "Peek":
apa = new TrackPowerAction(rs, effects); apa = new PeekPowerAction(rs);
else if (type.equals("DirectDamage")) break;
apa = new DirectDamagePowerAction(rs, effects); case "Charm":
else if (type.equals("Transform")) apa = new CharmPowerAction(rs);
apa = new TransformPowerAction(rs, effects); break;
else if (type.equals("CreateMob")) case "Fear":
apa = new CreateMobPowerAction(rs); apa = new FearPowerAction(rs);
else if (type.equals("Invis")) break;
apa = new InvisPowerAction(rs, effects); case "Confusion":
else if (type.equals("ClearNearbyAggro")) apa = new ConfusionPowerAction(rs);
apa = new ClearNearbyAggroPowerAction(rs); break;
else if (type.equals("MobRecall")) case "RemoveEffect":
apa = new MobRecallPowerAction(rs); apa = new RemoveEffectPowerAction(rs);
else if (type.equals("SetItemFlag")) break;
apa = new SetItemFlagPowerAction(rs); case "Track":
else if (type.equals("SimpleDamage")) apa = new TrackPowerAction(rs, effects);
apa = new SimpleDamagePowerAction(rs); break;
else if (type.equals("TransferStatOT")) case "DirectDamage":
apa = new TransferStatOTPowerAction(rs, effects); apa = new DirectDamagePowerAction(rs, effects);
else if (type.equals("TransferStat")) break;
apa = new TransferStatPowerAction(rs, effects); case "Transform":
else if (type.equals("Teleport")) apa = new TransformPowerAction(rs, effects);
apa = new TeleportPowerAction(rs); break;
else if (type.equals("TreeChoke")) case "CreateMob":
apa = new TreeChokePowerAction(rs); apa = new CreateMobPowerAction(rs);
else if (type.equals("Block")) break;
apa = new BlockPowerAction(rs); case "Invis":
else if (type.equals("Resurrect")) apa = new InvisPowerAction(rs, effects);
apa = new ResurrectPowerAction(rs); break;
else if (type.equals("ClearAggro")) case "ClearNearbyAggro":
apa = new ClearAggroPowerAction(rs); apa = new ClearNearbyAggroPowerAction(rs);
else if (type.equals("ClaimMine")) break;
apa = new ClaimMinePowerAction(rs); case "MobRecall":
else if (type.equals("Recall")) apa = new MobRecallPowerAction(rs);
apa = new RecallPowerAction(rs); break;
else if (type.equals("SpireDisable")) case "SetItemFlag":
apa = new SpireDisablePowerAction(rs); apa = new SetItemFlagPowerAction(rs);
else if (type.equals("Steal")) break;
apa = new StealPowerAction(rs); case "SimpleDamage":
else if (type.equals("Summon")) apa = new SimpleDamagePowerAction(rs);
apa = new SummonPowerAction(rs); break;
else if (type.equals("RunegateTeleport")) case "TransferStatOT":
apa = new RunegateTeleportPowerAction(rs); apa = new TransferStatOTPowerAction(rs, effects);
else if (type.equals("RunegateTeleport")) break;
apa = new RunegateTeleportPowerAction(rs); case "TransferStat":
else if (type.equals("OpenGate")) apa = new TransferStatPowerAction(rs, effects);
apa = new OpenGatePowerAction(rs); break;
else { case "Teleport":
Logger.error("valid type not found for poweraction of ID" + rs.getInt("ID")); apa = new TeleportPowerAction(rs);
continue; break;
case "TreeChoke":
apa = new TreeChokePowerAction(rs);
break;
case "Block":
apa = new BlockPowerAction(rs);
break;
case "Resurrect":
apa = new ResurrectPowerAction(rs);
break;
case "ClearAggro":
apa = new ClearAggroPowerAction(rs);
break;
case "ClaimMine":
apa = new ClaimMinePowerAction(rs);
break;
case "Recall":
apa = new RecallPowerAction(rs);
break;
case "SpireDisable":
apa = new SpireDisablePowerAction(rs);
break;
case "Steal":
apa = new StealPowerAction(rs);
break;
case "Summon":
apa = new SummonPowerAction(rs);
break;
case "RunegateTeleport":
apa = new RunegateTeleportPowerAction(rs);
break;
case "OpenGate":
apa = new OpenGatePowerAction(rs);
break;
} }
powerActions.put(IDString, apa); powerActions.put(IDString, apa);
powerActionsByID.put(apa.UUID, apa); powerActionsByID.put(apa.UUID, apa);

10
src/engine/server/MBServerStatics.java

@ -124,16 +124,6 @@ public class MBServerStatics {
public static final int CHM_THREAD_MED = 2; public static final int CHM_THREAD_MED = 2;
public static final int CHM_THREAD_LOW = 1; public static final int CHM_THREAD_LOW = 1;
/*
* LoginServer related
*/
public static final String PCMajorVer = "1.2.25.5";
public static final String PCMinorVer = "5.25.5";
public static final String MACMajorVer = "1.2.24.3";
public static final String MACMinorVer = "5.24.3";
/* /*
* LoginErrorMsg related * LoginErrorMsg related
*/ */

4
src/engine/server/login/LoginServer.java

@ -169,8 +169,8 @@ public class LoginServer {
// Configure the VersionInfoMsgs: // Configure the VersionInfoMsgs:
this.versionInfoMessage = new VersionInfoMsg(MBServerStatics.PCMajorVer, this.versionInfoMessage = new VersionInfoMsg(ConfigManager.MB_MAJOR_VER.getValue(),
MBServerStatics.PCMinorVer); ConfigManager.MB_MINOR_VER.getValue());
Logger.info("Initializing Database Pool"); Logger.info("Initializing Database Pool");
initDatabasePool(); initDatabasePool();

2
src/engine/server/login/LoginServerMsgHandler.java

@ -180,7 +180,7 @@ public class LoginServerMsgHandler implements NetMsgHandler {
if (account == null) { if (account == null) {
if (ConfigManager.MB_LOGIN_AUTOREG.getValue().equals("FALSE")) { if (ConfigManager.MB_LOGIN_AUTOREG.getValue().equalsIgnoreCase("false")) {
this.KickToLogin(MBServerStatics.LOGINERROR_INVALID_USERNAME_PASSWORD, "Could not find account (" + uname + ')', clientConnection); this.KickToLogin(MBServerStatics.LOGINERROR_INVALID_USERNAME_PASSWORD, "Could not find account (" + uname + ')', clientConnection);
Logger.info("Could not find account (" + uname + ')'); Logger.info("Could not find account (" + uname + ')');
return; return;

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

@ -53,7 +53,9 @@ import org.pmw.tinylog.labelers.TimestampLabeler;
import org.pmw.tinylog.policies.StartupPolicy; import org.pmw.tinylog.policies.StartupPolicy;
import org.pmw.tinylog.writers.RollingFileWriter; import org.pmw.tinylog.writers.RollingFileWriter;
import java.io.*; import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;

60
src/engine/util/MiscUtils.java

@ -9,27 +9,19 @@
package engine.util; package engine.util;
import engine.gameManager.ConfigManager;
import engine.server.MBServerStatics; import engine.server.MBServerStatics;
import java.util.regex.Pattern;
public class MiscUtils { public class MiscUtils {
// no need to recompile these each call, put them in object scope and
// compile just once.
private static final Pattern lastNameRegex = Pattern
.compile("^[A-Za-z][-'A-Za-z\\x20]*$");
private static final Pattern firstNameRegex = Pattern
.compile("^[A-Za-z]+$");
public static boolean checkIfFirstNameInvalid(String firstName) { public static boolean checkIfFirstNameInvalid(String firstName) {
if ((firstName == null) || (firstName.length() == 0) if ((firstName == null) || (firstName.length() == 0)
|| (firstName.length() > MBServerStatics.MAX_NAME_LENGTH) || (firstName.length() > MBServerStatics.MAX_NAME_LENGTH)
|| (firstName.length() < MBServerStatics.MIN_NAME_LENGTH)) { || (firstName.length() < MBServerStatics.MIN_NAME_LENGTH)) {
return true; return true;
} }
return (!firstNameRegex.matcher(firstName).matches()); return (!ConfigManager.regex.get(ConfigManager.MB_LOGIN_FNAME_REGEX).matcher(firstName).matches());
} }
public static boolean checkIfLastNameInvalid(String lastName) { public static boolean checkIfLastNameInvalid(String lastName) {
@ -43,52 +35,4 @@ public class MiscUtils {
// empty last names are fine, return false // empty last names are fine, return false
return false; return false;
} }
public static String getCallingMethodName() {
StackTraceElement e[] = Thread.currentThread().getStackTrace();
int numElements = e.length;
if (numElements < 1) {
return "NoStack";
}
if (numElements == 1) {
return e[0].getMethodName();
} else if (numElements == 2) {
return e[1].getMethodName();
} else if (numElements == 3) {
return e[2].getMethodName();
} else {
return e[3].getMethodName();
}
}
public static String getCallStackAsString() {
String out = "";
StackTraceElement e[] = Thread.currentThread().getStackTrace();
int numElements = e.length;
for (int i = (numElements - 1); i > 1; --i) {
String[] classStack = e[i].getClassName().split("\\.");
String methName = e[i].getMethodName();
String className = classStack[classStack.length - 1];
if (methName.equals("<init>")) {
methName = className;
}
out += className + '.' + methName + "()";
if (i > 2) {
out += " -> ";
}
}
return out;
}
} }

Loading…
Cancel
Save