diff --git a/pom.xml b/pom.xml
index aea6ec8..1c7c280 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,11 @@
spring-boot-configuration-processor
true
+
+ org.springframework
+ spring-test
+ 5.3.20
+
diff --git a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/ArkOneController.java b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/ArkOneController.java
index eb84357..423cd74 100644
--- a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/ArkOneController.java
+++ b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/ArkOneController.java
@@ -95,6 +95,12 @@ public class ArkOneController implements TcpHandler {
case "vsu":
responses.add(galaxyPlugin.VersionStatisticsRequest());
break;
+ case "sp":
+ responses.add(galaxyPlugin.SaveProfile(commandInfo, connection));
+ break;
+ case "spp":
+ responses.add(galaxyPlugin.SaveProfilePart(commandInfo, connection));
+ break;
// Plugin 10 (Trunk)
diff --git a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/GalaxyPlugin.java b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/GalaxyPlugin.java
index a639fb5..6328bea 100644
--- a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/GalaxyPlugin.java
+++ b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/GalaxyPlugin.java
@@ -1,16 +1,91 @@
package com.icedberries.UBFunkeysServer.ArkOne.Plugins;
+import com.icedberries.UBFunkeysServer.ArkOne.ArkOneParser;
+import com.icedberries.UBFunkeysServer.service.FileService;
+import javagrinko.spring.tcp.Connection;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import java.io.IOException;
+import java.io.StringReader;
@Service
public class GalaxyPlugin {
+ @Autowired
+ FileService fileService;
+
public String LoadProfileVersion() {
- //TODO: IMPLEMENT THIS WITH PROFILE SAVING
+ //TODO: IMPLEMENT THIS AFTER PROFILE SAVING
return "";
}
public String VersionStatisticsRequest() {
return "";
}
+
+ public String SaveProfile(Element element, Connection connection) {
+ // Set the number of chunks left to save
+ //TODO: VERIFY THIS ATTRIBUTE NAME
+ connection.setChunksLeft(Integer.valueOf(element.getAttribute("c")));
+
+ // Clear save data
+ connection.setSaveData("");
+
+ return "";
+ }
+
+ public String SaveProfilePart(Element element, Connection connection) throws ParserConfigurationException,
+ TransformerException, IOException, SAXException {
+ // Start of response
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+ Document resp = dBuilder.newDocument();
+ Element rootElement = resp.createElement("h7_0");
+ resp.appendChild(rootElement);
+
+ // Continue appending to the saveData
+ //TODO: VERIFY THIS ELEMENT ATTRIBUTE
+ connection.setSaveData(element.getAttribute("v") + connection.getSaveData());
+
+ if (connection.getChunksLeft() == 1) {
+ Element subElement = resp.createElement("sp");
+
+ // Parse the current save
+ Document save = dBuilder.parse(new InputSource(new StringReader(connection.getSaveData())));
+ save.getDocumentElement().normalize();
+ Element rootSave = (Element)save.getFirstChild();
+
+ String profileName = rootSave.getAttribute("gname");
+ if (!rootSave.getAttribute("sid").equals("")) {
+ subElement.setAttribute("v", String.valueOf(Integer.parseInt(rootSave.getAttribute("sid")) + 1));
+ } else {
+ subElement.setAttribute("v", "1");
+ }
+
+ // Write to file
+ fileService.save(new MockMultipartFile("profile", "profile", "text/xml", connection.getSaveData().getBytes()),
+ profileName);
+
+ rootElement.appendChild(subElement);
+ } else {
+ Element subElement = resp.createElement("rr");
+ rootElement.appendChild(subElement);
+
+ // Decrease the number of chunks by 1
+ connection.setChunksLeft(connection.getChunksLeft() - 1);
+ }
+
+ // Build response
+ return ArkOneParser.RemoveXMLTag(resp);
+ }
}
diff --git a/src/main/java/com/icedberries/UBFunkeysServer/service/FileService.java b/src/main/java/com/icedberries/UBFunkeysServer/service/FileService.java
index 2cc5283..60d7d58 100644
--- a/src/main/java/com/icedberries/UBFunkeysServer/service/FileService.java
+++ b/src/main/java/com/icedberries/UBFunkeysServer/service/FileService.java
@@ -5,7 +5,7 @@ import org.springframework.web.multipart.MultipartFile;
public interface FileService {
- void save(MultipartFile file);
+ void save(MultipartFile file, String subDir);
Resource load(String filename);
}
diff --git a/src/main/java/com/icedberries/UBFunkeysServer/service/impl/FileServiceImpl.java b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/FileServiceImpl.java
index 0f9f9ff..fc9a3ee 100644
--- a/src/main/java/com/icedberries/UBFunkeysServer/service/impl/FileServiceImpl.java
+++ b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/FileServiceImpl.java
@@ -13,6 +13,7 @@ import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
@Service
public class FileServiceImpl implements FileService {
@@ -26,9 +27,9 @@ public class FileServiceImpl implements FileService {
}
@Override
- public void save(MultipartFile file) {
+ public void save(MultipartFile file, String subDir) {
try {
- Files.copy(file.getInputStream(), fileStorageLocation.resolve(file.getOriginalFilename()));
+ Files.copy(file.getInputStream(), fileStorageLocation.resolve(subDir).resolve(file.getOriginalFilename()), StandardCopyOption.REPLACE_EXISTING);
} catch(Exception e) {
throw new RuntimeException("Could not store the file. Error: " + e.getMessage());
}
diff --git a/src/main/java/javagrinko/spring/tcp/Connection.java b/src/main/java/javagrinko/spring/tcp/Connection.java
index b37d7fe..ebd8604 100644
--- a/src/main/java/javagrinko/spring/tcp/Connection.java
+++ b/src/main/java/javagrinko/spring/tcp/Connection.java
@@ -13,6 +13,11 @@ public interface Connection {
void close() throws IOException;
UUID getClientIdentifier();
void setClientIdentifier(UUID newId);
+ Integer getChunksLeft();
+ void setChunksLeft(Integer chunksLeft);
+
+ String getSaveData();
+ void setSaveData(String saveData);
interface Listener {
void messageReceived(Connection connection, byte[] bytes)
throws InvocationTargetException, IllegalAccessException;
diff --git a/src/main/java/javagrinko/spring/tcp/TcpConnection.java b/src/main/java/javagrinko/spring/tcp/TcpConnection.java
index 0c6e40f..be3a862 100644
--- a/src/main/java/javagrinko/spring/tcp/TcpConnection.java
+++ b/src/main/java/javagrinko/spring/tcp/TcpConnection.java
@@ -20,8 +20,9 @@ public class TcpConnection implements Connection {
private OutputStream outputStream;
private Socket socket;
private List listeners = new CopyOnWriteArrayList<>();
-
private UUID clientIdentifier = null;
+ private Integer chunksLeft = 0;
+ private String saveData = "";
TcpConnection(Socket socket) {
this.socket = socket;
@@ -106,4 +107,24 @@ public class TcpConnection implements Connection {
public void setClientIdentifier(UUID newId) {
this.clientIdentifier = newId;
}
+
+ @Override
+ public Integer getChunksLeft() {
+ return chunksLeft;
+ }
+
+ @Override
+ public void setChunksLeft(Integer chunksLeft) {
+ this.chunksLeft = chunksLeft;
+ }
+
+ @Override
+ public String getSaveData() {
+ return saveData;
+ }
+
+ @Override
+ public void setSaveData(String saveData) {
+ this.saveData = saveData;
+ }
}