mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-31 17:43:44 +01:00 
			
		
		
		
	Sponge
This commit is contained in:
		
							
								
								
									
										159
									
								
								src/main/java/com/plotsquared/sponge/PlotGen.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								src/main/java/com/plotsquared/sponge/PlotGen.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| package com.plotsquared.sponge; | ||||
|  | ||||
| import org.spongepowered.api.block.BlockState; | ||||
| import org.spongepowered.api.block.BlockTypes; | ||||
| import org.spongepowered.api.world.World; | ||||
| import org.spongepowered.api.world.extent.ImmutableBiomeArea; | ||||
| import org.spongepowered.api.world.extent.MutableBlockVolume; | ||||
| import org.spongepowered.api.world.gen.GeneratorPopulator; | ||||
|  | ||||
| import com.flowpowered.math.vector.Vector3i; | ||||
|  | ||||
| public class PlotGen implements GeneratorPopulator { | ||||
|  | ||||
|     public String worldname; | ||||
|     public long seed; | ||||
|      | ||||
|  | ||||
|     public final int PLOT_HEIGHT = 64; // Plot height of 64 | ||||
|     public final int PLOT_WIDTH = 42; // Plot width of 42 | ||||
|     public final int ROAD_WIDTH = 7; // Road width of 7 | ||||
|      | ||||
|     public final BlockState ROAD_BLOCK = BlockTypes.QUARTZ_BLOCK.getDefaultState(); // Quartz | ||||
|     public final BlockState MAIN_BLOCK = BlockTypes.STONE.getDefaultState(); // Stone | ||||
|     public final BlockState WALL_BLOCK = BlockTypes.BEDROCK.getDefaultState(); // Bedrock | ||||
|     public final BlockState BORDER_BLOCK = BlockTypes.STONE_SLAB.getDefaultState(); // Stone slab | ||||
|     public final BlockState[] FLOOR_BLOCK = new BlockState[] {BlockTypes.GRASS.getDefaultState(), BlockTypes.SPONGE.getDefaultState()}; // Grass and sponge  | ||||
|      | ||||
|     public final int total_width; | ||||
|     public final int road_width_lower; | ||||
|     public final int road_width_upper; | ||||
|      | ||||
|     /** | ||||
|      * I'm using my PseudoRandom class as it's more efficient and we don't need secure randomness | ||||
|      */ | ||||
|     public final PseudoRandom RANDOM = new PseudoRandom(); | ||||
|     private SpongeMain main; | ||||
|  | ||||
|     public PlotGen(SpongeMain main, String worldname, long seed) { | ||||
|         this.main = main; | ||||
|         this.worldname = worldname; | ||||
|         this.seed = seed; | ||||
|          | ||||
|         total_width = PLOT_WIDTH + ROAD_WIDTH; | ||||
|          | ||||
|         // Calculating the bottom and top road portions (this is for a PlotSquared compatible generator, but you can have any offset you want) | ||||
|         if ((ROAD_WIDTH % 2) == 0) { | ||||
|             road_width_lower = ROAD_WIDTH / 2 - 1; | ||||
|         } else { | ||||
|             road_width_lower = ROAD_WIDTH / 2; | ||||
|         } | ||||
|         road_width_upper = road_width_lower + PLOT_WIDTH + 1; | ||||
|         main.log("LOADED GEN FOR: " + worldname); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * This simple pairing function is used for the seed for each chunk, | ||||
|      *  - This is useful if you want generation to appear random, but be the same each time | ||||
|      *  - You could also use a simple hash function like `return x + y * 31` - but this looks fancier | ||||
|      * @param x | ||||
|      * @param y | ||||
|      * @return | ||||
|      */ | ||||
|     public int pair(int x, int y) { | ||||
|         long hash; | ||||
|         if (x >= 0) { | ||||
|             if (y >= 0) { | ||||
|                 hash = (x * x) + (3 * x) + (2 * x * y) + y + (y * y) + 2; | ||||
|             } else { | ||||
|                 final int y1 = -y; | ||||
|                 hash = (x * x) + (3 * x) + (2 * x * y1) + y1 + (y1 * y1) + 1; | ||||
|             } | ||||
|         } else { | ||||
|             final int x1 = -x; | ||||
|             if (y >= 0) { | ||||
|                 hash = -((x1 * x1) + (3 * x1) + (2 * x1 * y) + y + (y * y)); | ||||
|             } else { | ||||
|                 final int y1 = -y; | ||||
|                 hash = -((x1 * x1) + (3 * x1) + (2 * x1 * y1) + y1 + (y1 * y1) + 1); | ||||
|             } | ||||
|         } | ||||
|         return (int) (hash % Integer.MAX_VALUE); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void populate(World world, MutableBlockVolume buffer, ImmutableBiomeArea biomeBase) { | ||||
|         try { | ||||
|             Vector3i min = buffer.getBlockMin(); | ||||
|             int X = min.getX(); | ||||
|             int Z = min.getZ(); | ||||
|             int cx = X >> 4; | ||||
|             int cz = Z >> 4; | ||||
|             main.log("POPULATING " + worldname + " | " + cx + "," + cz); | ||||
|             // If you have any random elements to your generation, you will want to set the state of the random class | ||||
|             RANDOM.state = pair(cx, cz); | ||||
|  | ||||
|             // TODO set bedrock | ||||
|              | ||||
|             // We want all plots to be the same | ||||
|             // To do this we will need to reduce the coordinates to the same base location | ||||
|             // To get the world coord from a chunk coord we multiply by 16 `cx << 4` | ||||
|             // Then we find the remainder of that `(cx << 4) % total_width` | ||||
|             // We don't want negative numbers though so add the `total_width` if the remainder is less than 0 | ||||
|             // We have to do this as the plot size will not necessarily have to be a multiple of 16, and so it won't always align to the chunk | ||||
|             // If the total width is a multiple of 16, you can in fact make some neat optimizations, see PlotSquaredMG source for more info | ||||
|             int bx = (cx << 4) % total_width + (cx < 0 ? total_width : 0); | ||||
|             int bz = (cz << 4) % total_width + (cz < 0 ? total_width : 0); | ||||
|              | ||||
|             // This is our main loop where we go over all the columns in the chunk and set the blocks | ||||
|             for (int x = 0; x < 16; x++) { | ||||
|                 for (int z = 0; z < 16; z++) { | ||||
|                     // Getting the reduced coordinate | ||||
|                     int xx = (x + bx); | ||||
|                     int zz = (z + bz); | ||||
|                     // If it's greater than the total width, we need to reduce it | ||||
|                     // Although we reduced the chunk coordinates before, that only means the base coordinate of the chunk is reduced | ||||
|                     // The top coordinate could still be outside our desired range | ||||
|                     if (xx >= total_width) xx -= total_width; | ||||
|                     if (zz >= total_width) zz -= total_width; | ||||
|                      | ||||
|                     // ROAD | ||||
|                     if (xx < road_width_lower || zz < road_width_lower || xx > road_width_upper || zz > road_width_upper) { | ||||
|                         for (int y = 0; y < PLOT_HEIGHT; y++) setBlock(buffer, X + x, y, Z + z, ROAD_BLOCK);  | ||||
|                     } | ||||
|                     // WALL | ||||
|                     else if (xx == road_width_lower || zz == road_width_lower || xx == road_width_upper || zz == road_width_upper) { | ||||
|                         // Set the wall block | ||||
|                         for (int y = 0; y < PLOT_HEIGHT; y++) setBlock(buffer, X + x, y, Z + z, WALL_BLOCK); | ||||
|                         // Set the border block (on top of the wall) | ||||
|                         setBlock(buffer, X + x, PLOT_HEIGHT, Z + z, BORDER_BLOCK); | ||||
|                     } | ||||
|                     // PLOT | ||||
|                     else { | ||||
|                         // Set the main plot block | ||||
|                         for (int y = 0; y < PLOT_HEIGHT - 1; y++) setBlock(buffer, X + x, y, Z + z, MAIN_BLOCK); | ||||
|                         // Set the plot floor | ||||
|                         setBlock(buffer, X + x, PLOT_HEIGHT - 1, Z + z, FLOOR_BLOCK); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             main.log("SUCCESS " + worldname + " | " + cx + "," + cz); | ||||
|         } | ||||
|         catch (Exception e) { | ||||
|             // Normally if something goes wrong in your code it will fail silently with world generators | ||||
|             // Having this try/catch will help recover the exception | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void setBlock(MutableBlockVolume buffer, int x, int y, int z, BlockState...states) { | ||||
|         if (states.length == 1) { | ||||
|             setBlock(buffer, x, y, z, states[0]); | ||||
|         } | ||||
|         setBlock(buffer, x, y, z, states[RANDOM.random(states.length)]); | ||||
|     } | ||||
|      | ||||
|     public void setBlock(MutableBlockVolume buffer, int x, int y, int z, BlockState state) { | ||||
|         buffer.setBlock(x, y, z, state); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								src/main/java/com/plotsquared/sponge/PseudoRandom.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/main/java/com/plotsquared/sponge/PseudoRandom.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| package com.plotsquared.sponge; | ||||
|  | ||||
| public class PseudoRandom { | ||||
|     public long state = 1; | ||||
|      | ||||
|     public long nextLong() { | ||||
|         final long a = state; | ||||
|         state = xorShift64(a); | ||||
|         return a; | ||||
|     } | ||||
|  | ||||
|     public long xorShift64(long a) { | ||||
|         a ^= (a << 21); | ||||
|         a ^= (a >>> 35); | ||||
|         a ^= (a << 4); | ||||
|         return a; | ||||
|     } | ||||
|  | ||||
|     public int random(final int n) { | ||||
|         if (n == 1) { | ||||
|             return 0; | ||||
|         } | ||||
|         final long r = ((nextLong() >>> 32) * n) >> 32; | ||||
|         return (int) r; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										325
									
								
								src/main/java/com/plotsquared/sponge/SpongeMain.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								src/main/java/com/plotsquared/sponge/SpongeMain.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,325 @@ | ||||
| package com.plotsquared.sponge; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.util.Collection; | ||||
| import java.util.UUID; | ||||
|  | ||||
| import org.bukkit.generator.ChunkGenerator; | ||||
| import org.slf4j.Logger; | ||||
| import org.spongepowered.api.Game; | ||||
| import org.spongepowered.api.Server; | ||||
| import org.spongepowered.api.entity.player.Player; | ||||
| import org.spongepowered.api.entity.player.gamemode.GameModes; | ||||
| import org.spongepowered.api.event.Subscribe; | ||||
| import org.spongepowered.api.event.entity.player.PlayerChatEvent; | ||||
| import org.spongepowered.api.event.state.PreInitializationEvent; | ||||
| import org.spongepowered.api.event.state.ServerAboutToStartEvent; | ||||
| import org.spongepowered.api.plugin.PluginContainer; | ||||
| import org.spongepowered.api.world.DimensionTypes; | ||||
| import org.spongepowered.api.world.GeneratorTypes; | ||||
| import org.spongepowered.api.world.World; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import com.intellectualcrafters.plot.IPlotMain; | ||||
| import com.intellectualcrafters.plot.PS; | ||||
| import com.intellectualcrafters.plot.config.C; | ||||
| import com.intellectualcrafters.plot.config.Settings; | ||||
| import com.intellectualcrafters.plot.generator.HybridUtils; | ||||
| import com.intellectualcrafters.plot.object.PlotPlayer; | ||||
| import com.intellectualcrafters.plot.util.BlockManager; | ||||
| import com.intellectualcrafters.plot.util.ChunkManager; | ||||
| import com.intellectualcrafters.plot.util.EconHandler; | ||||
| import com.intellectualcrafters.plot.util.EventUtil; | ||||
| import com.intellectualcrafters.plot.util.InventoryUtil; | ||||
| import com.intellectualcrafters.plot.util.PlayerManager; | ||||
| import com.intellectualcrafters.plot.util.TaskManager; | ||||
| import com.intellectualcrafters.plot.uuid.UUIDWrapper; | ||||
| import com.plotsquared.bukkit.listeners.APlotListener; | ||||
| import com.plotsquared.bukkit.util.SetupUtils; | ||||
| import com.plotsquared.bukkit.util.UUIDHandler; | ||||
|  | ||||
| /** | ||||
|  * Created by robin on 01/11/2014 | ||||
|  */ | ||||
|  | ||||
| //@Plugin(id = "PlotSquared", name = "PlotSquared", version = "3.0.0") | ||||
| public class SpongeMain implements IPlotMain, PluginContainer { | ||||
|     public static SpongeMain THIS; | ||||
|      | ||||
|     @Inject private Logger logger; | ||||
|     @Inject private Game game; | ||||
|     private Server server; | ||||
|      | ||||
|     private WorldModify modify; | ||||
|  | ||||
|     ////////////////////// SPONGE PLUGIN REGISTRATION //////////////////// | ||||
|     @Override | ||||
|     public String getId() { | ||||
|         return "PlotSquared"; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Object getInstance() { | ||||
|         return THIS; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getName() { | ||||
|         return "PlotSquared"; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getVersion() { | ||||
|         int[] version = PS.get().getVersion(); | ||||
|         String result = ""; | ||||
|         String prefix = ""; | ||||
|         for (int i : version) { | ||||
|             result += prefix + i; | ||||
|             prefix = "."; | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|     /////////////////////////////////////////////////////////////////////// | ||||
|      | ||||
|     ///////////////////// ON ENABLE /////////////////////   | ||||
|     @Subscribe | ||||
|     public void onInit(PreInitializationEvent event) { | ||||
|         THIS = this; | ||||
|         PS.instance = new PS(this); | ||||
|         if (Settings.METRICS) { | ||||
|             try { | ||||
|                 final SpongeMetrics metrics = new SpongeMetrics(game, this); | ||||
|                 metrics.start(); | ||||
|                 log(C.PREFIX.s() + "&6Metrics enabled."); | ||||
|             } catch (final Exception e) { | ||||
|                 log(C.PREFIX.s() + "&cFailed to load up metrics."); | ||||
|             } | ||||
|         } else { | ||||
|             log("&dUsing metrics will allow us to improve the plugin, please consider it :)"); | ||||
|         } | ||||
|         server = game.getServer(); | ||||
|         Collection<World> worlds = server.getWorlds(); | ||||
|         if (worlds.size() > 0) { | ||||
|             UUIDHandler.startCaching(); | ||||
|             for (World world : server.getWorlds()) { | ||||
|                 world.setWorldGenerator(new SpongePlotGenerator(world.getName())); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     @Subscribe | ||||
|     public void onServerAboutToStart(ServerAboutToStartEvent event) { | ||||
|         this.modify = new WorldModify(this); | ||||
|         Game game = event.getGame(); | ||||
|         game.getRegistry().registerWorldGeneratorModifier(modify); | ||||
|         game.getRegistry().getWorldBuilder() | ||||
|         .name("test") | ||||
|         .enabled(true) | ||||
|         .loadsOnStartup(true) | ||||
|         .keepsSpawnLoaded(true) | ||||
|         .dimensionType(DimensionTypes.OVERWORLD) | ||||
|         .generator(GeneratorTypes.DEBUG) | ||||
|         .gameMode(GameModes.CREATIVE) | ||||
|         .generatorModifiers(modify) | ||||
|         .build(); | ||||
|     } | ||||
|      | ||||
|     public Logger getLogger() { | ||||
|         return logger; | ||||
|     } | ||||
|      | ||||
|     public Game getGame() { | ||||
|         return game; | ||||
|     } | ||||
|      | ||||
|     @Subscribe | ||||
|     public void onPlayerChat(PlayerChatEvent event) { | ||||
|         // This is how events sort of work? | ||||
|         Player player  = event.getUser(); | ||||
|         log(player.getWorld().getName()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void log(String message) { | ||||
|         logger.info(message); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public File getDirectory() { | ||||
|         return new File("mods/PlotSquared"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void disable() { | ||||
|         PS.get().disable(); | ||||
|         THIS = null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int[] getPluginVersion() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int[] getServerVersion() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void handleKick(UUID uuid, C c) { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public TaskManager getTaskManager() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void runEntityTask() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerCommands() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerPlayerEvents() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerInventoryEvents() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerPlotPlusEvents() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerForceFieldEvents() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerWorldEditEvents() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerTNTListener() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public EconHandler getEconomyHandler() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public BlockManager initBlockManager() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public EventUtil initEventUtil() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ChunkManager initChunkManager() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public SetupUtils initSetupUtils() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public HybridUtils initHybridUtils() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public UUIDWrapper initUUIDHandler() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public InventoryUtil initInventoryUtil() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean initPlotMeConverter() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void unregister(PlotPlayer player) { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ChunkGenerator getGenerator(String world, String name) { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public APlotListener initPlotListener() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerChunkProcessor() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void registerWorldEvents() { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PlayerManager initPlayerManager() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getServerName() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										529
									
								
								src/main/java/com/plotsquared/sponge/SpongeMetrics.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										529
									
								
								src/main/java/com/plotsquared/sponge/SpongeMetrics.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,529 @@ | ||||
| package com.plotsquared.sponge; | ||||
|  | ||||
| /* | ||||
|  * Copyright 2011-2013 Tyler Blair. All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without modification, are | ||||
|  * permitted provided that the following conditions are met: | ||||
|  * | ||||
|  *    1. Redistributions of source code must retain the above copyright notice, this list of | ||||
|  *       conditions and the following disclaimer. | ||||
|  * | ||||
|  *    2. Redistributions in binary form must reproduce the above copyright notice, this list | ||||
|  *       of conditions and the following disclaimer in the documentation and/or other materials | ||||
|  *       provided with the distribution. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED | ||||
|  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR | ||||
|  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||
|  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
|  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||
|  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||||
|  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  * | ||||
|  * The views and conclusions contained in the software and documentation are those of the | ||||
|  * authors and contributors and should not be interpreted as representing official policies, | ||||
|  * either expressed or implied, of anybody else. | ||||
|  */ | ||||
|  | ||||
| import ninja.leaping.configurate.commented.CommentedConfigurationNode; | ||||
| import ninja.leaping.configurate.hocon.HoconConfigurationLoader; | ||||
| import ninja.leaping.configurate.loader.ConfigurationLoader; | ||||
|  | ||||
| import org.spongepowered.api.Game; | ||||
| import org.spongepowered.api.plugin.PluginContainer; | ||||
| import org.spongepowered.api.service.scheduler.Task; | ||||
| import org.spongepowered.api.service.scheduler.TaskBuilder; | ||||
|  | ||||
| import javax.inject.Inject; | ||||
|  | ||||
| import java.io.BufferedReader; | ||||
| import java.io.ByteArrayOutputStream; | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStreamReader; | ||||
| import java.io.OutputStream; | ||||
| import java.io.UnsupportedEncodingException; | ||||
| import java.net.Proxy; | ||||
| import java.net.URL; | ||||
| import java.net.URLConnection; | ||||
| import java.net.URLEncoder; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import java.util.zip.GZIPOutputStream; | ||||
|  | ||||
| public class SpongeMetrics { | ||||
|  | ||||
|     /** | ||||
|      * The current revision number | ||||
|      */ | ||||
|     private final static int REVISION = 7; | ||||
|  | ||||
|     /** | ||||
|      * The base url of the metrics domain | ||||
|      */ | ||||
|     private static final String BASE_URL = "http://report.mcstats.org"; | ||||
|  | ||||
|     /** | ||||
|      * The url used to report a server's status | ||||
|      */ | ||||
|     private static final String REPORT_URL = "/plugin/%s"; | ||||
|  | ||||
|     /** | ||||
|      * Interval of time to ping (in minutes) | ||||
|      */ | ||||
|     private static final int PING_INTERVAL = 15; | ||||
|  | ||||
|     /** | ||||
|      * The game data is being sent for | ||||
|      */ | ||||
|     private final Game game; | ||||
|  | ||||
|     /** | ||||
|      * The plugin this metrics submits for | ||||
|      */ | ||||
|     private final PluginContainer plugin; | ||||
|  | ||||
|     /** | ||||
|      * The plugin configuration file | ||||
|      */ | ||||
|     private CommentedConfigurationNode config; | ||||
|  | ||||
|     /** | ||||
|      * The configuration loader | ||||
|      */ | ||||
|     private ConfigurationLoader<CommentedConfigurationNode> configurationLoader; | ||||
|  | ||||
|     /** | ||||
|      * The plugin configuration file | ||||
|      */ | ||||
|     private File configurationFile; | ||||
|  | ||||
|     /** | ||||
|      * Unique server id | ||||
|      */ | ||||
|     private String guid; | ||||
|  | ||||
|     /** | ||||
|      * Debug mode | ||||
|      */ | ||||
|     private boolean debug; | ||||
|  | ||||
|     /** | ||||
|      * Lock for synchronization | ||||
|      */ | ||||
|     private final Object optOutLock = new Object(); | ||||
|  | ||||
|     /** | ||||
|      * The scheduled task | ||||
|      */ | ||||
|     private volatile Task task = null; | ||||
|  | ||||
|     @Inject | ||||
|     public SpongeMetrics(final Game game, final PluginContainer plugin) throws IOException { | ||||
|         if (plugin == null) { | ||||
|             throw new IllegalArgumentException("Plugin cannot be null"); | ||||
|         } | ||||
|  | ||||
|         this.game = game; | ||||
|         this.plugin = plugin; | ||||
|  | ||||
|         loadConfiguration(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Loads the configuration | ||||
|      */ | ||||
|     private void loadConfiguration() { | ||||
|         configurationFile = getConfigFile(); | ||||
|         configurationLoader = HoconConfigurationLoader.builder().setFile(configurationFile).build(); | ||||
|  | ||||
|         try { | ||||
|             if (!configurationFile.exists()) { | ||||
|                 configurationFile.createNewFile(); | ||||
|                 config = configurationLoader.load(); | ||||
|  | ||||
|                 config.setComment("This contains settings for MCStats: http://mcstats.org"); | ||||
|                 config.getNode("mcstats.guid").setValue(UUID.randomUUID().toString()); | ||||
|                 config.getNode("mcstats.opt-out").setValue(false); | ||||
|                 config.getNode("mcstats.debug").setValue(false); | ||||
|  | ||||
|                 configurationLoader.save(config); | ||||
|             } else { | ||||
|                 config = configurationLoader.load(); | ||||
|             } | ||||
|  | ||||
|             guid = config.getNode("mcstats.guid").getString(); | ||||
|             debug = config.getNode("mcstats.debug").getBoolean(); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Start measuring statistics. This will immediately create an async repeating task as the plugin and send the | ||||
|      * initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200 | ||||
|      * ticks. | ||||
|      * | ||||
|      * @return True if statistics measuring is running, otherwise false. | ||||
|      */ | ||||
|     public boolean start() { | ||||
|         synchronized (optOutLock) { | ||||
|             // Did we opt out? | ||||
|             if (isOptOut()) { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             // Is metrics already running? | ||||
|             if (task != null) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // Begin hitting the server with glorious data | ||||
|             TaskBuilder builder = game.getScheduler().getTaskBuilder(); | ||||
|             builder.async() | ||||
|             .interval(TimeUnit.MINUTES.toMillis(PING_INTERVAL)) | ||||
|             .execute(new Runnable() { | ||||
|                  | ||||
|                 private boolean firstPost = true; | ||||
|                  | ||||
|                 @Override | ||||
|                 public void run() { | ||||
|                     try { | ||||
|                         // This has to be synchronized or it can collide with the disable method. | ||||
|                         synchronized (optOutLock) { | ||||
|                             // Disable Task, if it is running and the server owner decided to opt-out | ||||
|                             if (isOptOut() && task != null) { | ||||
|                                 task.cancel(); | ||||
|                                 task = null; | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         // We use the inverse of firstPost because if it is the first time we are posting, | ||||
|                         // it is not a interval ping, so it evaluates to FALSE | ||||
|                         // Each time thereafter it will evaluate to TRUE, i.e PING! | ||||
|                         postPlugin(!firstPost); | ||||
|  | ||||
|                         // After the first post we set firstPost to false | ||||
|                         // Each post thereafter will be a ping | ||||
|                         firstPost = false; | ||||
|                     } catch (IOException e) { | ||||
|                         if (debug) { | ||||
|                             System.out.println("[Metrics] " + e.getMessage()); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Has the server owner denied plugin metrics? | ||||
|      * | ||||
|      * @return true if metrics should be opted out of it | ||||
|      */ | ||||
|     public boolean isOptOut() { | ||||
|         synchronized (optOutLock) { | ||||
|             loadConfiguration(); | ||||
|  | ||||
|             return config.getNode("mcstats.opt-out").getBoolean(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. | ||||
|      * | ||||
|      * @throws java.io.IOException | ||||
|      */ | ||||
|     public void enable() throws IOException { | ||||
|         // This has to be synchronized or it can collide with the check in the task. | ||||
|         synchronized (optOutLock) { | ||||
|             // Check if the server owner has already set opt-out, if not, set it. | ||||
|             if (isOptOut()) { | ||||
|                 config.getNode("mcstats.opt-out").setValue(false); | ||||
|                 configurationLoader.save(config); | ||||
|             } | ||||
|  | ||||
|             // Enable Task, if it is not running | ||||
|             if (task == null) { | ||||
|                 start(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. | ||||
|      * | ||||
|      * @throws java.io.IOException | ||||
|      */ | ||||
|     public void disable() throws IOException { | ||||
|         // This has to be synchronized or it can collide with the check in the task. | ||||
|         synchronized (optOutLock) { | ||||
|             // Check if the server owner has already set opt-out, if not, set it. | ||||
|             if (!isOptOut()) { | ||||
|                 config.getNode("mcstats.opt-out").setValue(true); | ||||
|                 configurationLoader.save(config); | ||||
|             } | ||||
|  | ||||
|             // Disable Task, if it is running | ||||
|             if (task != null) { | ||||
|                 task.cancel(); | ||||
|                 task = null; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status | ||||
|      * | ||||
|      * @return the File object for the config file | ||||
|      */ | ||||
|     public File getConfigFile() { | ||||
|         // TODO configDir | ||||
|         File configFolder = new File("config"); | ||||
|  | ||||
|         return new File(configFolder, "PluginMetrics.conf"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Generic method that posts a plugin to the metrics website | ||||
|      * | ||||
|      */ | ||||
|     private void postPlugin(final boolean isPing) throws IOException { | ||||
|         // Server software specific section | ||||
|         String pluginName = plugin.getName(); | ||||
|         boolean onlineMode = game.getServer().getOnlineMode(); // TRUE if online mode is enabled | ||||
|         String pluginVersion = plugin.getVersion(); | ||||
|         // TODO no visible way to get MC version at the moment | ||||
|         // TODO added by game.getPlatform().getMinecraftVersion() -- impl in 2.1 | ||||
|         String serverVersion = String.format("%s %s", "Sponge", game.getPlatform().getMinecraftVersion()); | ||||
|         int playersOnline = game.getServer().getOnlinePlayers().size(); | ||||
|  | ||||
|         // END server software specific section -- all code below does not use any code outside of this class / Java | ||||
|  | ||||
|         // Construct the post data | ||||
|         StringBuilder json = new StringBuilder(1024); | ||||
|         json.append('{'); | ||||
|  | ||||
|         // The plugin's description file containg all of the plugin data such as name, version, author, etc | ||||
|         appendJSONPair(json, "guid", guid); | ||||
|         appendJSONPair(json, "plugin_version", pluginVersion); | ||||
|         appendJSONPair(json, "server_version", serverVersion); | ||||
|         appendJSONPair(json, "players_online", Integer.toString(playersOnline)); | ||||
|  | ||||
|         // New data as of R6 | ||||
|         String osname = System.getProperty("os.name"); | ||||
|         String osarch = System.getProperty("os.arch"); | ||||
|         String osversion = System.getProperty("os.version"); | ||||
|         String java_version = System.getProperty("java.version"); | ||||
|         int coreCount = Runtime.getRuntime().availableProcessors(); | ||||
|  | ||||
|         // normalize os arch .. amd64 -> x86_64 | ||||
|         if (osarch.equals("amd64")) { | ||||
|             osarch = "x86_64"; | ||||
|         } | ||||
|  | ||||
|         appendJSONPair(json, "osname", osname); | ||||
|         appendJSONPair(json, "osarch", osarch); | ||||
|         appendJSONPair(json, "osversion", osversion); | ||||
|         appendJSONPair(json, "cores", Integer.toString(coreCount)); | ||||
|         appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); | ||||
|         appendJSONPair(json, "java_version", java_version); | ||||
|  | ||||
|         // If we're pinging, append it | ||||
|         if (isPing) { | ||||
|             appendJSONPair(json, "ping", "1"); | ||||
|         } | ||||
|  | ||||
|         // close json | ||||
|         json.append('}'); | ||||
|  | ||||
|         // Create the url | ||||
|         URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); | ||||
|  | ||||
|         // Connect to the website | ||||
|         URLConnection connection; | ||||
|  | ||||
|         // Mineshafter creates a socks proxy, so we can safely bypass it | ||||
|         // It does not reroute POST requests so we need to go around it | ||||
|         if (isMineshafterPresent()) { | ||||
|             connection = url.openConnection(Proxy.NO_PROXY); | ||||
|         } else { | ||||
|             connection = url.openConnection(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         byte[] uncompressed = json.toString().getBytes(); | ||||
|         byte[] compressed = gzip(json.toString()); | ||||
|  | ||||
|         // Headers | ||||
|         connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); | ||||
|         connection.addRequestProperty("Content-Type", "application/json"); | ||||
|         connection.addRequestProperty("Content-Encoding", "gzip"); | ||||
|         connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); | ||||
|         connection.addRequestProperty("Accept", "application/json"); | ||||
|         connection.addRequestProperty("Connection", "close"); | ||||
|  | ||||
|         connection.setDoOutput(true); | ||||
|  | ||||
|         if (debug) { | ||||
|             System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); | ||||
|         } | ||||
|  | ||||
|         // Write the data | ||||
|         OutputStream os = connection.getOutputStream(); | ||||
|         os.write(compressed); | ||||
|         os.flush(); | ||||
|  | ||||
|         // Now read the response | ||||
|         final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); | ||||
|         String response = reader.readLine(); | ||||
|  | ||||
|         // close resources | ||||
|         os.close(); | ||||
|         reader.close(); | ||||
|  | ||||
|         if (response == null || response.startsWith("ERR") || response.startsWith("7")) { | ||||
|             if (response == null) { | ||||
|                 response = "null"; | ||||
|             } else if (response.startsWith("7")) { | ||||
|                 response = response.substring(response.startsWith("7,") ? 2 : 1); | ||||
|             } | ||||
|  | ||||
|             throw new IOException(response); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * GZip compress a string of bytes | ||||
|      * | ||||
|      * @param input | ||||
|      * @return | ||||
|      */ | ||||
|     public static byte[] gzip(String input) { | ||||
|         ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||
|         GZIPOutputStream gzos = null; | ||||
|  | ||||
|         try { | ||||
|             gzos = new GZIPOutputStream(baos); | ||||
|             gzos.write(input.getBytes("UTF-8")); | ||||
|         } catch (IOException e) { | ||||
|             e.printStackTrace(); | ||||
|         } finally { | ||||
|             if (gzos != null) try { | ||||
|                 gzos.close(); | ||||
|             } catch (IOException ignore) { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return baos.toByteArray(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if mineshafter is present. If it is, we need to bypass it to send POST requests | ||||
|      * | ||||
|      * @return true if mineshafter is installed on the server | ||||
|      */ | ||||
|     private boolean isMineshafterPresent() { | ||||
|         try { | ||||
|             Class.forName("mineshafter.MineServer"); | ||||
|             return true; | ||||
|         } catch (Exception e) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Appends a json encoded key/value pair to the given string builder. | ||||
|      * | ||||
|      * @param json | ||||
|      * @param key | ||||
|      * @param value | ||||
|      * @throws java.io.UnsupportedEncodingException | ||||
|      */ | ||||
|     private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { | ||||
|         boolean isValueNumeric = false; | ||||
|  | ||||
|         try { | ||||
|             if (value.equals("0") || !value.endsWith("0")) { | ||||
|                 Double.parseDouble(value); | ||||
|                 isValueNumeric = true; | ||||
|             } | ||||
|         } catch (NumberFormatException e) { | ||||
|             isValueNumeric = false; | ||||
|         } | ||||
|  | ||||
|         if (json.charAt(json.length() - 1) != '{') { | ||||
|             json.append(','); | ||||
|         } | ||||
|  | ||||
|         json.append(escapeJSON(key)); | ||||
|         json.append(':'); | ||||
|  | ||||
|         if (isValueNumeric) { | ||||
|             json.append(value); | ||||
|         } else { | ||||
|             json.append(escapeJSON(value)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Escape a string to create a valid JSON string | ||||
|      * | ||||
|      * @param text | ||||
|      * @return | ||||
|      */ | ||||
|     private static String escapeJSON(String text) { | ||||
|         StringBuilder builder = new StringBuilder(); | ||||
|  | ||||
|         builder.append('"'); | ||||
|         for (int index = 0; index < text.length(); index++) { | ||||
|             char chr = text.charAt(index); | ||||
|  | ||||
|             switch (chr) { | ||||
|                 case '"': | ||||
|                 case '\\': | ||||
|                     builder.append('\\'); | ||||
|                     builder.append(chr); | ||||
|                     break; | ||||
|                 case '\b': | ||||
|                     builder.append("\\b"); | ||||
|                     break; | ||||
|                 case '\t': | ||||
|                     builder.append("\\t"); | ||||
|                     break; | ||||
|                 case '\n': | ||||
|                     builder.append("\\n"); | ||||
|                     break; | ||||
|                 case '\r': | ||||
|                     builder.append("\\r"); | ||||
|                     break; | ||||
|                 default: | ||||
|                     if (chr < ' ') { | ||||
|                         String t = "000" + Integer.toHexString(chr); | ||||
|                         builder.append("\\u" + t.substring(t.length() - 4)); | ||||
|                     } else { | ||||
|                         builder.append(chr); | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|         builder.append('"'); | ||||
|  | ||||
|         return builder.toString(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Encode text as UTF-8 | ||||
|      * | ||||
|      * @param text the text to encode | ||||
|      * @return the encoded text, as UTF-8 | ||||
|      */ | ||||
|     private static String urlEncode(final String text) throws UnsupportedEncodingException { | ||||
|         return URLEncoder.encode(text, "UTF-8"); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,57 @@ | ||||
| package com.plotsquared.sponge; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.bukkit.World; | ||||
| import org.spongepowered.api.world.gen.BiomeGenerator; | ||||
| import org.spongepowered.api.world.gen.GeneratorPopulator; | ||||
| import org.spongepowered.api.world.gen.Populator; | ||||
| import org.spongepowered.api.world.gen.WorldGenerator; | ||||
|  | ||||
| import com.intellectualcrafters.plot.object.PlotManager; | ||||
| import com.intellectualcrafters.plot.object.PlotWorld; | ||||
| import com.intellectualcrafters.plot.object.PseudoRandom; | ||||
| import com.intellectualcrafters.plot.object.RegionWrapper; | ||||
| import com.plotsquared.bukkit.object.PlotPopulator; | ||||
|  | ||||
| public class SpongePlotGenerator implements WorldGenerator { | ||||
|  | ||||
|     public SpongePlotGenerator(String world) { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public GeneratorPopulator getBaseGeneratorPopulator() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public BiomeGenerator getBiomeGenerator() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<GeneratorPopulator> getGeneratorPopulators() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<Populator> getPopulators() { | ||||
|         // TODO Auto-generated method stub | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setBaseGeneratorPopulator(GeneratorPopulator arg0) { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setBiomeGenerator(BiomeGenerator arg0) { | ||||
|         // TODO Auto-generated method stub | ||||
|          | ||||
|     } | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/main/java/com/plotsquared/sponge/WorldModify.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/main/java/com/plotsquared/sponge/WorldModify.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package com.plotsquared.sponge; | ||||
|  | ||||
| import org.spongepowered.api.data.DataContainer; | ||||
| import org.spongepowered.api.world.WorldCreationSettings; | ||||
| import org.spongepowered.api.world.gen.WorldGenerator; | ||||
| import org.spongepowered.api.world.gen.WorldGeneratorModifier; | ||||
|  | ||||
| public class WorldModify implements WorldGeneratorModifier { | ||||
|     private SpongeMain main; | ||||
|  | ||||
|     public WorldModify(SpongeMain main) { | ||||
|         this.main = main; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void modifyWorldGenerator(WorldCreationSettings world, DataContainer settings, WorldGenerator worldGenerator) { | ||||
|         worldGenerator.setBaseGeneratorPopulator(new PlotGen(main, world.getWorldName(), world.getSeed())); | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String getName() { | ||||
|         return "PlotSquared"; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getId() { | ||||
|         return "PlotSquared"; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 boy0001
					boy0001