Completion of Ace/Mulch Game Maker Galaxy

- Sharing/Loading/Rating games works
 - Challenge A Friend does NOT yet work
 - Multiplayer game (Lucky plugin 5) code commented out until completion
   of the rest of Galaxy work (challenge a friend)
This commit is contained in:
2023-05-31 13:12:11 -05:00
parent 7c09a41201
commit cf0d6c66d8
22 changed files with 524 additions and 101 deletions

View File

@@ -27,7 +27,7 @@ public class ArkOneController implements TcpHandler {
public static final String IP_ADDRESS = "127.0.0.1";
@Autowired
Server server;
private Server server;
// Services
@Autowired
@@ -38,22 +38,22 @@ public class ArkOneController implements TcpHandler {
// Plugins
@Autowired
BasePlugin basePlugin;
private BasePlugin basePlugin;
@Autowired
UserPlugin userPlugin;
private UserPlugin userPlugin;
@Autowired
GalaxyPlugin galaxyPlugin;
private GalaxyPlugin galaxyPlugin;
@Autowired
TrunkPlugin trunkPlugin;
private TrunkPlugin trunkPlugin;
@Autowired
MultiplayerPlugin multiplayerPlugin;
private MultiplayerPlugin multiplayerPlugin;
@Autowired
RainbowShootoutPlugin rainbowShootoutPlugin;
private RainbowShootoutPlugin rainbowShootoutPlugin;
@Override
public void receiveData(Connection connection, byte[] data) {
@@ -121,10 +121,10 @@ public class ArkOneController implements TcpHandler {
responses.add(userPlugin.DeleteBuddyResponse(commandInfo, connection));
break;
case "u_inv":
responses.add(userPlugin.InvitePlayer());
responses.add(userPlugin.InvitePlayer(commandInfo, connection, routingString.get(1)));
break;
case "u_inr":
responses.add(userPlugin.InviteBuddyResponse());
responses.add(userPlugin.InviteBuddyResponse(commandInfo, connection, routingString.get(1)));
break;
case "p":
responses.add(userPlugin.Ping(connection));
@@ -135,7 +135,7 @@ public class ArkOneController implements TcpHandler {
responses.add(rainbowShootoutPlugin.CharacterMove(commandInfo));
break;
case "bs":
responses.add(rainbowShootoutPlugin.BlockShot());
responses.add(rainbowShootoutPlugin.BlockShot(commandInfo, connection));
break;
// ---------------------------- Plugin 7 (Galaxy) --------------------------- \\
@@ -207,16 +207,16 @@ public class ArkOneController implements TcpHandler {
// ----------------------- Multiplayer (Shared by all) ---------------------- \\
case "lv":
responses.add(multiplayerPlugin.LeaveGame());
//responses.add(multiplayerPlugin.LeaveGame(routingString.get(1)));
break;
case "rp":
responses.add(multiplayerPlugin.ReadyPlay());
//responses.add(multiplayerPlugin.ReadyPlay());
break;
case "ms":
responses.add(multiplayerPlugin.MessageOpponent(commandInfo, connection, routingString.get(1)));
break;
case "pa":
responses.add(multiplayerPlugin.PlayAgain());
//responses.add(multiplayerPlugin.PlayAgain());
// ---------------------------- Conflict Commands --------------------------- \\
case "jn":

View File

@@ -115,8 +115,8 @@ public class GalaxyPlugin {
}
// Write to file
fileService.save(new MockMultipartFile("profile", "profile", "text/xml", connection.getSaveData().getBytes()),
profileName);
fileService.saveProfileFile(new MockMultipartFile("profile", "profile", "text/xml",
connection.getSaveData().getBytes()), profileName);
rootElement.appendChild(subElement);
} else {

View File

@@ -55,4 +55,8 @@ public class MultiplayerPlugin {
return ArkOneParser.RemoveXMLTag(resp);
}
//public String LeaveGame(String plugin) {
//}
}

View File

@@ -297,4 +297,71 @@ public class RainbowShootoutPlugin {
return "<notneeded/>";
}
public String BlockShot(Element element, Connection connection) throws ParserConfigurationException, TransformerException {
boolean blocked = false;
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document response = dBuilder.newDocument();
Element rootElement = response.createElement("h5_0");
response.appendChild(rootElement);
Element bsElement = response.createElement("bs");
bsElement.setAttribute("d", element.getAttribute("d"));
bsElement.setAttribute("lx", element.getAttribute("lx"));
bsElement.setAttribute("m", element.getAttribute("m"));
bsElement.setAttribute("c", element.getAttribute("c"));
bsElement.setAttribute("bid", element.getAttribute("bid"));
rootElement.appendChild(bsElement);
// For some reason, the Block Shot commmand is in charge of setting the score.
switch(element.getAttribute("c")) {
case "0": // Missed (Above net)
case "1": // Blocked
case "3": // Missed (Beside net)
blocked = true;
break;
}
RainbowShootout myRS = rainbowShootoutService.findByUserId(server.getConnectedUsers().get(
connection.getClientIdentifier()).getUUID()).orElse(null);
RainbowShootout oppRS = rainbowShootoutService.findByUserId(connection.getOpponentUID()).orElse(null);
if (myRS != null && oppRS != null) {
if (blocked) {
myRS.setScore(myRS.getScore() + 1);
rainbowShootoutService.save(myRS);
} else {
oppRS.setScore(myRS.getScore() + 1);
rainbowShootoutService.save(oppRS);
}
Element psElement = response.createElement("ps");
psElement.setAttribute("s", String.valueOf(oppRS.getScore()));
rootElement.appendChild(psElement);
Element osElement = response.createElement("os");
osElement.setAttribute("s", String.valueOf(myRS.getScore()));
rootElement.appendChild(osElement);
}
arkOneSender.SendToUser(connection.getOpponentConIDAsUUID(), ArkOneParser.RemoveXMLTag(response));
Document response1 = dBuilder.newDocument();
Element rootElement1 = response1.createElement("h5_0");
response1.appendChild(rootElement1);
Element psElement = response1.createElement("ps");
assert myRS != null;
psElement.setAttribute("s", String.valueOf(myRS.getScore()));
rootElement1.appendChild(psElement);
Element osElement = response1.createElement("os");
assert oppRS != null;
osElement.setAttribute("s", String.valueOf(oppRS.getScore()));
rootElement1.appendChild(osElement);
return ArkOneParser.RemoveXMLTag(response1);
}
}

View File

@@ -2,8 +2,19 @@ package com.icedberries.UBFunkeysServer.ArkOne.Plugins;
import com.icedberries.UBFunkeysServer.ArkOne.ArkOneParser;
import com.icedberries.UBFunkeysServer.DatabaseSetup.TrunkData;
import com.icedberries.UBFunkeysServer.domain.*;
import com.icedberries.UBFunkeysServer.service.*;
import com.icedberries.UBFunkeysServer.domain.Cleaning;
import com.icedberries.UBFunkeysServer.domain.Familiar;
import com.icedberries.UBFunkeysServer.domain.Item;
import com.icedberries.UBFunkeysServer.domain.Jammer;
import com.icedberries.UBFunkeysServer.domain.Mood;
import com.icedberries.UBFunkeysServer.domain.User;
import com.icedberries.UBFunkeysServer.service.CleaningService;
import com.icedberries.UBFunkeysServer.service.FamiliarService;
import com.icedberries.UBFunkeysServer.service.FileService;
import com.icedberries.UBFunkeysServer.service.ItemService;
import com.icedberries.UBFunkeysServer.service.JammerService;
import com.icedberries.UBFunkeysServer.service.MoodService;
import com.icedberries.UBFunkeysServer.service.UserService;
import javagrinko.spring.tcp.Connection;
import javagrinko.spring.tcp.Server;
import org.springframework.beans.factory.annotation.Autowired;
@@ -19,7 +30,11 @@ import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UncheckedIOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

View File

@@ -2,7 +2,9 @@ package com.icedberries.UBFunkeysServer.ArkOne.Plugins;
import com.icedberries.UBFunkeysServer.ArkOne.ArkOneParser;
import com.icedberries.UBFunkeysServer.ArkOne.ArkOneSender;
import com.icedberries.UBFunkeysServer.domain.Multiplayer.RainbowShootout;
import com.icedberries.UBFunkeysServer.domain.User;
import com.icedberries.UBFunkeysServer.service.RainbowShootoutService;
import com.icedberries.UBFunkeysServer.service.UserService;
import javagrinko.spring.tcp.Connection;
import javagrinko.spring.tcp.Server;
@@ -36,6 +38,9 @@ public class UserPlugin {
@Autowired
private ArkOneSender arkOneSender;
@Autowired
private RainbowShootoutService rainbowShootoutService;
public String RegisterUser(Element element) throws ParserConfigurationException, TransformerException {
String username = element.getAttribute("l");
String password = element.getAttribute("p");
@@ -445,6 +450,94 @@ public class UserPlugin {
return ArkOneParser.RemoveXMLTag(resp);
}
public String InvitePlayer(Element element, Connection connection, String plugin) throws ParserConfigurationException, TransformerException {
// Build message to send to other player
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document response = dBuilder.newDocument();
Element rootElement = response.createElement("u_inv");
rootElement.setAttribute("r", "0");
rootElement.setAttribute("av", element.getAttribute("av"));
rootElement.setAttribute("gid", element.getAttribute("gid"));
rootElement.setAttribute("bid", element.getAttribute("bid"));
rootElement.setAttribute("p", element.getAttribute("p"));
rootElement.setAttribute("t", element.getAttribute("t"));
rootElement.setAttribute("f", element.getAttribute("f"));
response.appendChild(rootElement);
User buddy = userService.findByUUID(Integer.valueOf(element.getAttribute("t"))).orElse(null);
if (buddy != null) {
switch (plugin) {
case "5":
// Create new entry for the invitee
RainbowShootout newRS = RainbowShootout.builder()
.username(buddy.getUsername())
.userId(buddy.getUUID())
.challenge(1)
.challenger(Integer.valueOf(element.getAttribute("f")))
.challengerInfo(element.getAttribute("av") + "|0")
.ready(0)
.score(0)
.build();
rainbowShootoutService.save(newRS);
// Update this players entry
RainbowShootout myRS = rainbowShootoutService.findByUserId(
server.getConnectedUsers().get(connection.getClientIdentifier()).getUUID()).orElse(null);
if (myRS != null) {
myRS.setChallenger(Integer.valueOf(element.getAttribute("t")));
rainbowShootoutService.save(myRS);
}
break;
default:
System.out.println("[ArkOne][ERROR] Unhandled plugin with ID [" + plugin + "] in UserPlugin.InvitePlayer!");
return "<notneeded />";
}
connection.setOpponentUID(buddy.getUUID());
connection.setOpponentConID(buddy.getConnectionId());
arkOneSender.SendToUser(connection.getOpponentConIDAsUUID(), ArkOneParser.RemoveXMLTag(response));
}
return "<notneeded />";
}
public String InviteBuddyResponse(Element element, Connection connection, String plugin)
throws ParserConfigurationException, TransformerException {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document response = dBuilder.newDocument();
Element rootElement = response.createElement("u_inr");
rootElement.setAttribute("r", "0");
rootElement.setAttribute("f", element.getAttribute("f"));
rootElement.setAttribute("t", element.getAttribute("t"));
rootElement.setAttribute("a", element.getAttribute("a"));
rootElement.setAttribute("p", element.getAttribute("p"));
response.appendChild(rootElement);
User fromUser = userService.findByUUID(Integer.valueOf(element.getAttribute("f"))).orElse(null);
if (fromUser != null) {
arkOneSender.SendToUser(fromUser.getConnectionId(), ArkOneParser.RemoveXMLTag(response));
switch (plugin) {
case "5":
rainbowShootoutService.findByUserId(server.getConnectedUsers().get(connection.getClientIdentifier()).getUUID())
.ifPresent(myRS -> rainbowShootoutService.delete(myRS));
break;
default:
System.out.println("[ArkOne][ERROR] Unhandled plugin with ID [" + plugin + "] in UserPlugin.InviteBuddyResponse!");
return "<notneeded />";
}
}
return "<notneeded />";
}
public String Ping(Connection connection) {
User user = server.getConnectedUsers().get(connection.getClientIdentifier());

View File

@@ -1,7 +1,15 @@
package com.icedberries.UBFunkeysServer.DatabaseSetup;
import com.icedberries.UBFunkeysServer.domain.*;
import com.icedberries.UBFunkeysServer.service.*;
import com.icedberries.UBFunkeysServer.domain.Cleaning;
import com.icedberries.UBFunkeysServer.domain.Familiar;
import com.icedberries.UBFunkeysServer.domain.Item;
import com.icedberries.UBFunkeysServer.domain.Jammer;
import com.icedberries.UBFunkeysServer.domain.Mood;
import com.icedberries.UBFunkeysServer.service.CleaningService;
import com.icedberries.UBFunkeysServer.service.FamiliarService;
import com.icedberries.UBFunkeysServer.service.ItemService;
import com.icedberries.UBFunkeysServer.service.JammerService;
import com.icedberries.UBFunkeysServer.service.MoodService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;

View File

@@ -4,7 +4,11 @@ import com.icedberries.UBFunkeysServer.ArkOne.ArkOneParser;
import com.icedberries.UBFunkeysServer.domain.Crib;
import com.icedberries.UBFunkeysServer.domain.Level;
import com.icedberries.UBFunkeysServer.domain.User;
import com.icedberries.UBFunkeysServer.service.*;
import com.icedberries.UBFunkeysServer.service.CribService;
import com.icedberries.UBFunkeysServer.service.EmailService;
import com.icedberries.UBFunkeysServer.service.FileService;
import com.icedberries.UBFunkeysServer.service.LevelService;
import com.icedberries.UBFunkeysServer.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -12,8 +16,10 @@ import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.HandlerMapping;
@@ -36,6 +42,7 @@ import java.io.InputStream;
import java.io.StringReader;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
@@ -63,7 +70,7 @@ public class GalaxyServer {
* This is only used as part of the updater to pass files to the client as requested via URL path
*/
@GetMapping("/**")
public void GalaxyGetResponse(HttpServletRequest request, HttpServletResponse response) {
public void GalaxyGetResponse(HttpServletRequest request, HttpServletResponse response) throws IOException {
String pathToFile = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
// Change the file path to use spaces
@@ -71,8 +78,58 @@ public class GalaxyServer {
System.out.println("[Galaxy][GET] Request for file: " + pathToFile);
Resource resource = new ClassPathResource("static/UpdateFiles/" + pathToFile);
int errorCode = 0;
// THIS IF CHECK IS PROBABLY NOT SAFE IF UPDATES ARE BEING DONE AS WELL
// See if the requested file is a gamemaker image file
if (pathToFile.startsWith("data/") && pathToFile.endsWith(".jpg")) {
byte[] imageData = null;
// Remove the "data/" since it already exists within fileService
pathToFile = pathToFile.replace("data/", "");
// See if the requested level image exists
Resource resource;
if (fileService.fileExists(pathToFile)) {
// The file exists - Load the file to the stream
resource = fileService.load(pathToFile);
} else {
// The file doesn't exist - Load the default image
resource = fileService.load("DEFAULT.jpg");
}
try {
// Copy the bytes to a byte[]
imageData = FileCopyUtils.copyToByteArray(resource.getInputStream());
} catch (IOException e) {
// Print the error to the log but let the data be null, so we return a bad data response
System.out.println("[Galaxy][GET] Exception thrown when loading image: ");
e.printStackTrace();
}
// Verify that something was loaded
if (imageData == null) {
System.out.println("[Galaxy][GET][ERROR] Game maker image not found!");
errorCode = HttpServletResponse.SC_NOT_FOUND;
response.sendError(errorCode);
return;
}
// Now that the image has been loaded we can send it back
// The file exists - Load the file to the stream
InputStream fileContentStream = new ByteArrayInputStream(imageData);
// Copy the stream to the response's output stream
IOUtils.copy(fileContentStream, response.getOutputStream());
// Flush the buffer
// MIGHT ALSO NEED TO SET THE FILE CONTENT LENGTH AS A HEADER
response.flushBuffer();
System.out.println("[Galaxy][GET] Game maker image sent!");
return;
}
Resource resource = new ClassPathResource("static/UpdateFiles/" + pathToFile);
try {
// Try to open the file as a resource
byte[] fileContent = org.apache.commons.io.IOUtils.toByteArray(resource.getInputStream());
@@ -118,6 +175,13 @@ public class GalaxyServer {
}
}
@PutMapping("/**")
public void GalaxyPutResponse(@RequestBody byte[] request, HttpServletRequest servletRequest) {
System.out.println("[Galaxy][PUT] Saving image file: " + servletRequest.getRequestURI());
fileService.saveGameMakerImage(request, servletRequest.getRequestURI().replace("data/", ""));
}
/**
* Handler for all POST Requests
* Postcards, LoadCrib and SaveCrib
@@ -165,6 +229,12 @@ public class GalaxyServer {
case "get_top":
response = getTop((Element)nodes.item(0));
break;
case "end_level":
response = endLevel((Element)nodes.item(0));
break;
case "search":
response = search((Element)nodes.item(0));
break;
default:
System.out.println("[Galaxy][POST][ERROR] Unhandled type of request for: " + command);
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
@@ -175,7 +245,7 @@ public class GalaxyServer {
// Return to the client
return response;
} catch (ParserConfigurationException | IOException | SAXException e) {
System.out.println("[Galaxy][POST][ERROR] Thrown Error: ");
//System.out.println("[Galaxy][POST][ERROR] Thrown Error: ");
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
@@ -347,7 +417,7 @@ public class GalaxyServer {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<get_sh_levels r=\"0\" >");
List<Level> sharedLevels = levelService.getLevelsByUserId(Integer.valueOf(element.getAttribute("uid")));
List<Level> sharedLevels = levelService.getLevelsByGameNameAndUserId(element.getAttribute("gn"), Integer.valueOf(element.getAttribute("uid")));
if (sharedLevels.isEmpty()) {
// No shared levels
@@ -359,9 +429,10 @@ public class GalaxyServer {
User creator = userService.findByUUID(level.getUserId()).orElse(null);
String creatorName = creator != null ? creator.getUsername() : "UNKNOWN";
stringBuilder.append("<level id=\"" + level.getId() + "\" sh=\"1\" ver=\"1\" n=\"" + level.getLevelName()
String levelData = "<level id=\"" + level.getId() + "\" sh=\"1\" ver=\"1\" n=\"" + level.getLevelName()
+ "\" v=\"" + level.getPlayCount() + "\" un=\"" + creatorName + "\" r=\"" + level.getRating()
+ "\" tnurl=\"" + level.getImagePath() + "\" pos=\"" + level.getPos() + "\"/>");
+ "\" tnurl=\"" + level.getImagePath() + "\" pos=\"" + level.getPos() + "\"/>";
stringBuilder.append(levelData);
}
}
stringBuilder.append("</get_sh_levels>");
@@ -373,21 +444,12 @@ public class GalaxyServer {
Integer levelId = Integer.valueOf(element.getAttribute("id"));
Level level = levelService.findLevelById(levelId).orElse(null);
String levelData = level == null ? "<level />" : level.getLevelData();
String levelData = level == null ? "<level tnurl=\"\" />" : level.getLevelData();
if (level == null) {
return new ResponseEntity<>("<get_level r=\"0\">" + levelData + "</get_level>", HttpStatus.OK);
}
User creator = userService.findByUUID(level.getUserId()).orElse(null);
String creatorName = creator != null ? creator.getUsername() : "UNKNOWN";
// This might need to also have tnurl in it later
String levelTag = "<level id=\"" + level.getId() + "\" sh=\"1\" ver=\"1\" n=\"" + level.getLevelName()
+ "\" v=\"" + level.getPlayCount() + "\" un=\"" + creatorName + "\" r=\"" + level.getRating()
+ "\" pos=\"" + level.getPos() + "\">";
return new ResponseEntity<>("<get_level r=\"0\">" + levelTag + levelData + "</level></get_level>", HttpStatus.OK);
return new ResponseEntity<>("<get_level r=\"0\">" + levelData + "</get_level>", HttpStatus.OK);
}
private ResponseEntity<String> addLevel(Element element) {
@@ -431,30 +493,31 @@ public class GalaxyServer {
responseCode = 1;
}
Level level = Level.builder()
.userId(uid)
.levelName(levelName)
.gameName(gameName)
.levelData(levelData)
.sharedDate(LocalDateTime.now())
.imagePath(tnurl)
.rating(0)
.ratingCount(0)
.playCount(0)
.pos(0)
.build();
Level savedLevel = levelService.save(level);
// If the level couldn't be parsed via the try-catch above, don't attempt to save it
Integer levelId = 0;
if (responseCode != 1) {
Level level = Level.builder()
.userId(uid)
.levelName(levelName)
.gameName(gameName)
.levelData(levelData)
.sharedDate(LocalDateTime.now())
.imagePath(tnurl)
.rating(0)
.ratingCount(0)
.playCount(0)
.pos(0)
.build();
if (savedLevel == null) {
responseCode = 2;
} else {
levelId = savedLevel.getId();
Level savedLevel = levelService.save(level);
if (savedLevel == null) {
responseCode = 2;
} else {
levelId = savedLevel.getId();
}
}
//TODO: THIS MIGHT BE WRONG?
//TODO: MIGHT NEED TO UPDATE TO ACCOUNT FOR UPDATING ALREADY UPLOADED LEVELS
return new ResponseEntity<>("<save_level r=\"" + responseCode + "\" n=\"" + levelName + "\" tnurl=\"" + tnurl + "\" id=\"" + levelId
+ "\" gn=\"" + gameName + "\" uid=\"" + uid + "\" />", HttpStatus.OK);
@@ -466,39 +529,49 @@ public class GalaxyServer {
String type = element.getAttribute("t");
int count = Integer.parseInt(element.getAttribute("c"));
List<Level> allLevelsWithName = levelService.findAllByGameName(gameName);
List<Level> allLevelsByGame = levelService.findAllByGameName(gameName);
List<Level> filteredLevels = new ArrayList<>();
int maxSize = Math.min(count, allLevelsWithName.size());
int maxSize = Math.min(count, allLevelsByGame.size());
// Switch based on what type of getTop it is
List<Level> sortedLevels;
switch (type) {
case "b":
// Best Levels
List<Level> sortedLevels = allLevelsWithName.stream()
sortedLevels = allLevelsByGame.stream()
.sorted(Comparator.comparing(Level::getRating))
.collect(Collectors.toList());
// Filter down to the top X levels
for (int i = 0; i < maxSize; i++) {
filteredLevels.add(sortedLevels.get(i));
}
Collections.reverse(sortedLevels);
break;
case "r":
// Random Level
sortedLevels = allLevelsByGame;
if (!sortedLevels.isEmpty()) {
Collections.shuffle(sortedLevels);
}
break;
case "l":
// Latest Levels
sortedLevels = allLevelsByGame.stream()
.sorted(Comparator.comparing(Level::getSharedDate))
.collect(Collectors.toList());
Collections.reverse(sortedLevels);
break;
default:
// Unhandled type
System.out.println("[Galaxy][POST] Unhandled type: " + type);
sortedLevels = new ArrayList<>();
break;
}
// Filter down to the top X levels
for (int i = 0; i < maxSize; i++) {
filteredLevels.add(sortedLevels.get(i));
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<get_top r=\"0\" c=\"" + maxSize + "\" t=\"" + type + "\" gn=\"" + gameName + "\">");
String openingTag = "<get_top r=\"0\" c=\"" + maxSize + "\" t=\"" + type + "\" gn=\"" + gameName + "\">";
stringBuilder.append(openingTag);
if (filteredLevels.isEmpty()) {
// No levels match
@@ -509,10 +582,10 @@ public class GalaxyServer {
User creator = userService.findByUUID(level.getUserId()).orElse(null);
String creatorName = creator != null ? creator.getUsername() : "UNKNOWN";
stringBuilder.append("<level id=\"" + level.getId() + "\" sh=\"1\" ver=\"1\" n=\"" + level.getLevelName()
String levelData = "<level id=\"" + level.getId() + "\" uid=\"" + level.getUserId() + "\" sh=\"1\" ver=\"1\" n=\"" + level.getLevelName()
+ "\" v=\"" + level.getPlayCount() + "\" un=\"" + creatorName + "\" r=\"" + level.getRating()
+ "\" tnurl=\"" + level.getImagePath() + "\" pos=\"" + level.getPos() + "\"/>");
//stringBuilder.append("<level id=\"" + level.getId() + "\" uid=\"" + level.getUserId() + "\" n=\"" + level.getLevelName() + "\"/>");
+ "\" tnurl=\"" + level.getImagePath() + "\" pos=\"" + level.getPos() + "\"/>";
stringBuilder.append(levelData);
}
}
@@ -521,14 +594,82 @@ public class GalaxyServer {
return new ResponseEntity<>(stringBuilder.toString(), HttpStatus.OK);
}
/*
// Game to get
String gamePath = element.getAttribute("tnpath").replaceFirst("data/", "");
// Load the users file
Resource resource = fileService.load(gamePath + "/uglevels.rdf");
// Load their save to a string
String content = "";
byte[] targetArray = org.apache.commons.io.IOUtils.toByteArray(resource.getInputStream());
content = RDFUtil.decode(new String(targetArray, StandardCharsets.ISO_8859_1));
*/
private ResponseEntity<String> endLevel(Element element) {
Integer levelId = Integer.valueOf(element.getAttribute("id"));
Level level = levelService.findLevelById(levelId).orElse(null);
if (level != null) {
// INCREMENT PLAY COUNT
level.setPlayCount(level.getPlayCount() + 1);
// UPDATE RATING
// Get the current level ratings
Integer ratingCount = level.getRatingCount();
Double rating = level.getRatingRaw();
// Grab the rating submitted by the user
Integer submittedRating = Integer.valueOf(element.getAttribute("rat"));
// Calculate the new rating
double newRating = rating + submittedRating;
Integer newRatingCount = ratingCount + 1;
// Store them back into the level object
level.setRating(newRating);
level.setRatingCount(newRatingCount);
level.setPos(level.getPos() + submittedRating);
// RE-SAVE THE LEVEL
levelService.save(level);
}
String uid = element.getAttribute("uid");
String id = element.getAttribute("id");
String response = "<end_level r=\"0\" end=\"1\" uid=\"" + uid + "\" id=\"" + id + "\" />";
return new ResponseEntity<>(response, HttpStatus.OK);
}
private ResponseEntity<String> search(Element element) {
StringBuilder response = new StringBuilder();
// Add the starting tag
String openingTag = "<search r=\"0\">";
response.append(openingTag);
String gameName = element.getAttribute("gn");
String searchType = element.getAttribute("t");
String searchKeyword = element.getAttribute("w");
List<Level> searchResults;
switch(searchType) {
case "k": // KEYWORD
searchResults = levelService.findAllByGameNameAndKeyword(gameName, searchKeyword);
break;
case "a": // AUTHOR
searchResults = levelService.findAllByGameNameAndAuthor(gameName, searchKeyword);
break;
case "g": // LEVEL NAME
searchResults = levelService.findAllByGameNameAndLevelName(gameName, searchKeyword);
break;
default:
System.out.println("[GALAXY][POST] Unhandled Game Maker search type: " + searchType);
searchResults = new ArrayList<>();
break;
}
for (Level level : searchResults) {
User creator = userService.findByUUID(level.getUserId()).orElse(null);
String creatorName = creator != null ? creator.getUsername() : "UNKNOWN";
String levelData = "<level id=\"" + level.getId() + "\" sh=\"1\" ver=\"1\" n=\"" + level.getLevelName()
+ "\" v=\"" + level.getPlayCount() + "\" un=\"" + creatorName + "\" r=\"" + level.getRating()
+ "\" tnurl=\"" + level.getImagePath() + "\" pos=\"" + level.getPos() + "\"/>";
response.append(levelData);
}
// Add the closing tag
response.append("</search>");
return new ResponseEntity<>(response.toString(), HttpStatus.OK);
}
}

View File

@@ -1,7 +1,11 @@
package com.icedberries.UBFunkeysServer.domain;
import com.icedberries.UBFunkeysServer.config.TableNames;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;

View File

@@ -8,7 +8,12 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Getter
@Setter

View File

@@ -1,7 +1,11 @@
package com.icedberries.UBFunkeysServer.domain;
import com.icedberries.UBFunkeysServer.config.TableNames;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;

View File

@@ -1,7 +1,11 @@
package com.icedberries.UBFunkeysServer.domain;
import com.icedberries.UBFunkeysServer.config.TableNames;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;

View File

@@ -1,7 +1,11 @@
package com.icedberries.UBFunkeysServer.domain;
import com.icedberries.UBFunkeysServer.config.TableNames;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;

View File

@@ -1,10 +1,19 @@
package com.icedberries.UBFunkeysServer.domain;
import com.icedberries.UBFunkeysServer.config.TableNames;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.LocalDateTime;
@Getter
@@ -42,6 +51,8 @@ public class Level {
private Integer playCount;
// We aren't 100% sure what this was used for originally,
// so now it will just hold the total number of stars ever received
private Integer pos;
public Integer getRating() {
@@ -52,4 +63,8 @@ public class Level {
double average = rating / ratingCount;
return (int)Math.rint(average);
}
public Double getRatingRaw() {
return rating;
}
}

View File

@@ -1,7 +1,11 @@
package com.icedberries.UBFunkeysServer.domain;
import com.icedberries.UBFunkeysServer.config.TableNames;
import lombok.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;

View File

@@ -15,8 +15,8 @@ public interface LevelRepository extends CrudRepository<Level, Integer> {
@Query("select level from Level level where level.levelName = :levelName")
Optional<Level> getLevelByName(@Param("levelName") String levelName);
@Query("select level from Level level where level.userId = :userId")
List<Level> getLevelsByUserId(@Param("userId") Integer userId);
@Query("select level from Level level where level.gameName = :gameName and level.userId = :userId")
List<Level> getLevelsByGameNameAndUserId(@Param("gameName") String gameName, @Param("userId") Integer userId);
Boolean existsByLevelNameAndGameName(String levelName, String gameName);
@@ -25,4 +25,21 @@ public interface LevelRepository extends CrudRepository<Level, Integer> {
@Query("select level from Level level where level.id = :id")
Optional<Level> findLevelById(@Param("id") Integer id);
@Query("select level from Level level" +
" left join User user on level.userId = user.UUID" +
" where level.gameName = :gameName" +
" and ((level.levelName like %:keyword%) or (user.username like %:keyword%))")
List<Level> findAllByGameNameAndKeyword(@Param("gameName") String gameName, @Param("keyword") String keyword);
@Query("select level from Level level" +
" left join User user on level.userId = user.UUID" +
" where level.gameName = :gameName" +
" and user.username like %:author%")
List<Level> findAllByGameNameAndAuthor(@Param("gameName") String gameName, @Param("author") String author);
@Query("select level from Level level" +
" where level.gameName = :gameName" +
" and level.levelName like %:levelName%")
List<Level> findAllByGameNameAndLevelName(@Param("gameName") String gameName, @Param("levelName") String levelName);
}

View File

@@ -5,7 +5,9 @@ import org.springframework.web.multipart.MultipartFile;
public interface FileService {
void save(MultipartFile file, String subDir);
void saveProfileFile(MultipartFile file, String subDir);
void saveGameMakerImage(byte[] imageData, String subDirAndFileName);
Resource load(String path);

View File

@@ -9,7 +9,7 @@ public interface LevelService {
Optional<Level> getLevelByName(String levelName);
List<Level> getLevelsByUserId(Integer userId);
List<Level> getLevelsByGameNameAndUserId(String gameName, Integer userId);
Boolean existsByLevelNameAndGameName(String levelName, String gameVersion);
@@ -18,4 +18,10 @@ public interface LevelService {
List<Level> findAllByGameName(String gameName);
Optional<Level> findLevelById(Integer id);
List<Level> findAllByGameNameAndKeyword(String gameName, String keyword);
List<Level> findAllByGameNameAndAuthor(String gameName, String author);
List<Level> findAllByGameNameAndLevelName(String gameName, String levelName);
}

View File

@@ -12,8 +12,6 @@ import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;
import javax.mail.Message;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
@Service("emailService")

View File

@@ -8,7 +8,9 @@ import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -27,12 +29,28 @@ public class FileServiceImpl implements FileService {
}
@Override
public void save(MultipartFile file, String subDir) {
public void saveGameMakerImage(byte[] imageData, String subDirAndFileName) {
try {
String path = subDirAndFileName.substring(0, subDirAndFileName.lastIndexOf("/"));
Path folderPath = Paths.get(fileStorageLocation.toString(), path);
Files.createDirectories(folderPath);
InputStream imageContentStream = new ByteArrayInputStream(imageData);
Path pathToFile = Paths.get(fileStorageLocation.toString(), subDirAndFileName);
Files.copy(imageContentStream, pathToFile, StandardCopyOption.REPLACE_EXISTING);
System.out.println("[Galaxy][PUT] Image saved successfully");
} catch(Exception e) {
throw new RuntimeException("Could not store the profile file. Error: " + e.getMessage());
}
}
@Override
public void saveProfileFile(MultipartFile file, String subDir) {
try {
Files.createDirectories(fileStorageLocation.resolve(subDir));
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());
throw new RuntimeException("Could not store the profile file. Error: " + e.getMessage());
}
}

View File

@@ -21,8 +21,8 @@ public class LevelServiceImpl implements LevelService {
}
@Override
public List<Level> getLevelsByUserId(Integer userId) {
return levelRepository.getLevelsByUserId(userId);
public List<Level> getLevelsByGameNameAndUserId(String gameName, Integer userId) {
return levelRepository.getLevelsByGameNameAndUserId(gameName, userId);
}
@Override
@@ -44,4 +44,19 @@ public class LevelServiceImpl implements LevelService {
public Optional<Level> findLevelById(Integer id) {
return levelRepository.findLevelById(id);
}
@Override
public List<Level> findAllByGameNameAndKeyword(String gameName, String keyword) {
return levelRepository.findAllByGameNameAndKeyword(gameName, keyword);
}
@Override
public List<Level> findAllByGameNameAndAuthor(String gameName, String author) {
return levelRepository.findAllByGameNameAndAuthor(gameName, author);
}
@Override
public List<Level> findAllByGameNameAndLevelName(String gameName, String levelName) {
return levelRepository.findAllByGameNameAndLevelName(gameName, levelName);
}
}

View File

@@ -3,7 +3,6 @@ package javagrinko.spring.tcp;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.UUID;
public interface Connection {