diff --git a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/ArkOneController.java b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/ArkOneController.java index fd8f86a..3976806 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/ArkOneController.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/ArkOneController.java @@ -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": 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 9e891a0..8193467 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/GalaxyPlugin.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/GalaxyPlugin.java @@ -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 { diff --git a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/Multiplayer/MultiplayerPlugin.java b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/Multiplayer/MultiplayerPlugin.java index a0d5400..b26ab41 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/Multiplayer/MultiplayerPlugin.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/Multiplayer/MultiplayerPlugin.java @@ -55,4 +55,8 @@ public class MultiplayerPlugin { return ArkOneParser.RemoveXMLTag(resp); } + + //public String LeaveGame(String plugin) { + + //} } diff --git a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/Multiplayer/RainbowShootoutPlugin.java b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/Multiplayer/RainbowShootoutPlugin.java index 0c26d5a..e57a64e 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/Multiplayer/RainbowShootoutPlugin.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/Multiplayer/RainbowShootoutPlugin.java @@ -297,4 +297,71 @@ public class RainbowShootoutPlugin { return ""; } + + 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); + } } diff --git a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/TrunkPlugin.java b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/TrunkPlugin.java index 96d4182..8a9c66e 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/TrunkPlugin.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/TrunkPlugin.java @@ -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; diff --git a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/UserPlugin.java b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/UserPlugin.java index ab52e00..f591407 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/UserPlugin.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/ArkOne/Plugins/UserPlugin.java @@ -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 ""; + } + + connection.setOpponentUID(buddy.getUUID()); + connection.setOpponentConID(buddy.getConnectionId()); + arkOneSender.SendToUser(connection.getOpponentConIDAsUUID(), ArkOneParser.RemoveXMLTag(response)); + } + + return ""; + } + + 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 ""; + } + } + + return ""; + } + public String Ping(Connection connection) { User user = server.getConnectedUsers().get(connection.getClientIdentifier()); diff --git a/src/main/java/com/icedberries/UBFunkeysServer/DatabaseSetup/TrunkData.java b/src/main/java/com/icedberries/UBFunkeysServer/DatabaseSetup/TrunkData.java index cef755c..6b50ede 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/DatabaseSetup/TrunkData.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/DatabaseSetup/TrunkData.java @@ -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; diff --git a/src/main/java/com/icedberries/UBFunkeysServer/Galaxy/GalaxyServer.java b/src/main/java/com/icedberries/UBFunkeysServer/Galaxy/GalaxyServer.java index 1a72f6f..33903c2 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/Galaxy/GalaxyServer.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/Galaxy/GalaxyServer.java @@ -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(""); - List sharedLevels = levelService.getLevelsByUserId(Integer.valueOf(element.getAttribute("uid"))); + List 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(""); + + "\" tnurl=\"" + level.getImagePath() + "\" pos=\"" + level.getPos() + "\"/>"; + stringBuilder.append(levelData); } } stringBuilder.append(""); @@ -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.getLevelData(); + String levelData = level == null ? "" : level.getLevelData(); if (level == null) { return new ResponseEntity<>("" + levelData + "", 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 = ""; - - return new ResponseEntity<>("" + levelTag + levelData + "", HttpStatus.OK); + return new ResponseEntity<>("" + levelData + "", HttpStatus.OK); } private ResponseEntity 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<>("", HttpStatus.OK); @@ -466,39 +529,49 @@ public class GalaxyServer { String type = element.getAttribute("t"); int count = Integer.parseInt(element.getAttribute("c")); - List allLevelsWithName = levelService.findAllByGameName(gameName); + List allLevelsByGame = levelService.findAllByGameName(gameName); List 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 sortedLevels; switch (type) { case "b": // Best Levels - List 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(""); + String openingTag = ""; + 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(""); - //stringBuilder.append(""); + + "\" 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 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 = ""; + return new ResponseEntity<>(response, HttpStatus.OK); + } + + private ResponseEntity search(Element element) { + StringBuilder response = new StringBuilder(); + + // Add the starting tag + String openingTag = ""; + response.append(openingTag); + + String gameName = element.getAttribute("gn"); + String searchType = element.getAttribute("t"); + String searchKeyword = element.getAttribute("w"); + + List 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 = ""; + response.append(levelData); + } + + // Add the closing tag + response.append(""); + + return new ResponseEntity<>(response.toString(), HttpStatus.OK); + } } diff --git a/src/main/java/com/icedberries/UBFunkeysServer/domain/Cleaning.java b/src/main/java/com/icedberries/UBFunkeysServer/domain/Cleaning.java index 453fe69..cc87197 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/domain/Cleaning.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/domain/Cleaning.java @@ -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; diff --git a/src/main/java/com/icedberries/UBFunkeysServer/domain/Crib.java b/src/main/java/com/icedberries/UBFunkeysServer/domain/Crib.java index bed024d..a08911d 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/domain/Crib.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/domain/Crib.java @@ -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 diff --git a/src/main/java/com/icedberries/UBFunkeysServer/domain/Familiar.java b/src/main/java/com/icedberries/UBFunkeysServer/domain/Familiar.java index d4456b3..1a8304f 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/domain/Familiar.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/domain/Familiar.java @@ -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; diff --git a/src/main/java/com/icedberries/UBFunkeysServer/domain/Item.java b/src/main/java/com/icedberries/UBFunkeysServer/domain/Item.java index 5bd53e2..5dd08bd 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/domain/Item.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/domain/Item.java @@ -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; diff --git a/src/main/java/com/icedberries/UBFunkeysServer/domain/Jammer.java b/src/main/java/com/icedberries/UBFunkeysServer/domain/Jammer.java index c38d8eb..54058e6 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/domain/Jammer.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/domain/Jammer.java @@ -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; diff --git a/src/main/java/com/icedberries/UBFunkeysServer/domain/Level.java b/src/main/java/com/icedberries/UBFunkeysServer/domain/Level.java index 71186a5..5fefdd2 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/domain/Level.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/domain/Level.java @@ -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; + } } diff --git a/src/main/java/com/icedberries/UBFunkeysServer/domain/Mood.java b/src/main/java/com/icedberries/UBFunkeysServer/domain/Mood.java index e7de562..d024a6c 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/domain/Mood.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/domain/Mood.java @@ -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; diff --git a/src/main/java/com/icedberries/UBFunkeysServer/repository/LevelRepository.java b/src/main/java/com/icedberries/UBFunkeysServer/repository/LevelRepository.java index 9ebbac7..4b14f9b 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/repository/LevelRepository.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/repository/LevelRepository.java @@ -15,8 +15,8 @@ public interface LevelRepository extends CrudRepository { @Query("select level from Level level where level.levelName = :levelName") Optional getLevelByName(@Param("levelName") String levelName); - @Query("select level from Level level where level.userId = :userId") - List getLevelsByUserId(@Param("userId") Integer userId); + @Query("select level from Level level where level.gameName = :gameName and level.userId = :userId") + List getLevelsByGameNameAndUserId(@Param("gameName") String gameName, @Param("userId") Integer userId); Boolean existsByLevelNameAndGameName(String levelName, String gameName); @@ -25,4 +25,21 @@ public interface LevelRepository extends CrudRepository { @Query("select level from Level level where level.id = :id") Optional 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 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 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 findAllByGameNameAndLevelName(@Param("gameName") String gameName, @Param("levelName") String levelName); } diff --git a/src/main/java/com/icedberries/UBFunkeysServer/service/FileService.java b/src/main/java/com/icedberries/UBFunkeysServer/service/FileService.java index 62e3854..03d89b8 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/service/FileService.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/service/FileService.java @@ -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); diff --git a/src/main/java/com/icedberries/UBFunkeysServer/service/LevelService.java b/src/main/java/com/icedberries/UBFunkeysServer/service/LevelService.java index cff937d..1b0ba37 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/service/LevelService.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/service/LevelService.java @@ -9,7 +9,7 @@ public interface LevelService { Optional getLevelByName(String levelName); - List getLevelsByUserId(Integer userId); + List getLevelsByGameNameAndUserId(String gameName, Integer userId); Boolean existsByLevelNameAndGameName(String levelName, String gameVersion); @@ -18,4 +18,10 @@ public interface LevelService { List findAllByGameName(String gameName); Optional findLevelById(Integer id); + + List findAllByGameNameAndKeyword(String gameName, String keyword); + + List findAllByGameNameAndAuthor(String gameName, String author); + + List findAllByGameNameAndLevelName(String gameName, String levelName); } diff --git a/src/main/java/com/icedberries/UBFunkeysServer/service/impl/EmailServiceImpl.java b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/EmailServiceImpl.java index a17b9ab..3fbaa96 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/service/impl/EmailServiceImpl.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/EmailServiceImpl.java @@ -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") 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 e302312..49c052c 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/service/impl/FileServiceImpl.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/FileServiceImpl.java @@ -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()); } } diff --git a/src/main/java/com/icedberries/UBFunkeysServer/service/impl/LevelServiceImpl.java b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/LevelServiceImpl.java index 06273c1..7628e75 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/service/impl/LevelServiceImpl.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/LevelServiceImpl.java @@ -21,8 +21,8 @@ public class LevelServiceImpl implements LevelService { } @Override - public List getLevelsByUserId(Integer userId) { - return levelRepository.getLevelsByUserId(userId); + public List getLevelsByGameNameAndUserId(String gameName, Integer userId) { + return levelRepository.getLevelsByGameNameAndUserId(gameName, userId); } @Override @@ -44,4 +44,19 @@ public class LevelServiceImpl implements LevelService { public Optional findLevelById(Integer id) { return levelRepository.findLevelById(id); } + + @Override + public List findAllByGameNameAndKeyword(String gameName, String keyword) { + return levelRepository.findAllByGameNameAndKeyword(gameName, keyword); + } + + @Override + public List findAllByGameNameAndAuthor(String gameName, String author) { + return levelRepository.findAllByGameNameAndAuthor(gameName, author); + } + + @Override + public List findAllByGameNameAndLevelName(String gameName, String levelName) { + return levelRepository.findAllByGameNameAndLevelName(gameName, levelName); + } } diff --git a/src/main/java/javagrinko/spring/tcp/Connection.java b/src/main/java/javagrinko/spring/tcp/Connection.java index 3396c76..305263e 100644 --- a/src/main/java/javagrinko/spring/tcp/Connection.java +++ b/src/main/java/javagrinko/spring/tcp/Connection.java @@ -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 {