diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/ApiException.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/ApiException.java new file mode 100644 index 000000000..2239245f7 --- /dev/null +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/ApiException.java @@ -0,0 +1,5 @@ +package mineplex.core.common.api; + +public class ApiException extends Exception +{ +} diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/ApiWebCall.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/ApiWebCall.java index e59cb7f76..faf5b7d43 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/ApiWebCall.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/ApiWebCall.java @@ -1,6 +1,11 @@ package mineplex.core.common.api; import com.google.gson.Gson; + +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.io.IOUtils; +import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.CloseableHttpResponse; @@ -13,10 +18,18 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; import org.apache.http.protocol.HTTP; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import mineplex.core.common.api.enderchest.HashesNotEqualException; /** * @author Shaun Bennett @@ -28,6 +41,11 @@ public class ApiWebCall private PoolingHttpClientConnectionManager _cm; private CloseableHttpClient _httpClient; + public ApiWebCall(String url) + { + this(url, new Gson()); + } + public ApiWebCall(String url, Gson gson) { _url = url; @@ -89,6 +107,50 @@ public class ApiWebCall return returnData; } + public File getFile(String resource, String savePath) throws HashesNotEqualException, IOException + { + HttpGet httpGet = new HttpGet(_url + resource); + File file = new File(savePath); + + FileOutputStream fos = null; + DigestInputStream dis = null; + try (CloseableHttpResponse response = _httpClient.execute(httpGet)) + { + MessageDigest md = DigestUtils.getMd5Digest(); + HttpEntity entity = response.getEntity(); + dis = new DigestInputStream(entity.getContent(), md); + fos = new FileOutputStream(file); + IOUtils.copy(dis, fos); + + String calculatedHash = Hex.encodeHexString(md.digest()); + Header hashHeader = response.getFirstHeader("Content-MD5"); + + if (hashHeader != null && !calculatedHash.equals(hashHeader.getValue())) + { + file.delete(); + throw new HashesNotEqualException(hashHeader.getValue(), calculatedHash); + } + } finally { + try + { + if (fos != null) fos.close(); + } catch (IOException e) + { + e.printStackTrace(); + } + + try + { + if (dis != null) dis.close(); + } catch (IOException e) + { + e.printStackTrace(); + } + } + + return file; + } + private T parseResponse(CloseableHttpResponse response, Type type) throws IOException { HttpEntity entity = response.getEntity(); diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/enderchest/EnderchestWorldLoader.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/enderchest/EnderchestWorldLoader.java new file mode 100644 index 000000000..e819a1109 --- /dev/null +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/enderchest/EnderchestWorldLoader.java @@ -0,0 +1,44 @@ +package mineplex.core.common.api.enderchest; + +import java.io.File; +import java.io.IOException; + +import mineplex.core.common.api.ApiWebCall; +import mineplex.core.common.util.ZipUtil; +import mineplex.core.common.timing.TimingManager; + +/** + * Load worlds from the `enderchest` microservice + */ +public class EnderchestWorldLoader +{ + private static final String TIMINGS_PREFIX = "Enderchest LoadMap::"; + private ApiWebCall _webCall; + + public EnderchestWorldLoader() + { + _webCall = new ApiWebCall("http://localhost:3000/"); + } + + public void loadMap(String mapType, String folder) throws HashesNotEqualException, IOException + { + TimingManager.start(TIMINGS_PREFIX + "DownloadMap"); + String fileName = mapType + "_map.zip"; + File f = _webCall.getFile(mapType, fileName); + TimingManager.stop(TIMINGS_PREFIX + "DownloadMap"); + + TimingManager.start(TIMINGS_PREFIX + "CreateFolders"); + new File(folder).mkdir(); + new File(folder + java.io.File.separator + "region").mkdir(); + new File(folder + java.io.File.separator + "data").mkdir(); + TimingManager.stop(TIMINGS_PREFIX + "CreateFolders"); + + TimingManager.start(TIMINGS_PREFIX + "UnzipToDirectory"); + ZipUtil.UnzipToDirectory(f.getAbsolutePath(), folder); + TimingManager.stop(TIMINGS_PREFIX + "UnzipToDirectory"); + + TimingManager.start(TIMINGS_PREFIX + "DeleteZip"); + f.delete(); + TimingManager.stop(TIMINGS_PREFIX + "DeleteZip"); + } +} diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/enderchest/HashesNotEqualException.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/enderchest/HashesNotEqualException.java new file mode 100644 index 000000000..f5920b26f --- /dev/null +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/api/enderchest/HashesNotEqualException.java @@ -0,0 +1,25 @@ +package mineplex.core.common.api.enderchest; + +import mineplex.core.common.api.ApiException; + +public class HashesNotEqualException extends ApiException +{ + private String _hashFromServer; + private String _calculatedHash; + + public HashesNotEqualException(String hashFromServer, String calculatedHash) + { + _hashFromServer = hashFromServer; + _calculatedHash = calculatedHash; + } + + public String getHashFromServer() + { + return _hashFromServer; + } + + public String getGeneratedHash() + { + return _calculatedHash; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/timing/TimeData.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/timing/TimeData.java similarity index 94% rename from Plugins/Mineplex.Core/src/mineplex/core/timing/TimeData.java rename to Plugins/Mineplex.Core.Common/src/mineplex/core/common/timing/TimeData.java index 2a00de525..28f56221e 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/timing/TimeData.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/timing/TimeData.java @@ -1,4 +1,4 @@ -package mineplex.core.timing; +package mineplex.core.common.timing; public class TimeData { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/timing/TimingManager.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/timing/TimingManager.java similarity index 76% rename from Plugins/Mineplex.Core/src/mineplex/core/timing/TimingManager.java rename to Plugins/Mineplex.Core.Common/src/mineplex/core/common/timing/TimingManager.java index 8935e5eb4..14bd0ecbb 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/timing/TimingManager.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/timing/TimingManager.java @@ -1,17 +1,11 @@ -package mineplex.core.timing; +package mineplex.core.common.timing; import java.util.Map.Entry; -import org.bukkit.event.Listener; -import org.bukkit.plugin.java.JavaPlugin; - import mineplex.core.common.util.NautHashMap; -public class TimingManager implements Listener +public class TimingManager { - private static TimingManager _instance; - - private JavaPlugin _plugin; private static NautHashMap _timingList = new NautHashMap(); private static NautHashMap _totalList = new NautHashMap(); @@ -20,30 +14,6 @@ public class TimingManager implements Listener public static boolean Debug = true; - protected TimingManager(JavaPlugin plugin) - { - _instance = this; - - _plugin = plugin; - - _plugin.getServer().getPluginManager().registerEvents(this, _plugin); - } - - public static TimingManager Initialize(JavaPlugin plugin) - { - if (_instance == null) - { - _instance = new TimingManager(plugin); - } - - return _instance; - } - - public static TimingManager instance() - { - return _instance; - } - public static void startTotal(String title) { if (!Debug) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java index dc68fca79..eca1592a6 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java @@ -30,7 +30,7 @@ import mineplex.core.common.util.Callback; import mineplex.core.common.util.UUIDFetcher; import mineplex.core.common.util.UtilPlayer; import mineplex.core.common.util.UtilTasks; -import mineplex.core.timing.TimingManager; +import mineplex.core.common.timing.TimingManager; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/visibility/VisibilityData.java b/Plugins/Mineplex.Core/src/mineplex/core/visibility/VisibilityData.java index 2c5f57637..851a0b73c 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/visibility/VisibilityData.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/visibility/VisibilityData.java @@ -4,7 +4,7 @@ import java.util.Iterator; import mineplex.core.common.util.NautHashMap; import mineplex.core.recharge.Recharge; -import mineplex.core.timing.TimingManager; +import mineplex.core.common.timing.TimingManager; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; import org.bukkit.entity.Player; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/visibility/VisibilityManager.java b/Plugins/Mineplex.Core/src/mineplex/core/visibility/VisibilityManager.java index 26fe0e706..dfd21d10c 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/visibility/VisibilityManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/visibility/VisibilityManager.java @@ -5,7 +5,7 @@ import java.util.Iterator; import mineplex.core.MiniPlugin; import mineplex.core.common.util.NautHashMap; import mineplex.core.common.util.UtilServer; -import mineplex.core.timing.TimingManager; +import mineplex.core.common.timing.TimingManager; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java index 86fa666a6..5f5bd3d73 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java @@ -98,7 +98,7 @@ import mineplex.core.status.ServerStatusManager; import mineplex.core.task.TaskManager; import mineplex.core.teleport.Teleport; import mineplex.core.thank.ThankManager; -import mineplex.core.timing.TimingManager; +import mineplex.core.common.timing.TimingManager; import mineplex.core.rankGiveaway.titangiveaway.TitanGiveawayManager; import mineplex.core.valentines.ValentinesGiftManager; import mineplex.core.youtube.YoutubeManager; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/UHC.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/UHC.java index 5c08f3709..e2ce57b59 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/UHC.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/uhc/UHC.java @@ -273,7 +273,7 @@ public abstract class UHC extends Game new OreVeinEditorModule().removeNonAirVeins().register(this); new AntiExpOrbModule().register(this); new RejoinModule().register(this); - + registerDebugCommand(new DebugCommand("startpvp", Rank.ADMIN) { @Override diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/OreVeinEditorModule.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/OreVeinEditorModule.java index a7582e28f..8bd58cc78 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/OreVeinEditorModule.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/OreVeinEditorModule.java @@ -3,7 +3,7 @@ package nautilus.game.arcade.game.modules; import mineplex.core.common.util.UtilBlock; import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilWorld; -import mineplex.core.timing.TimingManager; +import mineplex.core.common.timing.TimingManager; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.event.EventHandler; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java index c078afda9..39ed239e9 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameCreationManager.java @@ -4,7 +4,7 @@ import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilServer; import mineplex.core.common.util.UtilTime; import mineplex.core.itemstack.ItemStackFactory; -import mineplex.core.timing.TimingManager; +import mineplex.core.common.timing.TimingManager; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; import mineplex.minecraft.game.core.combat.CombatManager.AttackReason; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/lobby/current/NewGameLobbyManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/lobby/current/NewGameLobbyManager.java index ca5f05faf..432ec1298 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/lobby/current/NewGameLobbyManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/lobby/current/NewGameLobbyManager.java @@ -5,7 +5,7 @@ import com.google.common.collect.Maps; import mineplex.core.common.util.MapUtil; import mineplex.core.common.util.UtilAlg; import mineplex.core.common.util.UtilEnt; -import mineplex.core.timing.TimingManager; +import mineplex.core.common.timing.TimingManager; import nautilus.game.arcade.ArcadeManager; import nautilus.game.arcade.game.Game; import nautilus.game.arcade.game.GameTeam; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/world/WorldData.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/world/WorldData.java index 00f103353..622bad908 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/world/WorldData.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/world/WorldData.java @@ -1,6 +1,7 @@ package nautilus.game.arcade.world; import com.mineplex.spigot.ChunkPreLoadEvent; + import mineplex.core.common.util.FileUtil; import mineplex.core.common.util.MapUtil; import mineplex.core.common.util.UtilMath; @@ -8,14 +9,14 @@ import mineplex.core.common.util.UtilServer; import mineplex.core.common.util.WorldUtil; import mineplex.core.common.util.ZipUtil; import mineplex.core.common.util.worldgen.WorldGenCleanRoom; -import mineplex.core.timing.TimingManager; +import mineplex.core.common.api.enderchest.EnderchestWorldLoader; +import mineplex.core.common.timing.TimingManager; import nautilus.game.arcade.GameType; import nautilus.game.arcade.game.Game; import nautilus.game.arcade.game.games.uhc.UHC; import org.bukkit.Difficulty; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.World.Environment; import org.bukkit.WorldCreator; import java.io.BufferedReader; @@ -77,7 +78,17 @@ public class WorldData public void run() { //Unzip - worldData.UnzipWorld(); + if (Host instanceof UHC) { + boolean uhcLoaded = loadUHCMap(); // attempt to load from enderchest + if (!uhcLoaded) + { + // failsafe on normal UHC map + worldData.UnzipWorld(); + } + } else + { + worldData.UnzipWorld(); + } //Load World Data Sync UtilServer.getServer().getScheduler().runTask(Host.Manager.getPlugin(), new Runnable() @@ -85,9 +96,12 @@ public class WorldData public void run() { TimingManager.start("WorldData loading world."); + WorldCreator creator = new WorldCreator(GetFolder()); creator.generator(new WorldGenCleanRoom()); World = WorldUtil.LoadWorld(creator); + + TimingManager.stop("WorldData loading world."); World.setDifficulty(Difficulty.HARD); @@ -112,6 +126,29 @@ public class WorldData } }); } + + private boolean loadUHCMap() + { + EnderchestWorldLoader worldLoader = new EnderchestWorldLoader(); + boolean success = false; + + for (int attempt = 1; !success && attempt <= 3; attempt++) + { + System.out.println("Grabbing UHC map from Enderchest, attempt " + attempt); + + try + { + worldLoader.loadMap("uhc", GetFolder()); + success = true; + } catch (Exception e) + { + attempt++; + e.printStackTrace(); + } + } + + return success; + } protected GameType GetGame() {