diff --git a/pswgcommon b/pswgcommon
index d08a091fd..9f0e9fd4f 160000
--- a/pswgcommon
+++ b/pswgcommon
@@ -1 +1 @@
-Subproject commit d08a091fd478c342071b948dd5d05074dfb2c2bc
+Subproject commit 9f0e9fd4fa35fee8be34c4b7bc083e2408ceb709
diff --git a/src/display/java/com/projectswg/holocore/display/ResourceSpawnViewer.java b/src/display/java/com/projectswg/holocore/display/ResourceSpawnViewer.java
deleted file mode 100644
index de58cb3b6..000000000
--- a/src/display/java/com/projectswg/holocore/display/ResourceSpawnViewer.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/***********************************************************************************
- * Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
- * *
- * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
- * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
- * Our goal is to create an emulator which will provide a server for players to *
- * continue playing a game similar to the one they used to play. We are basing *
- * it on the final publish of the game prior to end-game events. *
- * *
- * This file is part of Holocore. *
- * *
- * --------------------------------------------------------------------------------*
- * *
- * Holocore is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU Affero General Public License as *
- * published by the Free Software Foundation, either version 3 of the *
- * License, or (at your option) any later version. *
- * *
- * Holocore is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU Affero General Public License for more details. *
- * *
- * You should have received a copy of the GNU Affero General Public License *
- * along with Holocore. If not, see . *
- ***********************************************************************************/
-package com.projectswg.holocore.display;
-
-import com.projectswg.common.data.location.Terrain;
-import com.projectswg.holocore.resources.gameplay.crafting.resource.galactic.GalacticResourceLoader;
-import com.projectswg.holocore.resources.gameplay.crafting.resource.galactic.GalacticResourceSpawn;
-import javafx.application.Application;
-import javafx.collections.FXCollections;
-import javafx.embed.swing.SwingFXUtils;
-import javafx.scene.Scene;
-import javafx.scene.canvas.Canvas;
-import javafx.scene.canvas.GraphicsContext;
-import javafx.scene.control.Button;
-import javafx.scene.control.ComboBox;
-import javafx.scene.image.WritableImage;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.VBox;
-import javafx.scene.paint.Color;
-import javafx.stage.Stage;
-
-import javax.imageio.ImageIO;
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
-public class ResourceSpawnViewer extends Application {
-
- private static final int MAP_SIZE = 16384;
- private static final double POSITION_GAUSSIAN_FACTOR = MAP_SIZE / 2 * Math.sqrt(2);
- private static final int STAGE_SIZE = 800;
-
- private static final Terrain [] ALL_PLANETS = new Terrain[] {
- Terrain.CORELLIA, Terrain.DANTOOINE, Terrain.DATHOMIR,
- Terrain.ENDOR, Terrain.KASHYYYK_MAIN, Terrain.LOK,
- Terrain.MUSTAFAR, Terrain.NABOO, Terrain.RORI,
- Terrain.TALUS, Terrain.TATOOINE, Terrain.YAVIN4
- };
- private static final Color [] COLORS = new Color[] {
- Color.BLACK, Color.LIGHTGRAY, Color.BLUE, Color.MAGENTA,
- Color.CYAN, Color.ORANGE, Color.DARKGRAY, Color.PINK, Color.GRAY,
- Color.RED, Color.GREEN, Color.YELLOW
- };
-
- private ComboBox terrainCombo;
- private Button saveButton;
- private Canvas resourceCanvas;
-
- public static void main(String [] args) {
- Application.launch(args);
- }
-
- @Override
- public void start(Stage primaryStage) {
- VBox root = new VBox();
- HBox topPanel = new HBox();
- root.getChildren().add(topPanel);
- root.getChildren().add(resourceCanvas = new Canvas(800, 800));
- topPanel.getChildren().add(terrainCombo = new ComboBox<>());
- topPanel.getChildren().add(saveButton = new Button("Save"));
- setupTopPanel();
- primaryStage.setScene(new Scene(root, STAGE_SIZE, STAGE_SIZE + 20));
- primaryStage.show();
- }
-
- private void setupTopPanel() {
- terrainCombo.setItems(FXCollections.observableArrayList(ALL_PLANETS));
- terrainCombo.valueProperty().addListener((val, o, n) -> onTerrainChanged(n));
- terrainCombo.setValue(Terrain.TATOOINE);
- saveButton.setOnAction(e -> save());
- }
-
- private void save() {
- WritableImage writableImage = new WritableImage(STAGE_SIZE, STAGE_SIZE);
- resourceCanvas.snapshot(null, writableImage);
- try {
- ImageIO.write(SwingFXUtils.fromFXImage(writableImage, null), "png", new File("resource_spawns.png"));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- private void onTerrainChanged(Terrain terrain) {
- GraphicsContext gc = resourceCanvas.getGraphicsContext2D();
- gc.clearRect(0, 0, STAGE_SIZE, STAGE_SIZE);
- for (int x = 0; x < STAGE_SIZE/2; x++) {
- for (int y = 0; y < STAGE_SIZE/2; y++) {
- double dist = Math.sqrt(Math.pow(STAGE_SIZE/2-x, 2)+Math.pow(STAGE_SIZE/2-y, 2));
- double opacity = getProbabilityOpacity(dist/STAGE_SIZE*MAP_SIZE);
- gc.setStroke(new Color(0, 0, 0, opacity * 0.75));
- gc.strokeLine(x, y, x, y);
- gc.strokeLine(STAGE_SIZE-x, STAGE_SIZE-y, STAGE_SIZE-x, STAGE_SIZE-y);
- gc.strokeLine(STAGE_SIZE-x, y, STAGE_SIZE-x, y);
- gc.strokeLine(x, STAGE_SIZE-y, x, STAGE_SIZE-y);
- }
- }
- GalacticResourceLoader loader = new GalacticResourceLoader();
- List spawns = loader.loadSpawns();
- int index = 0;
- for (GalacticResourceSpawn spawn : spawns) {
- if (spawn.getTerrain() != terrain)
- continue;
- Color c = COLORS[(index++) % COLORS.length];
- gc.setFill(c.deriveColor(0, 1, 1, 0.7));
- double x = convertToStage(spawn.getX());
- double z = convertToStage(spawn.getZ());
- double width = (double) spawn.getRadius() / (MAP_SIZE/2) * STAGE_SIZE;
- gc.fillOval(x-width/2, STAGE_SIZE-z-width/2, width, width);
- gc.setFill(Color.BLACK);
- gc.fillText(Long.toString(spawn.getResourceId()), convertToStage(spawn.getX()) - getHorizontalShift(spawn.getResourceId()), STAGE_SIZE-convertToStage(spawn.getZ())+5);
- }
- }
-
- private int convertToStage(double x) {
- return (int) (x / (MAP_SIZE/2) * STAGE_SIZE/2) + STAGE_SIZE/2;
- }
-
-
- private int getHorizontalShift(long resourceId) {
- if (resourceId < 10)
- return 4;
- if (resourceId < 100)
- return 8;
- return 12;
- }
-
- private double getProbabilityOpacity(double dist) {
- return getGaussianY(((dist / POSITION_GAUSSIAN_FACTOR) - 0.5) * 6);
- }
-
- private double getGaussianY(double x) {
- return Math.pow(Math.exp(-((x * x) / 2)), 1 / (Math.sqrt(2 * Math.PI)));
- }
-
-}
diff --git a/src/integration/java/com/projectswg/holocore/ProjectSWGRunner.java b/src/integration/java/com/projectswg/holocore/ProjectSWGRunner.java
index 9e5b9c5b0..023e94c4d 100644
--- a/src/integration/java/com/projectswg/holocore/ProjectSWGRunner.java
+++ b/src/integration/java/com/projectswg/holocore/ProjectSWGRunner.java
@@ -1,7 +1,7 @@
package com.projectswg.holocore;
-import com.projectswg.connection.HolocoreSocket;
-import com.projectswg.connection.ServerConnectionChangedReason;
+import com.projectswg.common.network.packets.swg.holo.HoloConnectionStopped.ConnectionStoppedReason;
+import com.projectswg.holocore.client.HolocoreSocket;
import me.joshlarson.jlcommon.concurrency.BasicThread;
import me.joshlarson.jlcommon.concurrency.Delay;
@@ -18,25 +18,25 @@ public class ProjectSWGRunner {
public void start() {
runner.start();
{
- HolocoreSocket socket = new HolocoreSocket(InetAddress.getLoopbackAddress(), 44463);
- long start = System.nanoTime();
- boolean connected = false;
- while (System.nanoTime() - start <= 60E9) { // 60s max wait
- connected = socket.getServerStatus().equals("UP");
- if (connected)
- break;
- Delay.sleepSeconds(1);
- }
- if (connected) {
- start = System.nanoTime();
+ try (HolocoreSocket socket = new HolocoreSocket(InetAddress.getLoopbackAddress(), 44463)) {
+ long start = System.nanoTime();
+ boolean connected = false;
while (System.nanoTime() - start <= 60E9) { // 60s max wait
- if (socket.connect(1000)) {
- socket.disconnect(ServerConnectionChangedReason.CLIENT_DISCONNECT);
+ connected = socket.getServerStatus().equals("UP");
+ if (connected)
break;
+ Delay.sleepSeconds(1);
+ }
+ if (connected) {
+ start = System.nanoTime();
+ while (System.nanoTime() - start <= 60E9) { // 60s max wait
+ if (socket.connect(1000)) {
+ socket.disconnect(ConnectionStoppedReason.NETWORK);
+ break;
+ }
}
}
}
- socket.terminate();
}
}
diff --git a/src/integration/java/com/projectswg/holocore/integration/resources/HolocoreClient.java b/src/integration/java/com/projectswg/holocore/integration/resources/HolocoreClient.java
index 4efb7827e..b100fadcb 100644
--- a/src/integration/java/com/projectswg/holocore/integration/resources/HolocoreClient.java
+++ b/src/integration/java/com/projectswg/holocore/integration/resources/HolocoreClient.java
@@ -6,6 +6,7 @@ import com.projectswg.common.data.location.Terrain;
import com.projectswg.common.network.NetBuffer;
import com.projectswg.common.network.packets.PacketType;
import com.projectswg.common.network.packets.SWGPacket;
+import com.projectswg.common.network.packets.swg.holo.HoloConnectionStopped.ConnectionStoppedReason;
import com.projectswg.common.network.packets.swg.holo.login.HoloLoginRequestPacket;
import com.projectswg.common.network.packets.swg.holo.login.HoloLoginResponsePacket;
import com.projectswg.common.network.packets.swg.login.EnumerateCharacterId.SWGCharacter;
@@ -15,9 +16,8 @@ import com.projectswg.common.network.packets.swg.zone.SceneEndBaselines;
import com.projectswg.common.network.packets.swg.zone.baselines.Baseline;
import com.projectswg.common.network.packets.swg.zone.insertion.CmdStartScene;
import com.projectswg.common.network.packets.swg.zone.insertion.SelectCharacter;
-import com.projectswg.connection.HolocoreSocket;
-import com.projectswg.connection.RawPacket;
-import com.projectswg.connection.ServerConnectionChangedReason;
+import com.projectswg.holocore.client.HolocoreSocket;
+import com.projectswg.holocore.client.RawPacket;
import com.projectswg.holocore.resources.support.objects.ObjectCreator;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import me.joshlarson.jlcommon.concurrency.BasicThread;
@@ -26,9 +26,7 @@ import org.junit.Assert;
import java.net.InetSocketAddress;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Objects;
-import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
@@ -107,8 +105,8 @@ public class HolocoreClient {
public void disconnect() {
listenThread.stop(false);
- socket.disconnect(ServerConnectionChangedReason.CLIENT_DISCONNECT);
- socket.terminate();
+ socket.disconnect(ConnectionStoppedReason.APPLICATION);
+ socket.close();
listenThread.awaitTermination(1000);
}
diff --git a/src/main/java/com/projectswg/holocore/ProjectSWG.java b/src/main/java/com/projectswg/holocore/ProjectSWG.java
index 71938bdb1..821c635fc 100644
--- a/src/main/java/com/projectswg/holocore/ProjectSWG.java
+++ b/src/main/java/com/projectswg/holocore/ProjectSWG.java
@@ -56,7 +56,7 @@ import java.util.*;
public class ProjectSWG {
- public static final String VERSION = "DEC18";
+ public static final String VERSION = "FEB19";
private static final Galaxy GALAXY = new Galaxy();
diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/combat/buff/BuffData.java b/src/main/java/com/projectswg/holocore/resources/gameplay/combat/buff/BuffData.java
deleted file mode 100644
index c9b78ba4e..000000000
--- a/src/main/java/com/projectswg/holocore/resources/gameplay/combat/buff/BuffData.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/***********************************************************************************
- * Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
- * *
- * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
- * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
- * Our goal is to create an emulator which will provide a server for players to *
- * continue playing a game similar to the one they used to play. We are basing *
- * it on the final publish of the game prior to end-game events. *
- * *
- * This file is part of Holocore. *
- * *
- * --------------------------------------------------------------------------------*
- * *
- * Holocore is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU Affero General Public License as *
- * published by the Free Software Foundation, either version 3 of the *
- * License, or (at your option) any later version. *
- * *
- * Holocore is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU Affero General Public License for more details. *
- * *
- * You should have received a copy of the GNU Affero General Public License *
- * along with Holocore. If not, see . *
- ***********************************************************************************/
-package com.projectswg.holocore.resources.gameplay.combat.buff;
-
-import com.projectswg.common.data.CRC;
-import me.joshlarson.jlcommon.utilities.Arguments;
-
-import java.util.Locale;
-
-public class BuffData {
-
- private final int crc;
- private final String name;
- private final String groupName;
- private final int groupPriority;
- private final String [] effectNames;
- private final float [] effectValues;
-
- private int maxStackCount;
- private float defaultDuration;
- private String effectFileName;
- private String particleHardPoint;
- private String stanceParticle;
- private String callback;
- private boolean persistent;
- private boolean removedOnDeath;
- private boolean decayOnPvpDeath;
-
- public BuffData(String name, String groupName, int groupPriority) {
- this.crc = CRC.getCrc(name.toLowerCase(Locale.ENGLISH));
- this.name = name;
- this.groupName = groupName;
- this.groupPriority = groupPriority;
- this.effectNames = new String[5];
- this.effectValues = new float[5];
- }
-
- public int getCrc() {
- return crc;
- }
-
- public String getName() {
- return name;
- }
-
- public String getGroupName() {
- return groupName;
- }
-
- public int getGroupPriority() {
- return groupPriority;
- }
-
- public int getMaxStackCount() {
- return maxStackCount;
- }
-
- public String getEffectName(int effect) {
- Arguments.validate(effect >= 0 && effect < 5, "Effect # must be in range: [0, 5)");
- return effectNames[effect];
- }
-
- public float getEffectValue(int effect) {
- Arguments.validate(effect >= 0 && effect < 5, "Effect # must be in range: [0, 5)");
- return effectValues[effect];
- }
-
- public float getDefaultDuration() {
- return defaultDuration;
- }
-
- public String getEffectFileName() {
- return effectFileName;
- }
-
- public String getParticleHardPoint() {
- return particleHardPoint;
- }
-
- public String getStanceParticle() {
- return stanceParticle;
- }
-
- public String getCallback() {
- return callback;
- }
-
- public boolean isPersistent() {
- return persistent;
- }
-
- public boolean isRemovedOnDeath() {
- return removedOnDeath;
- }
-
- public boolean isDecayOnPvpDeath() {
- return decayOnPvpDeath;
- }
-
- public void setMaxStackCount(int maxStackCount) {
- this.maxStackCount = maxStackCount;
- }
-
- public void setEffectName(int effect, String name) {
- Arguments.validate(effect >= 0 && effect < 5, "Effect # must be in range: [0, 5)");
- effectNames[effect] = name;
- }
-
- public void setEffectValue(int effect, float value) {
- Arguments.validate(effect >= 0 && effect < 5, "Effect # must be in range: [0, 5)");
- effectValues[effect] = value;
- }
-
- public void setDefaultDuration(float defaultDuration) {
- this.defaultDuration = defaultDuration;
- }
-
- public void setEffectFileName(String effectFileName) {
- this.effectFileName = effectFileName;
- }
-
- public void setParticleHardPoint(String particleHardPoint) {
- this.particleHardPoint = particleHardPoint;
- }
-
- public void setStanceParticle(String stanceParticle) {
- this.stanceParticle = stanceParticle;
- }
-
- public void setCallback(String callback) {
- this.callback = callback;
- }
-
- public void setPersistent(boolean persistent) {
- this.persistent = persistent;
- }
-
- public void setRemovedOnDeath(boolean removedOnDeath) {
- this.removedOnDeath = removedOnDeath;
- }
-
- public void setDecayOnPvpDeath(boolean decayOnPvpDeath) {
- this.decayOnPvpDeath = decayOnPvpDeath;
- }
-
-}
diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/combat/buff/BuffMap.java b/src/main/java/com/projectswg/holocore/resources/gameplay/combat/buff/BuffMap.java
deleted file mode 100644
index 2ba5b074d..000000000
--- a/src/main/java/com/projectswg/holocore/resources/gameplay/combat/buff/BuffMap.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/***********************************************************************************
- * Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
- * *
- * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
- * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
- * Our goal is to create an emulator which will provide a server for players to *
- * continue playing a game similar to the one they used to play. We are basing *
- * it on the final publish of the game prior to end-game events. *
- * *
- * This file is part of Holocore. *
- * *
- * --------------------------------------------------------------------------------*
- * *
- * Holocore is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU Affero General Public License as *
- * published by the Free Software Foundation, either version 3 of the *
- * License, or (at your option) any later version. *
- * *
- * Holocore is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU Affero General Public License for more details. *
- * *
- * You should have received a copy of the GNU Affero General Public License *
- * along with Holocore. If not, see . *
- ***********************************************************************************/
-package com.projectswg.holocore.resources.gameplay.combat.buff;
-
-import com.projectswg.common.data.CRC;
-import com.projectswg.common.data.swgfile.ClientFactory;
-import com.projectswg.common.data.swgfile.visitors.DatatableData;
-
-import java.util.Locale;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class BuffMap {
-
- private final Map buffMap;
-
- public BuffMap() {
- this.buffMap = new ConcurrentHashMap<>();
- }
-
- public void load() {
- DatatableData buffTable = (DatatableData) ClientFactory.getInfoFromFile("datatables/buff/buff.iff");
- int rows = buffTable.getRowCount();
-
- buffMap.clear();
- for (int row = 0; row < rows; ++row) {
- BuffData buff = new BuffData(buffTable.getString(row, "NAME"), buffTable.getString(row, "GROUP1"), buffTable.getInt(row, "PRIORITY"));
- buff.setMaxStackCount(buffTable.getInt(row, "MAX_STACKS"));
- for (int i = 0; i < 5; i++) {
- buff.setEffectName(i, buffTable.getString(row, "EFFECT"+(i+1)+"_PARAM"));
- buff.setEffectValue(i, buffTable.getFloat(row, "EFFECT"+(i+1)+"_VALUE"));
- }
- buff.setDefaultDuration(buffTable.getFloat(row, "DURATION"));
- buff.setEffectFileName(buffTable.getString(row, "PARTICLE"));
- buff.setParticleHardPoint(buffTable.getString(row, "PARTICLE_HARDPOINT"));
- buff.setStanceParticle(buffTable.getString(row, "STANCE_PARTICLE"));
- buff.setCallback(buffTable.getString(row, "CALLBACK"));
- buff.setPersistent(buffTable.getInt(row, "IS_PERSISTENT") == 1);
- buff.setRemovedOnDeath(buffTable.getInt(row, "REMOVE_ON_DEATH") == 1);
- buff.setDecayOnPvpDeath(buffTable.getInt(row, "DECAY_ON_PVP_DEATH") == 1);
- buffMap.put(buff.getCrc(), buff);
- }
- }
-
- public int size() {
- return buffMap.size();
- }
-
- public BuffData getBuff(int crc) {
- return buffMap.get(crc);
- }
-
- public BuffData getBuff(CRC crc) {
- return getBuff(crc.getCrc());
- }
-
- public BuffData getBuff(String name) {
- return getBuff(getCrc(name));
- }
-
- public boolean containsBuff(int crc) {
- return buffMap.containsKey(crc);
- }
-
- public boolean containsBuff(String name) {
- return containsBuff(getCrc(name));
- }
-
- private int getCrc(String name) {
- return CRC.getCrc(name.toLowerCase(Locale.ENGLISH));
- }
-
-}
diff --git a/src/main/java/com/projectswg/holocore/resources/gameplay/world/travel/TravelHelper.java b/src/main/java/com/projectswg/holocore/resources/gameplay/world/travel/TravelHelper.java
index dc9e6a7a4..ee3810d40 100644
--- a/src/main/java/com/projectswg/holocore/resources/gameplay/world/travel/TravelHelper.java
+++ b/src/main/java/com/projectswg/holocore/resources/gameplay/world/travel/TravelHelper.java
@@ -31,8 +31,6 @@ import com.projectswg.common.data.encodables.oob.StringId;
import com.projectswg.common.data.info.Config;
import com.projectswg.common.data.location.Location;
import com.projectswg.common.data.location.Terrain;
-import com.projectswg.common.data.swgfile.ClientFactory;
-import com.projectswg.common.data.swgfile.visitors.DatatableData;
import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent;
import com.projectswg.holocore.intents.support.objects.swg.DestroyObjectIntent;
import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent;
@@ -41,6 +39,7 @@ import com.projectswg.holocore.resources.support.data.config.ConfigFile;
import com.projectswg.holocore.resources.support.data.server_info.DataManager;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet;
+import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.objects.SpecificObject;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
@@ -60,16 +59,13 @@ public class TravelHelper {
private final Map travel;
private final ThreadPool travelExecutor;
- private final AllowedRouteManager routeManager;
private final TravelPointManager pointManager;
public TravelHelper() {
this.travel = new ConcurrentHashMap<>();
this.travelExecutor = new ThreadPool(3, "travel-shuttles-%d");
- this.routeManager = new AllowedRouteManager();
this.pointManager = new TravelPointManager();
- loadAllowedRoutesAndPrices();
createGalaxyTravels();
loadTravelPoints();
}
@@ -89,11 +85,11 @@ public class TravelHelper {
}
public boolean isValidRoute(Terrain departure, Terrain destination) {
- return routeManager.isRouteAvailable(departure, destination);
+ return getTravelFee(departure, destination) != 0;
}
public int getTravelFee(Terrain departure, Terrain destination) {
- return routeManager.getRouteFee(departure, destination);
+ return DataLoader.travelCosts().getCost(departure, destination);
}
public TravelGroup getTravelGroup(String template) {
@@ -191,25 +187,6 @@ public class TravelHelper {
traveler.moveToContainer(destination.getCollector().getParent(), destination.getLocation());
}
- private void loadAllowedRoutesAndPrices() {
- DatatableData travelFeeTable = (DatatableData) ClientFactory.getInfoFromFile("datatables/travel/travel.iff");
- // Sets up the travelPlanets array to be in the order of the datatable
- Terrain [] travelPlanets = new Terrain[travelFeeTable.getRowCount()];
- travelFeeTable.handleRows(currentRow -> travelPlanets[currentRow] = Terrain.getTerrainFromName((String) travelFeeTable.getCell(currentRow, "Planet")));
-
- for (int rowIndex = 0; rowIndex < travelPlanets.length; rowIndex++) {
- for (int columnIndex = rowIndex; columnIndex < travelPlanets.length; columnIndex++) {
- int price = (int) travelFeeTable.getCell(rowIndex, columnIndex+1);
-
- if (price <= 0) // If price is below or equal to 0 then this is an invalid route and isn't an option.
- continue;
-
- routeManager.addRoute(travelPlanets[rowIndex], travelPlanets[columnIndex], price);
- routeManager.addRoute(travelPlanets[columnIndex], travelPlanets[rowIndex], price);
- }
- }
- }
-
private void createGalaxyTravels() {
Config config = DataManager.getConfig(ConfigFile.FEATURES);
long groundTime = config.getInt("SHUTTLE-GROUND-TIME", 120);
@@ -266,29 +243,4 @@ public class TravelHelper {
}
}
- private static class AllowedRouteManager {
-
- private final Map> routeCosts;
-
- public AllowedRouteManager() {
- this.routeCosts = new ConcurrentHashMap<>();
- }
-
- public void addRoute(Terrain departure, Terrain destination, int fee) {
- Map departureCosts = routeCosts.computeIfAbsent(departure, k -> new ConcurrentHashMap<>());
- departureCosts.put(destination, fee);
- }
-
- public boolean isRouteAvailable(Terrain departure, Terrain destination) {
- return routeCosts.get(departure) != null && routeCosts.get(departure).get(destination) != null;
- }
-
- public int getRouteFee(Terrain departure, Terrain destination) {
- Integer fee = routeCosts.get(departure).get(destination);
- if (fee == null)
- return 0;
- return fee;
- }
- }
-
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/location/InstanceLocation.java b/src/main/java/com/projectswg/holocore/resources/support/data/location/InstanceLocation.java
index 363b3e1ba..9d7e1103c 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/data/location/InstanceLocation.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/data/location/InstanceLocation.java
@@ -62,14 +62,14 @@ public class InstanceLocation implements Persistable, MongoPersistable {
}
@Override
- public void read(MongoData data) {
+ public void readMongo(MongoData data) {
instanceNumber = data.getInteger("number", 0);
instanceType = InstanceType.valueOf(data.getString("type", "NONE"));
location = data.getDocument("location", new Location());
}
@Override
- public void save(MongoData data) {
+ public void saveMongo(MongoData data) {
data.putInteger("number", instanceNumber);
data.putString("type", instanceType.name());
data.putDocument("location", location);
diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/persistable/SWGObjectFactory.java b/src/main/java/com/projectswg/holocore/resources/support/data/persistable/SWGObjectFactory.java
index 204b73efb..205fb06d2 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/data/persistable/SWGObjectFactory.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/data/persistable/SWGObjectFactory.java
@@ -39,8 +39,12 @@ public class SWGObjectFactory {
obj.save(stream);
}
+ public static MongoData save(SWGObject obj) {
+ return save(obj, new MongoData());
+ }
+
public static MongoData save(SWGObject obj, MongoData data) {
- obj.save(data);
+ obj.saveMongo(data);
assert data.containsKey("id") : "serialized MongoData does not contain the objectId";
assert data.containsKey("template") : "serialized MongoData does not contain the template";
return data;
@@ -60,7 +64,7 @@ public class SWGObjectFactory {
assert objectId != 0 : "objectId is not defined in MongoData";
assert template != null : "template is not defined in MongoData";
SWGObject obj = ObjectCreator.createObjectFromTemplate(objectId, template);
- obj.read(data);
+ obj.readMongo(data);
return obj;
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/BuffLoader.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/BuffLoader.java
new file mode 100644
index 000000000..56663f34a
--- /dev/null
+++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/BuffLoader.java
@@ -0,0 +1,271 @@
+/***********************************************************************************
+ * Copyright (c) 2019 /// Project SWG /// www.projectswg.com *
+ * *
+ * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
+ * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
+ * Our goal is to create an emulator which will provide a server for players to *
+ * continue playing a game similar to the one they used to play. We are basing *
+ * it on the final publish of the game prior to end-game events. *
+ * *
+ * This file is part of Holocore. *
+ * *
+ * --------------------------------------------------------------------------------*
+ * *
+ * Holocore is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU Affero General Public License as *
+ * published by the Free Software Foundation, either version 3 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * Holocore is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Affero General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Affero General Public License *
+ * along with Holocore. If not, see . *
+ ***********************************************************************************/
+
+package com.projectswg.holocore.resources.support.data.server_info.loader;
+
+import com.projectswg.common.data.CRC;
+import com.projectswg.holocore.resources.support.data.server_info.SdbColumnArraySet.SdbRealColumnArraySet;
+import com.projectswg.holocore.resources.support.data.server_info.SdbColumnArraySet.SdbTextColumnArraySet;
+import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
+import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+public final class BuffLoader extends DataLoader {
+
+ private final Map buffsByCrc;
+ private final Map buffsByName;
+
+ BuffLoader() {
+ this.buffsByCrc = new HashMap<>();
+ this.buffsByName = new HashMap<>();
+ }
+
+ @Nullable
+ public BuffInfo getBuff(int crc) {
+ return buffsByCrc.get(crc);
+ }
+
+ @Nullable
+ public BuffInfo getBuff(CRC crc) {
+ return getBuff(crc.getCrc());
+ }
+
+ @Nullable
+ public BuffInfo getBuff(String name) {
+ return buffsByName.get(name.toLowerCase(Locale.US));
+ }
+
+ public boolean containsBuff(int crc) {
+ return buffsByCrc.containsKey(crc);
+ }
+
+ public boolean containsBuff(String name) {
+ return buffsByName.containsKey(name.toLowerCase(Locale.US));
+ }
+
+ @Override
+ public final void load() throws IOException {
+ try (SdbResultSet set = SdbLoader.load(new File("serverdata/buff/buff.sdb"))) {
+ SdbTextColumnArraySet effectParams = set.getTextArrayParser("effect([0-9]+)_param");
+ SdbRealColumnArraySet effectValues = set.getRealArrayParser("effect([0-9]+)_value");
+ while (set.next()) {
+ BuffInfo buff = new BuffInfo(set, effectParams, effectValues);
+ buffsByCrc.put(buff.getCrc(), buff);
+ buffsByName.put(buff.getName(), buff);
+ }
+ }
+ }
+
+ public static class BuffInfo {
+
+ private final String name;
+ private final int crc;
+ private final String group1;
+ private final String group2;
+ private final String block;
+ private final int priority;
+ private final String icon;
+ private final double duration;
+ private final String [] effectNames;
+ private final double [] effectValues;
+ private final String state;
+ private final String callback;
+ private final String particle;
+ private final String particleHardpoint;
+ private final int visible;
+ private final boolean debuff;
+ private final String stanceParticle;
+ private final boolean dispellPlayer;
+ private final boolean removeOnDeath;
+ private final boolean playerRemovable;
+ private final boolean celestial;
+ private final int maxStackCount;
+ private final boolean persistent;
+ private final boolean displayOrder;
+ private final boolean removeOnRespec;
+ private final boolean aiRemoveOnCombatEnd;
+ private final boolean decayOnPvpDeath;
+
+ public BuffInfo(SdbResultSet set, SdbTextColumnArraySet effectNames, SdbRealColumnArraySet effectValues) {
+ this.name = set.getText("name").toLowerCase(Locale.US);
+ this.crc = CRC.getCrc(this.name);
+ this.group1 = set.getText("group1");
+ this.group2 = set.getText("group2");
+ this.block = set.getText("block");
+ this.priority = (int) set.getInt("priority");
+ this.icon = set.getText("icon");
+ this.duration = set.getReal("duration");
+ this.effectNames = effectNames.getArray().clone();
+ this.effectValues = effectValues.getArray().clone();
+ this.state = set.getText("state");
+ this.callback = set.getText("callback");
+ this.particle = set.getText("particle");
+ this.particleHardpoint = set.getText("particle_hardpoint");
+ this.visible = (int) set.getInt("visible");
+ this.debuff = set.getBoolean("debuff");
+ this.stanceParticle = set.getText("stance_particle");
+ this.dispellPlayer = set.getInt("dispell_player") != 0;
+ this.removeOnDeath = set.getInt("remove_on_death") != 0;
+ this.playerRemovable = set.getInt("player_removable") != 0;
+ this.celestial = set.getInt("is_celestial") != 0;
+ this.maxStackCount = (int) set.getInt("max_stacks");
+ this.persistent = set.getInt("is_persistent") != 0;
+ this.displayOrder = set.getInt("display_order") != 0;
+ this.removeOnRespec = set.getInt("remove_on_respec") != 0;
+ this.aiRemoveOnCombatEnd = set.getInt("ai_remove_on_combat_end") != 0;
+ this.decayOnPvpDeath = set.getInt("decay_on_pvp_death") != 0;
+
+ assert this.effectNames.length == this.effectValues.length : "effect params and effect values differ in size";
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getCrc() {
+ return crc;
+ }
+
+ public String getGroup1() {
+ return group1;
+ }
+
+ public String getGroup2() {
+ return group2;
+ }
+
+ public String getBlock() {
+ return block;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+
+ public double getDuration() {
+ return duration;
+ }
+
+ public String[] getEffectNames() {
+ return effectNames.clone();
+ }
+
+ public String getEffectName(int index) {
+ return effectNames[index];
+ }
+
+ public double[] getEffectValues() {
+ return effectValues.clone();
+ }
+
+ public double getEffectValue(int index) {
+ return effectValues[index];
+ }
+
+ public int getEffects() {
+ return effectNames.length;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public String getCallback() {
+ return callback;
+ }
+
+ public String getParticle() {
+ return particle;
+ }
+
+ public String getParticleHardpoint() {
+ return particleHardpoint;
+ }
+
+ public int getVisible() {
+ return visible;
+ }
+
+ public boolean isDebuff() {
+ return debuff;
+ }
+
+ public String getStanceParticle() {
+ return stanceParticle;
+ }
+
+ public boolean isDispellPlayer() {
+ return dispellPlayer;
+ }
+
+ public boolean isRemoveOnDeath() {
+ return removeOnDeath;
+ }
+
+ public boolean isPlayerRemovable() {
+ return playerRemovable;
+ }
+
+ public boolean isCelestial() {
+ return celestial;
+ }
+
+ public int getMaxStackCount() {
+ return maxStackCount;
+ }
+
+ public boolean isPersistent() {
+ return persistent;
+ }
+
+ public boolean isDisplayOrder() {
+ return displayOrder;
+ }
+
+ public boolean isRemoveOnRespec() {
+ return removeOnRespec;
+ }
+
+ public boolean isAiRemoveOnCombatEnd() {
+ return aiRemoveOnCombatEnd;
+ }
+
+ public boolean isDecayOnPvpDeath() {
+ return decayOnPvpDeath;
+ }
+ }
+}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/CachedLoader.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/CachedLoader.java
index 2419f669c..6327887a1 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/CachedLoader.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/CachedLoader.java
@@ -8,6 +8,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
enum CachedLoader {
+ BUFFS (BuffLoader::new),
BUILDING_CELLS (BuildingCellLoader::new),
NPC_LOADER (NpcLoader::new),
NPC_COMBAT_PROFILES (NpcCombatProfileLoader::new),
@@ -17,10 +18,12 @@ enum CachedLoader {
NPC_WEAPON_RANGES (NpcWeaponRangeLoader::new),
STATIC_SPAWNS (NpcStaticSpawnLoader::new),
OBJECT_DATA (ObjectDataLoader::new),
+ PERFORMANCES (PerformanceLoader::new),
COMMANDS (CommandLoader::new),
SLOT_DEFINITIONS (SlotDefinitionLoader::new),
ZONE_INSERTIONS (TerrainZoneInsertionLoader::new),
- VEHICLES (VehicleLoader::new);
+ VEHICLES (VehicleLoader::new),
+ TRAVEL_COSTS (TravelCostLoader::new);
private final AtomicReference> cachedLoader;
private final Supplier supplier;
diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/DataLoader.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/DataLoader.java
index 3b86d2cb0..56e0e6ea0 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/DataLoader.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/DataLoader.java
@@ -18,6 +18,10 @@ public abstract class DataLoader {
}
}
+ public static BuffLoader buffs() {
+ return (BuffLoader) CachedLoader.BUFFS.load();
+ }
+
public static BuildoutLoader buildouts() {
return BuildoutLoader.load(List.of());
}
@@ -66,6 +70,10 @@ public abstract class DataLoader {
return (ObjectDataLoader) CachedLoader.OBJECT_DATA.load();
}
+ public static PerformanceLoader performances() {
+ return (PerformanceLoader) CachedLoader.PERFORMANCES.load();
+ }
+
public static CommandLoader commands() {
return (CommandLoader) CachedLoader.COMMANDS.load();
}
@@ -78,6 +86,10 @@ public abstract class DataLoader {
return (TerrainZoneInsertionLoader) CachedLoader.ZONE_INSERTIONS.load();
}
+ public static TravelCostLoader travelCosts() {
+ return (TravelCostLoader) CachedLoader.TRAVEL_COSTS.load();
+ }
+
public static VehicleLoader vehicles() {
return (VehicleLoader) CachedLoader.VEHICLES.load();
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/ObjectDataLoader.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/ObjectDataLoader.java
index 5ae305453..e75cdcc84 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/ObjectDataLoader.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/ObjectDataLoader.java
@@ -35,10 +35,7 @@ import me.joshlarson.jlcommon.log.Log;
import java.io.File;
import java.io.IOException;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
public final class ObjectDataLoader extends DataLoader {
@@ -52,6 +49,10 @@ public final class ObjectDataLoader extends DataLoader {
return attributes.get(iff);
}
+ public Collection getObjects() {
+ return Collections.unmodifiableCollection(attributes.keySet());
+ }
+
@Override
public void load() throws IOException {
try (SdbResultSet set = SdbLoader.load(new File("serverdata/objects/object_data.sdb"))) {
diff --git a/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/PerformanceLoader.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/PerformanceLoader.java
new file mode 100644
index 000000000..acff163a7
--- /dev/null
+++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/PerformanceLoader.java
@@ -0,0 +1,193 @@
+/***********************************************************************************
+ * Copyright (c) 2019 /// Project SWG /// www.projectswg.com *
+ * *
+ * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
+ * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
+ * Our goal is to create an emulator which will provide a server for players to *
+ * continue playing a game similar to the one they used to play. We are basing *
+ * it on the final publish of the game prior to end-game events. *
+ * *
+ * This file is part of Holocore. *
+ * *
+ * --------------------------------------------------------------------------------*
+ * *
+ * Holocore is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU Affero General Public License as *
+ * published by the Free Software Foundation, either version 3 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * Holocore is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Affero General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Affero General Public License *
+ * along with Holocore. If not, see . *
+ ***********************************************************************************/
+
+package com.projectswg.holocore.resources.support.data.server_info.loader;
+
+import com.projectswg.common.data.CRC;
+import com.projectswg.holocore.resources.support.data.server_info.SdbColumnArraySet.SdbTextColumnArraySet;
+import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
+import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class PerformanceLoader extends DataLoader {
+
+ private final Map nameMap;
+ private final Map danceMap;
+
+ PerformanceLoader() {
+ this.nameMap = new HashMap<>();
+ this.danceMap = new HashMap<>();
+ }
+
+ @Nullable
+ public PerformanceInfo getPerformanceByName(String performanceName) {
+ return nameMap.get(performanceName);
+ }
+
+ @Nullable
+ public PerformanceInfo getPerformanceByDanceId(int danceVisualId) {
+ return danceMap.get(danceVisualId);
+ }
+
+ @Override
+ public final void load() throws IOException {
+ try (SdbResultSet set = SdbLoader.load(new File("serverdata/performance/performance.sdb"))) {
+ SdbTextColumnArraySet flourishes = set.getTextArrayParser("flourish(%d+)");
+ while (set.next()) {
+ PerformanceInfo performance = new PerformanceInfo(set, flourishes);
+ nameMap.put(performance.getPerformanceName(), performance);
+ danceMap.put(performance.getDanceVisualId(), performance);
+ }
+ }
+ }
+
+ public static class PerformanceInfo {
+
+ private final String performanceName;
+ private final int instrumentAudioId;
+ private final String requiredSong;
+ private final String requiredInstrument;
+ private final String requiredDance;
+ private final int danceVisualId;
+ private final int actionPointsPerLoop;
+ private final double loopDuration;
+ private final CRC type;
+ private final int baseXp;
+ private final int flourishXpMod;
+ private final int healMindWound;
+ private final int healShockWound;
+ private final String requiredSkillMod;
+ private final int requiredSkillModValue;
+ private final String mainloop;
+ private final String [] flourishes;
+ private final String intro;
+ private final String outro;
+
+ public PerformanceInfo(SdbResultSet set, SdbTextColumnArraySet flourishes) {
+ this.performanceName = set.getText("performance_name");
+ this.instrumentAudioId = (int) set.getInt("instrument_audio_id");
+ this.requiredSong = set.getText("required_song");
+ this.requiredInstrument = set.getText("required_instrument");
+ this.requiredDance = set.getText("required_dance");
+ this.danceVisualId = (int) set.getInt("dance_visual_id");
+ this.actionPointsPerLoop = (int) set.getInt("action_points_per_loop");
+ this.loopDuration = set.getReal("loop_duration");
+ this.type = new CRC((int) set.getInt("type"));
+ this.baseXp = (int) set.getInt("base_xp");
+ this.flourishXpMod = (int) set.getInt("flourish_xp_mod");
+ this.healMindWound = (int) set.getInt("heal_mind_wound");
+ this.healShockWound = (int) set.getInt("heal_shock_wound");
+ this.requiredSkillMod = set.getText("required_skill_mod");
+ this.requiredSkillModValue = (int) set.getInt("required_skill_mod_value");
+ this.mainloop = set.getText("mainloop");
+ this.flourishes = flourishes.getArray().clone();
+ this.intro = set.getText("intro");
+ this.outro = set.getText("outro");
+ }
+
+ public String getPerformanceName() {
+ return performanceName;
+ }
+
+ public int getInstrumentAudioId() {
+ return instrumentAudioId;
+ }
+
+ public String getRequiredSong() {
+ return requiredSong;
+ }
+
+ public String getRequiredInstrument() {
+ return requiredInstrument;
+ }
+
+ public String getRequiredDance() {
+ return requiredDance;
+ }
+
+ public int getDanceVisualId() {
+ return danceVisualId;
+ }
+
+ public int getActionPointsPerLoop() {
+ return actionPointsPerLoop;
+ }
+
+ public double getLoopDuration() {
+ return loopDuration;
+ }
+
+ public CRC getType() {
+ return type;
+ }
+
+ public int getBaseXp() {
+ return baseXp;
+ }
+
+ public int getFlourishXpMod() {
+ return flourishXpMod;
+ }
+
+ public int getHealMindWound() {
+ return healMindWound;
+ }
+
+ public int getHealShockWound() {
+ return healShockWound;
+ }
+
+ public String getRequiredSkillMod() {
+ return requiredSkillMod;
+ }
+
+ public int getRequiredSkillModValue() {
+ return requiredSkillModValue;
+ }
+
+ public String getMainloop() {
+ return mainloop;
+ }
+
+ public String[] getFlourishes() {
+ return flourishes.clone();
+ }
+
+ public String getIntro() {
+ return intro;
+ }
+
+ public String getOutro() {
+ return outro;
+ }
+ }
+}
diff --git a/src/utility/java/com/projectswg/utility/packets/PacketRecord.java b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/TravelCostLoader.java
similarity index 51%
rename from src/utility/java/com/projectswg/utility/packets/PacketRecord.java
rename to src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/TravelCostLoader.java
index c6bffcc7b..4b51f1af5 100644
--- a/src/utility/java/com/projectswg/utility/packets/PacketRecord.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/data/server_info/loader/TravelCostLoader.java
@@ -1,5 +1,5 @@
/***********************************************************************************
- * Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
+ * Copyright (c) 2019 /// Project SWG /// www.projectswg.com *
* *
* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
@@ -25,59 +25,74 @@
* along with Holocore. If not, see . *
***********************************************************************************/
-package com.projectswg.utility.packets;
+package com.projectswg.holocore.resources.support.data.server_info.loader;
-import com.projectswg.common.network.NetBuffer;
-import com.projectswg.common.network.packets.PacketType;
-import com.projectswg.common.network.packets.SWGPacket;
-import com.projectswg.common.network.packets.swg.zone.object_controller.ObjectController;
+import com.projectswg.common.data.location.Terrain;
+import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
+import com.projectswg.holocore.resources.support.data.server_info.SdbLoader.SdbResultSet;
-import java.time.Instant;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.Map;
-public class PacketRecord {
+public final class TravelCostLoader extends DataLoader {
- private final boolean server;
- private final Instant time;
- private final byte[] data;
+ private final Map> costs;
- public PacketRecord(boolean server, Instant time, byte[] data) {
- this.server = server;
- this.time = time;
- this.data = data;
+ TravelCostLoader() {
+ this.costs = new EnumMap<>(Terrain.class);
}
- public boolean isServer() {
- return server;
+ public boolean isCostDefined(Terrain source) {
+ return costs.containsKey(source);
}
- public Instant getTime() {
- return time;
+ public int getCost(Terrain source, Terrain destination) {
+ Map costMap = costs.get(source);
+ if (costMap == null)
+ return 0;
+ return costMap.getOrDefault(destination, 0);
}
- public byte[] getData() {
- return data;
- }
-
- public PacketType parseType() {
- NetBuffer data = NetBuffer.wrap(this.data);
- data.position(2);
- return PacketType.fromCrc(data.getInt());
- }
-
- public SWGPacket parse() {
- NetBuffer data = NetBuffer.wrap(this.data);
- data.position(2);
- PacketType type = PacketType.fromCrc(data.getInt());
- data.position(0);
- SWGPacket packet;
- if (type == PacketType.OBJECT_CONTROLLER) {
- return ObjectController.decodeController(data);
- } else {
- packet = PacketType.getForCrc(type.getCrc());
- if (packet != null)
- packet.decode(data);
- return packet;
+ @Override
+ public final void load() throws IOException {
+ try (SdbResultSet set = SdbLoader.load(new File("serverdata/travel/travel_costs.sdb"))) {
+ while (set.next()) {
+ TravelCostInfo travel = new TravelCostInfo(set);
+ costs.put(travel.getPlanet(), travel.getCosts());
+ }
+ }
+ for (Terrain key : costs.keySet()) {
+ for (Map costMap : costs.values()) {
+ assert costMap.keySet().equals(costs.keySet()) : "planet "+key+" is improperly defined in travel_costs.sdb";
+ }
}
}
+ public static class TravelCostInfo {
+
+ private final Terrain planet;
+ private final EnumMap costs;
+
+ public TravelCostInfo(SdbResultSet set) {
+ this.planet = Terrain.getTerrainFromName(set.getText("planet"));
+ this.costs = new EnumMap<>(Terrain.class);
+ for (String col : set.getColumns()) {
+ if (col.equalsIgnoreCase("planet"))
+ continue;
+ costs.put(Terrain.getTerrainFromName(col), (int) set.getInt(col));
+ }
+ }
+
+ public Terrain getPlanet() {
+ return planet;
+ }
+
+ public Map getCosts() {
+ return Collections.unmodifiableMap(costs);
+ }
+
+ }
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/FindFriendCallback.java b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/FindFriendCallback.java
index e88f043fa..e1e59be94 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/FindFriendCallback.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/FindFriendCallback.java
@@ -93,7 +93,8 @@ public class FindFriendCallback implements ICmdCallback {
waypoint.setPosition(location.getTerrain(), location.getX(), location.getY(), location.getZ());
waypoint.setColor(WaypointColor.PURPLE);
waypoint.setName(friendName);
- ghost.addWaypoint(waypoint);
+ if (!ghost.addWaypoint(waypoint))
+ SystemMessageIntent.broadcastPersonal(player, "@base_player:too_many_waypoints");
new ObjectCreatedIntent(waypoint).broadcast();
new SystemMessageIntent(player, new ProsePackage(new StringId("ui_cmnty", "friend_location_create_new_wp"), "TU", friendName)).broadcast();
} else {
diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/RequestWaypointCmdCallback.java b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/RequestWaypointCmdCallback.java
index 24b634c72..87aab41b4 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/RequestWaypointCmdCallback.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/RequestWaypointCmdCallback.java
@@ -65,7 +65,8 @@ public class RequestWaypointCmdCallback implements ICmdCallback {
waypoint.setPosition(terrain, position.getX(), position.getY(), position.getZ());
waypoint.setName(name);
waypoint.setColor(color);
- player.getPlayerObject().addWaypoint(waypoint);
+ if (!player.getPlayerObject().addWaypoint(waypoint))
+ SystemMessageIntent.broadcastPersonal(player, "@base_player:too_many_waypoints");
ObjectCreatedIntent.broadcast(waypoint);
}
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.java b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.java
index 6e6553849..4e80e87e8 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/global/commands/callbacks/WaypointCmdCallback.java
@@ -166,7 +166,8 @@ public class WaypointCmdCallback implements ICmdCallback {
if (name == null || name.isEmpty())
name = "Waypoint";
- ghost.addWaypoint(createWaypoint(color, name, location.build()));
+ if (!ghost.addWaypoint(createWaypoint(color, name, location.build())))
+ SystemMessageIntent.broadcastPersonal(player, "@base_player:too_many_waypoints");
if (differentPlanetMessage) {
new SystemMessageIntent(player, "Waypoint: New waypoint \""+ name + "\" created for location "
diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/network/BaselineObject.java b/src/main/java/com/projectswg/holocore/resources/support/global/network/BaselineObject.java
index 66df90622..743067966 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/global/network/BaselineObject.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/global/network/BaselineObject.java
@@ -75,9 +75,6 @@ public class BaselineObject {
case 6:
parseBaseline6(buffer);
break;
- case 7:
- parseBaseline7(buffer);
- break;
case 8:
parseBaseline8(buffer);
break;
@@ -107,10 +104,6 @@ public class BaselineObject {
return createBaseline(target, 6, this::createBaseline6);
}
- public Baseline createBaseline7(Player target) {
- return createBaseline(target, 7, this::createBaseline7);
- }
-
public Baseline createBaseline8(Player target) {
return createBaseline(target, 8, this::createBaseline8);
}
@@ -155,15 +148,6 @@ public class BaselineObject {
}
- /**
- * Creates the seventh baseline for the specified target. This baseline is sent when the object is used.
- * @param target the target to prepare the baseline for
- * @param data the baseline to build
- */
- protected void createBaseline7(Player target, BaselineBuilder data) {
-
- }
-
/**
* Creates the eighth baseline for the specified target. Only sent if the target has some permissions.
* @param target the target to prepare the baseline for
@@ -198,10 +182,6 @@ public class BaselineObject {
}
- protected void parseBaseline7(NetBuffer buffer) {
-
- }
-
protected void parseBaseline8(NetBuffer buffer) {
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/player/PlayerFlags.java b/src/main/java/com/projectswg/holocore/resources/support/global/player/PlayerFlags.java
index 3cfb26c99..c7701cceb 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/global/player/PlayerFlags.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/global/player/PlayerFlags.java
@@ -26,23 +26,43 @@
***********************************************************************************/
package com.projectswg.holocore.resources.support.global.player;
+import java.util.BitSet;
+import java.util.EnumSet;
+import java.util.Set;
+
public enum PlayerFlags {
/** Marks as Looking for a Group */
- LFG (0),
+ LFG (0),
/** Marks as Helper */
- HELPER (1),
+ HELPER (1),
/** Marks as Roleplayer */
- ROLEPLAYER (2),
+ ROLEPLAYER (2),
+ /** - */
+ FACTION (3),
+ /** - */
+ SPECIES (4),
+ /** - */
+ TITLE (5),
+ /** - */
+ FRIEND (6),
/** Away from Keyboard */
- AFK (7),
- /** Logged Out */
- LD (8),
+ AFK (7),
+ /** Logged Out / Link Dead */
+ LD (8),
/** Display the Faction Rank */
- FACTIONRANK (9),
+ FACTIONRANK (9),
+ /** Display the player's location in the matchmaking search */
+ DISPLAY_LOCATION_IN_SEARCH (10),
/** Marks as Out of Character */
- OOC (11),
+ OOC (11),
+ /** - */
+ SEARCH_BY_SOURCE_GALAXY (12),
/** Marks as Looking for Work */
- LFW (13);
+ LFW (13),
+ /** - */
+ ANONYMOUS (127);
+
+ private static final PlayerFlags [] FLAGS = values();
private int flag;
@@ -53,4 +73,22 @@ public enum PlayerFlags {
public int getFlag() {
return flag;
}
+
+ public static BitSet bitsetFromFlags(Set flags) {
+ BitSet ret = new BitSet(128);
+ for (PlayerFlags flag : flags) {
+ ret.set(flag.flag);
+ }
+ return ret;
+ }
+
+ public static Set flagsFromBitset(BitSet bitset) {
+ Set ret = EnumSet.noneOf(PlayerFlags.class);
+ for (PlayerFlags flag : FLAGS) {
+ if (bitset.get(flag.flag))
+ ret.add(flag);
+ }
+ return ret;
+ }
+
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/global/zone/creation/CharacterCreation.java b/src/main/java/com/projectswg/holocore/resources/support/global/zone/creation/CharacterCreation.java
index 064d0b19e..6d62830c9 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/global/zone/creation/CharacterCreation.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/global/zone/creation/CharacterCreation.java
@@ -50,7 +50,7 @@ import com.projectswg.holocore.services.support.objects.ObjectStorageService.Bui
import me.joshlarson.jlcommon.utilities.Arguments;
import org.jetbrains.annotations.NotNull;
-import java.util.Calendar;
+import java.time.Instant;
public class CharacterCreation {
@@ -165,8 +165,7 @@ public class CharacterCreation {
private void setPlayerObjectValues(PlayerObject playerObj) {
playerObj.setProfession(create.getProfession());
- Calendar date = Calendar.getInstance();
- playerObj.setBornDate(date.get(Calendar.YEAR), date.get(Calendar.MONTH) + 1, date.get(Calendar.DAY_OF_MONTH));
+ playerObj.setBornDate(Instant.now());
}
private void createStarterClothing(CreatureObject creature, String race) {
diff --git a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/AdminPermissions.java b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/AdminPermissions.java
index bbb992b82..6d42ee1f1 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/AdminPermissions.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/AdminPermissions.java
@@ -74,12 +74,12 @@ public final class AdminPermissions implements ContainerPermissions {
}
@Override
- public void read(MongoData data) {
+ public void readMongo(MongoData data) {
}
@Override
- public void save(MongoData data) {
+ public void saveMongo(MongoData data) {
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ContainerPermissions.java b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ContainerPermissions.java
index 43fc4e186..209705f03 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ContainerPermissions.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ContainerPermissions.java
@@ -64,7 +64,7 @@ public interface ContainerPermissions extends Persistable, MongoPersistable {
static MongoData save(MongoData data, ContainerPermissions permissions) {
data.putString("type", permissions.getType().name());
- permissions.save(data);
+ permissions.saveMongo(data);
return data;
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/DefaultPermissions.java b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/DefaultPermissions.java
index 07546076e..0e35e6886 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/DefaultPermissions.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/DefaultPermissions.java
@@ -86,12 +86,12 @@ public final class DefaultPermissions implements ContainerPermissions {
}
@Override
- public void read(MongoData data) {
+ public void readMongo(MongoData data) {
}
@Override
- public void save(MongoData data) {
+ public void saveMongo(MongoData data) {
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ReadOnlyPermissions.java b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ReadOnlyPermissions.java
index e2b8224e9..a8344245e 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ReadOnlyPermissions.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ReadOnlyPermissions.java
@@ -64,7 +64,7 @@ public final class ReadOnlyPermissions implements ContainerPermissions {
private ReadOnlyPermissions(MongoData data) {
this.exempt = new HashSet<>();
this.locked = false;
- read(data);
+ readMongo(data);
this.locked = true;
}
@@ -108,7 +108,7 @@ public final class ReadOnlyPermissions implements ContainerPermissions {
}
@Override
- public void read(MongoData data) {
+ public void readMongo(MongoData data) {
if (locked)
throw new IllegalStateException("Permissions is already locked");
for (long id : data.getArray("exempt", Long.class))
@@ -116,7 +116,7 @@ public final class ReadOnlyPermissions implements ContainerPermissions {
}
@Override
- public void save(MongoData data) {
+ public void saveMongo(MongoData data) {
data.putArray("exempt", exempt.stream().map(SWGObject::getObjectId).collect(Collectors.toList()));
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ReadWritePermissions.java b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ReadWritePermissions.java
index 2e91294d6..0226c3e07 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ReadWritePermissions.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/objects/permissions/ReadWritePermissions.java
@@ -68,7 +68,7 @@ public final class ReadWritePermissions implements ContainerPermissions {
private ReadWritePermissions(MongoData data) {
this.allowed = new HashSet<>();
this.locked = false;
- read(data);
+ readMongo(data);
this.locked = true;
}
@@ -112,14 +112,14 @@ public final class ReadWritePermissions implements ContainerPermissions {
}
@Override
- public void read(MongoData data) {
+ public void readMongo(MongoData data) {
if (locked)
throw new IllegalStateException("Permissions is already locked");
allowed.addAll(data.getArray("allowed", Long.class));
}
@Override
- public void save(MongoData data) {
+ public void saveMongo(MongoData data) {
data.putArray("allowed", new ArrayList<>(allowed));
}
diff --git a/src/main/java/com/projectswg/holocore/resources/support/objects/radial/terminal/TerminalBankRadial.java b/src/main/java/com/projectswg/holocore/resources/support/objects/radial/terminal/TerminalBankRadial.java
index a510a0ebf..709fd8884 100644
--- a/src/main/java/com/projectswg/holocore/resources/support/objects/radial/terminal/TerminalBankRadial.java
+++ b/src/main/java/com/projectswg/holocore/resources/support/objects/radial/terminal/TerminalBankRadial.java
@@ -11,6 +11,7 @@ import com.projectswg.holocore.resources.support.global.zone.sui.SuiWindow;
import com.projectswg.holocore.resources.support.objects.radial.RadialHandlerInterface;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
+import com.projectswg.holocore.resources.support.objects.swg.player.PlayerObject;
import com.projectswg.holocore.utilities.IntentFactory;
import java.util.ArrayList;
@@ -27,6 +28,7 @@ public class TerminalBankRadial implements RadialHandlerInterface {
@Override
public void getOptions(Collection options, Player player, SWGObject target) {
CreatureObject creature = player.getCreatureObject();
+ PlayerObject playerObject = player.getPlayerObject();
{
List useOptions = new ArrayList<>();
@@ -47,7 +49,7 @@ public class TerminalBankRadial implements RadialHandlerInterface {
List reserveOptions = new ArrayList<>();
if (creature.getBankBalance() >= 1E9 || creature.getCashBalance() >= 1E9)
reserveOptions.add(RadialOption.create(RadialItem.SERVER_MENU49, "@sui:bank_galactic_reserve_deposit"));
- if (creature.getReserveBalance() > 0)
+ if (playerObject != null && playerObject.getGalacticReserveDeposit() > 0)
reserveOptions.add(RadialOption.create(RadialItem.SERVER_MENU48, "@sui:bank_galactic_reserve_withdraw"));
options.add(RadialOption.createSilent(RadialItem.SERVER_MENU50, "@sui:bank_galactic_reserve", reserveOptions));
@@ -133,15 +135,19 @@ public class TerminalBankRadial implements RadialHandlerInterface {
SystemMessageIntent.broadcastPersonal(player, "You have to wait to perform another Galactic Reserve transaction");
return;
}
- long amount = creature.getBankBalance();
- if (amount > 1E9)
- amount = (long) 1E9;
- if (creature.getReserveBalance() + amount > 3E9 || amount == 0) {
+ PlayerObject playerObject = player.getPlayerObject();
+ if (playerObject == null) {
+ SystemMessageIntent.broadcastPersonal(player, "Internal server error with loading your player");
+ return;
+ }
+ long updatedBank = creature.getBankBalance() - 1_000_000_000L;
+ byte reserveBalance = playerObject.getGalacticReserveDeposit();
+ if (reserveBalance >= 3 || updatedBank < 0) {
SystemMessageIntent.broadcastPersonal(player, "@error_message:bank_deposit");
return;
}
- creature.setBankBalance((creature.getBankBalance() - amount));
- creature.setReserveBalance((creature.getReserveBalance() + amount));
+ creature.setBankBalance(updatedBank);
+ playerObject.setGalacticReserveDeposit((byte) (reserveBalance + 1));
creature.updateLastGalacticReserveTime();
}
@@ -150,15 +156,19 @@ public class TerminalBankRadial implements RadialHandlerInterface {
SystemMessageIntent.broadcastPersonal(player, "You have to wait to perform another Galactic Reserve transaction");
return;
}
- long amount = creature.getReserveBalance();
- if (amount > 1E9)
- amount = (long) 1E9;
- if (creature.getBankBalance() + amount > 2E9 || amount == 0) {
- SystemMessageIntent.broadcastPersonal(player, "@error_message:bank_withdraw");
+ PlayerObject playerObject = player.getPlayerObject();
+ if (playerObject == null) {
+ SystemMessageIntent.broadcastPersonal(player, "Internal server error with loading your player");
return;
}
- creature.setBankBalance(creature.getBankBalance() + amount);
- creature.setReserveBalance(creature.getReserveBalance() - amount);
+ long updatedBank = creature.getBankBalance() + 1_000_000_000L;
+ byte reserveBalance = playerObject.getGalacticReserveDeposit();
+ if (reserveBalance <= 0 || updatedBank >= 2_000_000_000L) {
+ SystemMessageIntent.broadcastPersonal(player, "@error_message:bank_deposit");
+ return;
+ }
+ creature.setBankBalance(updatedBank);
+ playerObject.setGalacticReserveDeposit((byte) (reserveBalance - 1));
creature.updateLastGalacticReserveTime();
}
diff --git a/src/main/java/com/projectswg/holocore/services/gameplay/combat/buffs/BuffService.java b/src/main/java/com/projectswg/holocore/services/gameplay/combat/buffs/BuffService.java
index a94080574..ab2642909 100644
--- a/src/main/java/com/projectswg/holocore/services/gameplay/combat/buffs/BuffService.java
+++ b/src/main/java/com/projectswg/holocore/services/gameplay/combat/buffs/BuffService.java
@@ -33,16 +33,15 @@ import com.projectswg.holocore.intents.gameplay.combat.CreatureKilledIntent;
import com.projectswg.holocore.intents.gameplay.combat.buffs.BuffIntent;
import com.projectswg.holocore.intents.gameplay.player.experience.skills.SkillModIntent;
import com.projectswg.holocore.intents.support.global.zone.PlayerEventIntent;
-import com.projectswg.holocore.resources.gameplay.combat.buff.BuffData;
-import com.projectswg.holocore.resources.gameplay.combat.buff.BuffMap;
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
+import com.projectswg.holocore.resources.support.data.server_info.loader.BuffLoader.BuffInfo;
+import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.objects.swg.creature.Buff;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
import me.joshlarson.jlcommon.concurrency.BasicScheduledThread;
import me.joshlarson.jlcommon.control.IntentHandler;
import me.joshlarson.jlcommon.control.Service;
-import me.joshlarson.jlcommon.log.Log;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -52,8 +51,8 @@ import java.util.stream.Stream;
public class BuffService extends Service {
/*
- * TODO allow removal of buffs with BuffData where PLAYER_REMOVABLE == 1
- * TODO remove buffs on respec. Listen for respec event and remove buffs with BuffData where
+ * TODO allow removal of buffs with BuffInfo where PLAYER_REMOVABLE == 1
+ * TODO remove buffs on respec. Listen for respec event and remove buffs with BuffInfo where
* REMOVE_ON_RESPEC == 1
* TODO remove group buff(s) from receiver when distance between caster and receiver is 100m.
* Perform same check upon zoning in. Skillmod1 effect name is "group"
@@ -61,20 +60,10 @@ public class BuffService extends Service {
private final BasicScheduledThread timerCheckThread;
private final Set monitored;
- private final BuffMap dataMap; // All CRCs are lower-cased buff names!
public BuffService() {
timerCheckThread = new BasicScheduledThread("buff-timer-check", this::checkBuffTimers);
monitored = new HashSet<>();
- dataMap = new BuffMap();
- }
-
- @Override
- public boolean initialize() {
- long startTime = StandardLog.onStartLoad("buffs");
- dataMap.load();
- StandardLog.onEndLoad(dataMap.size(), "buffs", startTime);
- return super.initialize();
}
@Override
@@ -101,9 +90,9 @@ public class BuffService extends Service {
@IntentHandler
private void handleBuffIntent(BuffIntent bi) {
- BuffData buffData = getBuff(bi.getBuffName());
+ BuffInfo buffData = getBuff(bi.getBuffName());
Objects.requireNonNull(buffData, "No known buff: " + bi.getBuffName());
- assert buffData.getName().equals(bi.getBuffName()) : "BuffIntent name ["+bi.getBuffName()+"] does not match BuffData name ["+buffData.getName()+ ']';
+ assert buffData.getName().equals(bi.getBuffName()) : "BuffIntent name ["+bi.getBuffName()+"] does not match BuffInfo name ["+buffData.getName()+ ']';
if (bi.isRemove()) {
removeBuff(bi.getReceiver(), buffData, false);
} else {
@@ -186,11 +175,11 @@ public class BuffService extends Service {
}
private boolean isBuffRemovedOnDeath(Buff buff) {
- return getBuff(buff).isRemovedOnDeath();
+ return getBuff(buff).isRemoveOnDeath();
}
- private boolean isBuffInfinite(BuffData buffData) {
- return buffData.getDefaultDuration() < 0;
+ private boolean isBuffInfinite(BuffInfo buffData) {
+ return buffData.getDuration() < 0;
}
private boolean isCreatureBuffed(CreatureObject creature) {
@@ -207,9 +196,9 @@ public class BuffService extends Service {
buffStream.forEach(buff -> removeBuff(creature, getBuff(buff), true));
}
- private void addBuff(CreatureObject receiver, @NotNull BuffData buffData, CreatureObject buffer) {
- String groupName = buffData.getGroupName();
- Optional groupBuff = receiver.getBuffEntries(buff -> groupName.equals(getBuff(buff).getGroupName())).findAny();
+ private void addBuff(CreatureObject receiver, @NotNull BuffInfo buffData, CreatureObject buffer) {
+ String groupName = buffData.getGroup1();
+ Optional groupBuff = receiver.getBuffEntries(buff -> groupName.equals(getBuff(buff).getGroup1())).findAny();
int applyTime = calculatePlayTime(receiver);
@@ -224,8 +213,8 @@ public class BuffService extends Service {
checkStackCount(receiver, buff, applyTime, 1);
}
} else {
- BuffData oldBuff = getBuff(buff);
- if (buffData.getGroupPriority() >= oldBuff.getGroupPriority()) {
+ BuffInfo oldBuff = getBuff(buff);
+ if (buffData.getPriority() >= oldBuff.getPriority()) {
removeBuff(receiver, oldBuff, true);
applyBuff(receiver, buffer, buffData, applyTime);
}
@@ -235,7 +224,7 @@ public class BuffService extends Service {
}
}
- private void removeBuff(CreatureObject creature, @NotNull BuffData buffData, boolean expired) {
+ private void removeBuff(CreatureObject creature, @NotNull BuffInfo buffData, boolean expired) {
Optional optionalEntry = creature.getBuffEntries(buff -> buff.getCrc() == buffData.getCrc()).findAny();
if (!optionalEntry.isPresent())
return; // Obique: Used to be an assertion, however if a service sends the removal after it expires it would assert - so I just removed it.
@@ -257,7 +246,7 @@ public class BuffService extends Service {
}
private void checkStackCount(CreatureObject receiver, Buff buff, int applyTime, int stackMod) {
- BuffData buffData = getBuff(buff);
+ BuffInfo buffData = getBuff(buff);
Objects.requireNonNull(buffData, "No known buff: " + buff.getCrc());
// If it's the same buff, we need to check for stacks
@@ -279,26 +268,26 @@ public class BuffService extends Service {
// If the stack count was incremented, also renew the duration
if (stackMod > 0) {
- receiver.setBuffDuration(crc, applyTime, (int) buffData.getDefaultDuration());
+ receiver.setBuffDuration(crc, applyTime, (int) buffData.getDuration());
}
}
- private void applyBuff(CreatureObject receiver, CreatureObject buffer, BuffData buffData, int applyTime) {
+ private void applyBuff(CreatureObject receiver, CreatureObject buffer, BuffInfo buffData, int applyTime) {
// TODO stack counts upon add/remove need to be defined on a per-buff basis due to skillmod influence. Scripts might not be a bad idea.
int stackCount = 1;
- int buffDuration = (int) buffData.getDefaultDuration();
+ int buffDuration = (int) buffData.getDuration();
{
Player bufferPlayer = buffer.getOwner();
String bufferUsername = bufferPlayer == null ? "NULL" : bufferPlayer.getUsername();
StandardLog.onPlayerTrace(this, receiver, "received buff '%s' from %s/%s; applyTime: %d, buffDuration: %d", buffData.getName(), bufferUsername, buffer.getObjectName(), applyTime, buffDuration);
}
- Buff buff = new Buff(buffData.getCrc(), applyTime + buffDuration, buffData.getEffectValue(0), buffDuration, buffer.getObjectId(), stackCount);
+ Buff buff = new Buff(buffData.getCrc(), applyTime + buffDuration, (float) buffData.getEffectValue(0), buffDuration, buffer.getObjectId(), stackCount);
checkSkillMods(buffData, receiver, 1);
receiver.addBuff(buff);
- sendParticleEffect(buffData.getEffectFileName(), receiver, buffData.getParticleHardPoint());
- sendParticleEffect(buffData.getStanceParticle(), receiver, buffData.getParticleHardPoint());
+ sendParticleEffect(buffData.getParticle(), receiver, buffData.getParticleHardpoint());
+ sendParticleEffect(buffData.getStanceParticle(), receiver, buffData.getParticleHardpoint());
addToMonitored(receiver);
}
@@ -309,19 +298,19 @@ public class BuffService extends Service {
}
}
- private void checkCallback(BuffData buffData, CreatureObject creature) {
+ private void checkCallback(BuffInfo buffData, CreatureObject creature) {
String callback = buffData.getCallback();
if (callback.equals("none")) {
return;
}
- if (dataMap.containsBuff(callback)) {
+ if (DataLoader.buffs().containsBuff(callback)) {
addBuff(creature, getBuff(callback), creature);
}
}
- private void checkSkillMods(BuffData buffData, CreatureObject creature, int valueFactor) {
+ private void checkSkillMods(BuffInfo buffData, CreatureObject creature, int valueFactor) {
/*
* TODO Check effectName == "group". If yes, every group member within 100m range (maybe
* just the ones aware of the buffer) receive the buff. Once outside range, buff needs
@@ -331,19 +320,19 @@ public class BuffService extends Service {
sendSkillModIntent(creature, buffData.getEffectName(i), buffData.getEffectValue(i), valueFactor);
}
- private void sendSkillModIntent(CreatureObject creature, String effectName, float effectValue, int valueFactor) {
+ private void sendSkillModIntent(CreatureObject creature, String effectName, double effectValue, int valueFactor) {
if (!effectName.isEmpty())
new SkillModIntent(effectName, 0, (int) effectValue * valueFactor, creature).broadcast();
}
@Nullable
- private BuffData getBuff(String name) {
- return dataMap.getBuff(name);
+ private BuffInfo getBuff(String name) {
+ return DataLoader.buffs().getBuff(name);
}
@Nullable
- private BuffData getBuff(@NotNull Buff buff) {
- return dataMap.getBuff(buff.getCrc());
+ private BuffInfo getBuff(@NotNull Buff buff) {
+ return DataLoader.buffs().getBuff(buff.getCrc());
}
}
diff --git a/src/main/java/com/projectswg/holocore/services/gameplay/entertainment/EntertainmentService.java b/src/main/java/com/projectswg/holocore/services/gameplay/entertainment/EntertainmentService.java
index 13e6bcc9b..dbe2fe3f2 100644
--- a/src/main/java/com/projectswg/holocore/services/gameplay/entertainment/EntertainmentService.java
+++ b/src/main/java/com/projectswg/holocore/services/gameplay/entertainment/EntertainmentService.java
@@ -30,8 +30,6 @@ import com.projectswg.common.data.encodables.oob.ProsePackage;
import com.projectswg.common.data.encodables.oob.StringId;
import com.projectswg.common.data.encodables.tangible.Posture;
import com.projectswg.common.data.location.Location;
-import com.projectswg.common.data.swgfile.ClientFactory;
-import com.projectswg.common.data.swgfile.visitors.DatatableData;
import com.projectswg.common.network.packets.swg.zone.object_controller.Animation;
import com.projectswg.holocore.intents.gameplay.entertainment.dance.DanceIntent;
import com.projectswg.holocore.intents.gameplay.entertainment.dance.FlourishIntent;
@@ -40,6 +38,8 @@ import com.projectswg.holocore.intents.gameplay.player.experience.ExperienceInte
import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent;
import com.projectswg.holocore.intents.support.global.zone.PlayerEventIntent;
import com.projectswg.holocore.intents.support.global.zone.PlayerTransformedIntent;
+import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
+import com.projectswg.holocore.resources.support.data.server_info.loader.PerformanceLoader.PerformanceInfo;
import com.projectswg.holocore.resources.support.global.player.Player;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
@@ -65,39 +65,14 @@ public class EntertainmentService extends Service {
private static final byte XP_CYCLE_RATE = 10;
private static final byte WATCH_RADIUS = 20;
- private final Map performanceMap; // performance names mapped to performance data
private final Map performerMap;
- private final Map danceMap; // Maps performance ID to performance name
private final ScheduledExecutorService executorService;
public EntertainmentService() {
- performanceMap = new HashMap<>();
performerMap = new HashMap<>(); // TODO synchronize access?
- danceMap = new HashMap<>();
executorService = Executors.newSingleThreadScheduledExecutor();
}
- @Override
- public boolean initialize() {
- DatatableData performanceTable = (DatatableData) ClientFactory.getInfoFromFile("datatables/performance/performance.iff");
-
- for (int i = 0; i < performanceTable.getRowCount(); i++) {
- String requiredDance = (String) performanceTable.getCell(i, 4);
-
- // Load the dances only. Music is currently unsupported.
- if (!requiredDance.isEmpty()) {
- String performanceName = (String) performanceTable.getCell(i, 0);
- String performanceNumber = String.valueOf(performanceTable.getCell(i, 5)); // danceVisualId
- PerformanceData performanceData = new PerformanceData(performanceNumber, (int) performanceTable.getCell(i, 10)); // flourishXpMod
-
- performanceMap.put(performanceName, performanceData); // Map the name to the performance data
- danceMap.put(performanceNumber, performanceName); // Map the dance ID to a performance name!
- }
- }
-
- return super.initialize();
- }
-
@Override
public boolean terminate() {
executorService.shutdownNow();
@@ -116,7 +91,7 @@ public class EntertainmentService extends Service {
if (!changeDance && dancer.isPerforming()) {
new SystemMessageIntent(dancer.getOwner(), "@performance:already_performing_self").broadcast();
- } else if (performanceMap.containsKey(danceName)) {
+ } else if (DataLoader.performances().getPerformanceByName(danceName) != null) {
// The dance name is valid.
if (dancer.hasAbility("startDance+" + danceName)) {
@@ -157,7 +132,7 @@ public class EntertainmentService extends Service {
case PE_ZONE_IN_SERVER:
// We need to check if they're dancing in order to start giving them XP
if (isEntertainer(creature) && creature.getPosture().equals(Posture.SKILL_ANIMATING)) {
- scheduleExperienceTask(creature, danceMap.get(creature.getAnimation().replace("dance_", "")));
+ scheduleExperienceTask(creature, DataLoader.performances().getPerformanceByDanceId(Integer.parseInt(creature.getAnimation().replace("dance_", ""))).getPerformanceName());
}
break;
@@ -311,7 +286,7 @@ public class EntertainmentService extends Service {
}
private void startDancing(CreatureObject dancer, String danceName) {
- dancer.setAnimation("dance_" + performanceMap.get(danceName).getPerformanceId());
+ dancer.setAnimation("dance_" + DataLoader.performances().getPerformanceByName(danceName).getPerformanceName());
dancer.setPerformanceId(0); // 0 - anything else will make it look like we're playing music
dancer.setPerformanceCounter(0);
dancer.setPerforming(true);
@@ -342,7 +317,7 @@ public class EntertainmentService extends Service {
private void changeDance(CreatureObject dancer, String newPerformanceName) {
performerMap.get(dancer.getObjectId()).setPerformanceName(newPerformanceName);
- dancer.setAnimation("dance_" + performanceMap.get(newPerformanceName).getPerformanceId());
+ dancer.setAnimation("dance_" + DataLoader.performances().getPerformanceByName(newPerformanceName).getPerformanceName());
}
private void startWatching(CreatureObject actor, CreatureObject creature) {
@@ -448,7 +423,7 @@ public class EntertainmentService extends Service {
}
String performanceName = performance.getPerformanceName();
- PerformanceData performanceData = performanceMap.get(performanceName);
+ PerformanceInfo performanceData = DataLoader.performances().getPerformanceByName(performanceName);
int flourishXpMod = performanceData.getFlourishXpMod();
int performanceCounter = performer.getPerformanceCounter();
int xpGained = performanceCounter * flourishXpMod;
diff --git a/src/main/java/com/projectswg/holocore/services/gameplay/gcw/faction/CivilWarService.java b/src/main/java/com/projectswg/holocore/services/gameplay/gcw/faction/CivilWarService.java
index 2c4a2ccc4..9fe0f639c 100644
--- a/src/main/java/com/projectswg/holocore/services/gameplay/gcw/faction/CivilWarService.java
+++ b/src/main/java/com/projectswg/holocore/services/gameplay/gcw/faction/CivilWarService.java
@@ -208,7 +208,7 @@ public class CivilWarService extends Service {
private void changeRank(PlayerObject playerObject, int newRank) {
assert (newRank < 1 || newRank > 12);
- int oldRank = playerObject.getCurrentRank();
+ int oldRank = playerObject.getCurrentGcwRank();
assert (oldRank > 1);
@@ -218,7 +218,7 @@ public class CivilWarService extends Service {
PvpFaction faction = creature.getPvpFaction();
int abilityIndex = faction == PvpFaction.IMPERIAL ? IMPERIAL_INDEX : REBEL_INDEX;
- playerObject.setCurrentRank(newRank);
+ playerObject.setCurrentGcwRank(newRank);
if (oldRank > newRank) {
// They've been demoted
@@ -258,8 +258,8 @@ public class CivilWarService extends Service {
}
private void updateRank(PlayerObject playerObject) {
- int currentRank = playerObject.getCurrentRank();
- float oldProgress = playerObject.getRankProgress();
+ int currentRank = playerObject.getCurrentGcwRank();
+ float oldProgress = playerObject.getCurrentGcwRankProgress();
int points = playerObject.getGcwPoints();
float decay = 0;
@@ -270,10 +270,10 @@ public class CivilWarService extends Service {
float newProgress = rankProgress(oldProgress, decay, currentRank, points);
if (newProgress >= 100) {
- int promotion = playerObject.getCurrentRank() + 1;
+ int promotion = playerObject.getCurrentGcwRank() + 1;
if (promotion > 12) { // 12 is the max rank
- playerObject.setRankProgress(99.99F);
+ playerObject.setCurrentGcwRankProgress(99.99F);
moveToLifetime(playerObject, points);
return;
}
@@ -292,17 +292,17 @@ public class CivilWarService extends Service {
return;
} else {
// They've ranked up, but cannot rank up again
- playerObject.setRankProgress(nextRankProgress);
+ playerObject.setCurrentGcwRankProgress(nextRankProgress);
}
} else if (newProgress > 0) {
// Set their new progress
- playerObject.setRankProgress(newProgress);
+ playerObject.setCurrentGcwRankProgress(newProgress);
} else if (newProgress < 0 && isRankDown(oldProgress, newProgress)) {
- int demotion = playerObject.getCurrentRank() - 1;
+ int demotion = playerObject.getCurrentGcwRank() - 1;
if (demotion < 1) { // 1 is the minimum rank
- playerObject.setRankProgress(0);
+ playerObject.setCurrentGcwRankProgress(0);
return;
}
@@ -321,7 +321,7 @@ public class CivilWarService extends Service {
return;
} else {
// They've ranked down, but cannot rank down again
- playerObject.setRankProgress(nextRankProgress);
+ playerObject.setCurrentGcwRankProgress(nextRankProgress);
}
}
@@ -330,7 +330,7 @@ public class CivilWarService extends Service {
private void updateRanks() {
playerObjects.forEach(playerObject -> {
- if (playerObject.getCurrentRank() > 0)
+ if (playerObject.getCurrentGcwRank() > 0)
updateRank(playerObject);
});
@@ -431,14 +431,14 @@ public class CivilWarService extends Service {
if (fi.getNewFaction() == PvpFaction.NEUTRAL) {
// They've left the imperials or rebels and must have rank removed
- playerObject.setCurrentRank(0);
+ playerObject.setCurrentGcwRank(0);
int points = playerObject.getGcwPoints();
moveToLifetime(playerObject, points);
} else {
// They've joined the imperials or rebels and become Privates
- playerObject.setCurrentRank(1);
+ playerObject.setCurrentGcwRank(1);
}
}
diff --git a/src/main/java/com/projectswg/holocore/services/gameplay/player/badge/BadgeService.java b/src/main/java/com/projectswg/holocore/services/gameplay/player/badge/BadgeService.java
index 1297c38a3..9ca268275 100644
--- a/src/main/java/com/projectswg/holocore/services/gameplay/player/badge/BadgeService.java
+++ b/src/main/java/com/projectswg/holocore/services/gameplay/player/badge/BadgeService.java
@@ -63,15 +63,12 @@ public class BadgeService extends Service {
}
private void grantBadge(PlayerObject player, int beginSlotId, String collectionName, boolean isHidden, String slotName) {
- BitSet collections = BitSet.valueOf(player.getCollectionBadges());
-
- collections.set(beginSlotId);
- player.setCollectionBadges(collections.toByteArray());
+ player.setCollectionFlag(beginSlotId);
handleMessage(player, hasCompletedCollection(player, collectionName), collectionName, isHidden, slotName);
}
private void grantBadgeIncrement(PlayerObject player, int beginSlotId, int endSlotId, int maxSlotValue) {
- BitSet collections = BitSet.valueOf(player.getCollectionBadges());
+ BitSet collections = player.getCollectionBadges();
int binaryValue = 1;
int curValue = 0;
@@ -94,7 +91,7 @@ public class BadgeService extends Service {
collections.clear(beginSlotId + i);
}
}
- player.setCollectionBadges(collections.toByteArray());
+ player.setCollectionFlags(collections);
}
}
@@ -264,15 +261,12 @@ public class BadgeService extends Service {
}
private boolean hasBadge(PlayerObject player, int badgeBeginSlotId) {
- BitSet collections = BitSet.valueOf(player.getCollectionBadges());
-
- return collections.get(badgeBeginSlotId);
+ return player.getCollectionFlag(badgeBeginSlotId);
}
private boolean hasCompletedCollection(PlayerObject player, String collectionTitle) {
-
String collectionName = "";
- BitSet collections = BitSet.valueOf(player.getCollectionBadges());
+ BitSet collections = player.getCollectionBadges();
for (int row = 0; row < collectionTable.getRowCount(); row++) {
int beginSlotId = (int) collectionTable.getCell(row, 4);
diff --git a/src/main/java/com/projectswg/holocore/services/support/data/dev/CustomObjectService.java b/src/main/java/com/projectswg/holocore/services/support/data/dev/CustomObjectService.java
index a76fce9bc..be55adf85 100644
--- a/src/main/java/com/projectswg/holocore/services/support/data/dev/CustomObjectService.java
+++ b/src/main/java/com/projectswg/holocore/services/support/data/dev/CustomObjectService.java
@@ -6,6 +6,7 @@ import com.projectswg.holocore.intents.support.global.chat.SystemMessageIntent;
import com.projectswg.holocore.intents.support.global.command.ExecuteCommandIntent;
import com.projectswg.holocore.intents.support.objects.swg.DestroyObjectIntent;
import com.projectswg.holocore.intents.support.objects.swg.ObjectCreatedIntent;
+import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.global.commands.Command;
import com.projectswg.holocore.resources.support.global.player.AccessLevel;
import com.projectswg.holocore.resources.support.global.zone.sui.SuiButtons;
@@ -92,21 +93,24 @@ public class CustomObjectService extends Service {
}
private ListBoxRecursive createListBoxRecursive() {
- return createListBoxRecursive(new File("clientdata/object"));
+ return createListBoxRecursive(DataLoader.objectData().getObjects());
}
- private ListBoxRecursive createListBoxRecursive(File start) {
+ private ListBoxRecursive createListBoxRecursive(Collection objects) {
Map mapping = new TreeMap<>();
- File [] children = start.listFiles();
- assert children != null;
- for (File file : children) {
- if (file.isDirectory()) {
- mapping.put(file.getName(), createListBoxRecursive(file));
- } else if (file.isFile() && file.getName().startsWith("shared_") && file.getName().endsWith(".iff")) {
- String iff = file.getAbsolutePath().replace(new File("clientdata").getAbsolutePath()+File.separator, "");
- mapping.put(prettyIff(iff), iff.replace(File.separatorChar, '/'));
- }
+ for (String iff : objects) {
+ mapping.put(prettyIff(iff), iff.replace(File.separatorChar, '/'));
}
+// File [] children = start.listFiles();
+// assert children != null;
+// for (File file : children) {
+// if (file.isDirectory()) {
+// mapping.put(file.getName(), createListBoxRecursive(file));
+// } else if (file.isFile() && file.getName().startsWith("shared_") && file.getName().endsWith(".iff")) {
+// String iff = file.getAbsolutePath().replace(new File("clientdata").getAbsolutePath()+File.separator, "");
+// mapping.put(prettyIff(iff), iff.replace(File.separatorChar, '/'));
+// }
+// }
return new ListBoxRecursive(mapping);
}
diff --git a/src/main/java/com/projectswg/holocore/services/support/global/chat/ChatFriendService.java b/src/main/java/com/projectswg/holocore/services/support/global/chat/ChatFriendService.java
index e86b6853d..f6c1065dc 100644
--- a/src/main/java/com/projectswg/holocore/services/support/global/chat/ChatFriendService.java
+++ b/src/main/java/com/projectswg/holocore/services/support/global/chat/ChatFriendService.java
@@ -117,7 +117,7 @@ public class ChatFriendService extends Service {
}
private void handleRequestFriendList(Player player) {
- player.getPlayerObject().sendFriendsList();
+ player.getPlayerObject().sendFriendList();
}
/* Ignore List */
diff --git a/src/main/java/com/projectswg/holocore/services/support/global/zone/ConnectionService.java b/src/main/java/com/projectswg/holocore/services/support/global/zone/ConnectionService.java
index 3a189e72e..7c1125887 100644
--- a/src/main/java/com/projectswg/holocore/services/support/global/zone/ConnectionService.java
+++ b/src/main/java/com/projectswg/holocore/services/support/global/zone/ConnectionService.java
@@ -127,14 +127,14 @@ public class ConnectionService extends Service {
PlayerObject player = p.getPlayerObject();
if (player == null)
return;
- player.setFlagBitmask(PlayerFlags.LD);
+ player.setFlag(PlayerFlags.LD);
}
private void clearPlayerFlag(Player p) {
PlayerObject player = p.getPlayerObject();
if (player == null)
return;
- player.clearFlagBitmask(PlayerFlags.LD);
+ player.clearFlag(PlayerFlags.LD);
}
private void zoneIn(Player p) {
diff --git a/src/main/java/com/projectswg/holocore/services/support/objects/ObjectStorageService.java b/src/main/java/com/projectswg/holocore/services/support/objects/ObjectStorageService.java
index 1d780ed5c..a04e24d30 100644
--- a/src/main/java/com/projectswg/holocore/services/support/objects/ObjectStorageService.java
+++ b/src/main/java/com/projectswg/holocore/services/support/objects/ObjectStorageService.java
@@ -13,10 +13,12 @@ import com.projectswg.holocore.resources.support.data.server_info.ObjectDatabase
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
import com.projectswg.holocore.resources.support.data.server_info.loader.BuildoutLoader;
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
+import com.projectswg.holocore.resources.support.data.server_info.mongodb.users.PswgUserDatabase;
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
import com.projectswg.holocore.resources.support.objects.swg.building.BuildingObject;
import com.projectswg.holocore.resources.support.objects.swg.cell.CellObject;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
+import me.joshlarson.jlcommon.concurrency.ScheduledThreadPool;
import me.joshlarson.jlcommon.control.IntentHandler;
import me.joshlarson.jlcommon.control.Service;
import me.joshlarson.jlcommon.log.Log;
@@ -24,6 +26,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
@@ -31,6 +35,9 @@ import java.util.function.Function;
public class ObjectStorageService extends Service {
private final ObjectDatabase database;
+ private final PswgUserDatabase userDatabase;
+ private final ScheduledThreadPool persistenceThread;
+ private final Set persistedObjects;
private final Map objectMap;
private final Map buildouts;
private final Map buildingLookup;
@@ -38,6 +45,9 @@ public class ObjectStorageService extends Service {
public ObjectStorageService() {
this.database = new CachedObjectDatabase<>("odb/objects.db", SWGObjectFactory::create, SWGObjectFactory::save);
+ this.userDatabase = new PswgUserDatabase();
+ this.persistenceThread = new ScheduledThreadPool(1, 3, "object-storage-service");
+ this.persistedObjects = new CopyOnWriteArraySet<>();
this.objectMap = new ConcurrentHashMap<>(256*1024, 0.8f, Runtime.getRuntime().availableProcessors());
this.buildouts = new HashMap<>(128*1024, 1f);
this.buildingLookup = new HashMap<>();
@@ -59,14 +69,17 @@ public class ObjectStorageService extends Service {
database.traverse(this::loadObject);
}
+ persistenceThread.start();
+ persistenceThread.executeWithFixedDelay(TimeUnit.MINUTES.toMillis(5), TimeUnit.MINUTES.toMillis(5), this::saveObjects);
started.set(true);
return true;
}
@Override
public boolean stop() {
+ persistenceThread.stop();
started.set(false);
- return true;
+ return persistenceThread.awaitTermination(1000);
}
@Override
@@ -75,6 +88,7 @@ public class ObjectStorageService extends Service {
database.close();
}
ObjectLookup.setObjectAuthority(null);
+ saveObjects();
return true;
}
@@ -84,6 +98,7 @@ public class ObjectStorageService extends Service {
if (!database.load() && database.fileExists())
return false;
}
+ database.traverse(persistedObjects::add);
StandardLog.onEndLoad(database.size(), "players", startTime);
return true;
}
@@ -129,6 +144,12 @@ public class ObjectStorageService extends Service {
}
}
+ private void saveObjects() {
+ for (SWGObject obj : persistedObjects) {
+
+ }
+ }
+
@IntentHandler
private void processObjectCreatedIntent(ObjectCreatedIntent intent) {
SWGObject obj = intent.getObject();
@@ -205,6 +226,10 @@ public class ObjectStorageService extends Service {
AUTHORITY.set(authority);
}
+ public static boolean isDefined() {
+ return AUTHORITY.get() != null;
+ }
+
@Nullable
public static SWGObject getObjectById(long id) {
return AUTHORITY.get().apply(id);
diff --git a/src/main/java/com/projectswg/holocore/utilities/clientdata_printer/ClientdataPrinterDatatable.java b/src/main/java/com/projectswg/holocore/utilities/clientdata_printer/ClientdataPrinterDatatable.java
deleted file mode 100644
index 51d432238..000000000
--- a/src/main/java/com/projectswg/holocore/utilities/clientdata_printer/ClientdataPrinterDatatable.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/***********************************************************************************
- * Copyright (c) 2018 /// Project SWG /// www.projectswg.com *
- * *
- * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
- * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
- * Our goal is to create an emulator which will provide a server for players to *
- * continue playing a game similar to the one they used to play. We are basing *
- * it on the final publish of the game prior to end-game events. *
- * *
- * This file is part of Holocore. *
- * *
- * --------------------------------------------------------------------------------*
- * *
- * Holocore is free software: you can redistribute it and/or modify *
- * it under the terms of the GNU Affero General Public License as *
- * published by the Free Software Foundation, either version 3 of the *
- * License, or (at your option) any later version. *
- * *
- * Holocore is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU Affero General Public License for more details. *
- * *
- * You should have received a copy of the GNU Affero General Public License *
- * along with Holocore. If not, see . *
- ***********************************************************************************/
-package com.projectswg.holocore.utilities.clientdata_printer;
-
-import com.projectswg.common.data.swgfile.ClientFactory;
-import com.projectswg.common.data.swgfile.visitors.DatatableData;
-import me.joshlarson.jlcommon.log.Log;
-import me.joshlarson.jlcommon.log.log_wrapper.ConsoleLogWrapper;
-
-public class ClientdataPrinterDatatable {
-
- public static void main(String [] args) {
- Log.addWrapper(new ConsoleLogWrapper());
- printTable("datatables/buildout/areas_tatooine.iff");
- }
-
- private static void printTable(String table) {
- DatatableData data = (DatatableData) ClientFactory.getInfoFromFile(table);
- for (int col = 0; col < data.getColumnCount(); col++) {
- System.out.print(data.getColumnName(col) + ',');
- }
- System.out.println();
- for (int row = 0; row < data.getRowCount(); row++) {
- for (int col = 0; col < data.getColumnCount(); col++) {
- System.out.print(data.getCell(row, col) + ",");
- }
- System.out.println();
- }
- }
-
-}
diff --git a/src/test/java/com/projectswg/holocore/resources/gameplay/world/travel/TestTravelHelper.java b/src/test/java/com/projectswg/holocore/resources/gameplay/world/travel/TestTravelHelper.java
index d3d7a0d69..8674a3389 100644
--- a/src/test/java/com/projectswg/holocore/resources/gameplay/world/travel/TestTravelHelper.java
+++ b/src/test/java/com/projectswg/holocore/resources/gameplay/world/travel/TestTravelHelper.java
@@ -59,9 +59,9 @@ public class TestTravelHelper extends TestRunnerNoIntents {
for (Terrain terrain : terrains) {
Assert.assertEquals(100, helper.getTravelFee(terrain, terrain));
}
- Assert.assertEquals(2000, helper.getTravelFee(Terrain.DATHOMIR, Terrain.CORELLIA));
+ Assert.assertEquals(1250, helper.getTravelFee(Terrain.DATHOMIR, Terrain.CORELLIA));
Assert.assertEquals(2000, helper.getTravelFee(Terrain.CORELLIA, Terrain.DATHOMIR));
- Assert.assertEquals(1750, helper.getTravelFee(Terrain.NABOO, Terrain.ENDOR));
+ Assert.assertEquals(4000, helper.getTravelFee(Terrain.NABOO, Terrain.ENDOR));
Assert.assertEquals(500, helper.getTravelFee(Terrain.TATOOINE, Terrain.NABOO));
Assert.assertFalse(helper.isValidRoute(Terrain.TATOOINE, Terrain.YAVIN4));
Assert.assertTrue(helper.isValidRoute(Terrain.TATOOINE, Terrain.LOK));
diff --git a/src/test/java/com/projectswg/holocore/resources/support/data/collections/TestSWGFlag.java b/src/test/java/com/projectswg/holocore/resources/support/data/collections/TestSWGFlag.java
index 350bdc981..82f523498 100644
--- a/src/test/java/com/projectswg/holocore/resources/support/data/collections/TestSWGFlag.java
+++ b/src/test/java/com/projectswg/holocore/resources/support/data/collections/TestSWGFlag.java
@@ -27,14 +27,18 @@
package com.projectswg.holocore.resources.support.data.collections;
+import com.projectswg.common.network.NetBuffer;
import com.projectswg.holocore.test.runners.TestRunnerNoIntents;
import org.junit.Assert;
import org.junit.Test;
+import java.nio.IntBuffer;
+import java.util.BitSet;
+
public class TestSWGFlag extends TestRunnerNoIntents {
@Test
- public void testFlag() {
+ public void testFlagAccuracy() {
SWGFlag flag = new SWGFlag(3, 16);
flag.set(1);
flag.set(4);
@@ -47,6 +51,24 @@ public class TestSWGFlag extends TestRunnerNoIntents {
Assert.assertEquals(1, ints[1]);
Assert.assertEquals(1, ints[2]);
Assert.assertEquals(1, ints[3]);
+ SWGFlag decoded = new SWGFlag(3, 16);
+ decoded.decode(NetBuffer.wrap(flag.encode()));
+ Assert.assertArrayEquals(flag.encode(), decoded.encode());
+ }
+
+ @Test
+ public void testFlagSize() {
+ byte [] encoded;
+ SWGFlag flag = new SWGFlag(3, 16);
+
+ encoded = flag.encode();
+ Assert.assertEquals(4, encoded.length);
+
+ flag.set(1);
+ encoded = flag.encode();
+ Assert.assertEquals(8, encoded.length);
+ Assert.assertEquals(1, encoded[0]);
+ Assert.assertEquals(2, encoded[4]);
}
}
diff --git a/src/test/java/com/projectswg/holocore/resources/support/objects/swg/TestSWGPersistence.java b/src/test/java/com/projectswg/holocore/resources/support/objects/swg/TestSWGPersistence.java
new file mode 100644
index 000000000..af827b2f4
--- /dev/null
+++ b/src/test/java/com/projectswg/holocore/resources/support/objects/swg/TestSWGPersistence.java
@@ -0,0 +1,289 @@
+/***********************************************************************************
+ * Copyright (c) 2019 /// Project SWG /// www.projectswg.com *
+ * *
+ * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on *
+ * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. *
+ * Our goal is to create an emulator which will provide a server for players to *
+ * continue playing a game similar to the one they used to play. We are basing *
+ * it on the final publish of the game prior to end-game events. *
+ * *
+ * This file is part of Holocore. *
+ * *
+ * --------------------------------------------------------------------------------*
+ * *
+ * Holocore is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU Affero General Public License as *
+ * published by the Free Software Foundation, either version 3 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * Holocore is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Affero General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Affero General Public License *
+ * along with Holocore. If not, see . *
+ ***********************************************************************************/
+
+package com.projectswg.holocore.resources.support.objects.swg;
+
+import com.projectswg.common.data.CRC;
+import com.projectswg.common.data.encodables.mongo.MongoData;
+import com.projectswg.common.data.encodables.mongo.MongoPersistable;
+import com.projectswg.common.data.encodables.oob.StringId;
+import com.projectswg.common.data.encodables.tangible.PvpFlag;
+import com.projectswg.holocore.resources.support.data.persistable.SWGObjectFactory;
+import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
+import com.projectswg.holocore.resources.support.objects.swg.intangible.IntangibleObject;
+import com.projectswg.holocore.resources.support.objects.swg.player.PlayerObject;
+import com.projectswg.holocore.resources.support.objects.swg.tangible.OptionFlag;
+import com.projectswg.holocore.resources.support.objects.swg.tangible.TangibleObject;
+import com.projectswg.holocore.test.resources.GenericCreatureObject;
+import org.bson.Document;
+import org.bson.types.Binary;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class TestSWGPersistence {
+
+ @SuppressWarnings("unchecked")
+ private void assertContains(Map expected, Map actual) {
+ for (Entry e : expected.entrySet()) {
+ if (actual.get(e.getKey()) instanceof Map) {
+ assertContains((Map) e.getValue(), (Map) actual.get(e.getKey()));
+ } else if (actual.get(e.getKey()) instanceof Collection) {
+ Collection