-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit d7d7541
Showing
7 changed files
with
392 additions
and
0 deletions.
There are no files selected for viewing
114 changes: 114 additions & 0 deletions
114
src/main/java/me/realized/de/arenaregen/ArenaRegen.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package me.realized.de.arenaregen; | ||
|
||
import com.sk89q.worldedit.BlockVector; | ||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin; | ||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import me.realized.duels.api.arena.ArenaManager; | ||
import me.realized.duels.api.command.SubCommand; | ||
import me.realized.duels.api.event.match.MatchEndEvent; | ||
import me.realized.duels.api.event.match.MatchStartEvent; | ||
import me.realized.duels.api.extension.DuelsExtension; | ||
import me.realized.duels.api.match.Match; | ||
import me.realized.de.arenaregen.util.NMSUtil; | ||
import org.bukkit.Bukkit; | ||
import org.bukkit.Chunk; | ||
import org.bukkit.Location; | ||
import org.bukkit.Material; | ||
import org.bukkit.block.Block; | ||
import org.bukkit.command.CommandSender; | ||
import org.bukkit.entity.Player; | ||
import org.bukkit.event.EventHandler; | ||
import org.bukkit.event.Listener; | ||
|
||
public class ArenaRegen extends DuelsExtension implements Listener { | ||
|
||
private WorldGuardPlugin worldGuard; | ||
private ProtectedCuboidRegion region; | ||
private ArenaManager arenaManager; | ||
|
||
private final Map<Match, BlockChange> changes = new HashMap<>(); | ||
|
||
@Override | ||
public void onEnable() { | ||
this.worldGuard = (WorldGuardPlugin) api.getServer().getPluginManager().getPlugin("WorldGuard"); | ||
this.region = (ProtectedCuboidRegion) worldGuard.getRegionManager(Bukkit.getWorlds().get(0)).getRegion("arena"); | ||
|
||
if (region == null) { | ||
return; | ||
} | ||
|
||
this.arenaManager = api.getArenaManager(); | ||
api.getServer().getPluginManager().registerEvents(this, api); | ||
api.registerSubCommand("duels", new SubCommand("test", null, null, null, true, 1) { | ||
@Override | ||
public void execute(final CommandSender commandSender, final String s, final String[] strings) { | ||
final Player player = (Player) commandSender; | ||
final Location location = player.getLocation(); | ||
final Set<Chunk> chunks = new HashSet<>(); | ||
|
||
for (int i = 0; i < 20; i++) { | ||
final Location blockLoc = location.clone().add(i, 0, i); | ||
NMSUtil.setBlockFast(blockLoc.getBlock(), Material.BLACK_STAINED_GLASS, 0); | ||
chunks.add(blockLoc.getChunk()); | ||
} | ||
|
||
NMSUtil.update(player, chunks); | ||
player.sendMessage("done!"); | ||
} | ||
}); | ||
} | ||
|
||
@EventHandler | ||
public void on(final MatchStartEvent event) { | ||
final BlockChange change = new BlockChange(); | ||
changes.put(event.getMatch(), change); | ||
|
||
final Set<Chunk> chunks = new HashSet<>(); | ||
final BlockVector min = region.getMinimumPoint(); | ||
final BlockVector max = region.getMaximumPoint(); | ||
|
||
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { | ||
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { | ||
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { | ||
final Location location = new Location(Bukkit.getWorlds().get(0), x, y, z); | ||
chunks.add(location.getChunk()); | ||
|
||
if (location.getBlock().getType() != Material.AIR) { | ||
continue; | ||
} | ||
|
||
change.getSpaces().add(location); | ||
} | ||
} | ||
} | ||
|
||
update(chunks, event.getPlayers()); | ||
} | ||
|
||
@EventHandler | ||
public void on(final MatchEndEvent event) { | ||
final BlockChange change = changes.remove(event.getMatch()); | ||
|
||
if (change == null) { | ||
return; | ||
} | ||
|
||
change.getSpaces().forEach(location -> { | ||
final Block block = location.getBlock(); | ||
|
||
if (block.getType() != Material.AIR) { | ||
NMSUtil.setBlockFast(block, Material.AIR, 0); | ||
} | ||
}); | ||
} | ||
|
||
private void update(final Set<Chunk> chunks, final Player... players) { | ||
for (final Player player : players) { | ||
NMSUtil.update(player, chunks); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package me.realized.de.arenaregen; | ||
|
||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import lombok.Getter; | ||
import org.bukkit.Location; | ||
import org.bukkit.Material; | ||
import org.bukkit.block.Block; | ||
|
||
public class BlockChange { | ||
|
||
@Getter | ||
private final Set<Location> spaces = new HashSet<>(); | ||
@Getter | ||
private final Map<Location, Block> places = new HashMap<>(); | ||
|
||
public BlockChange() {} | ||
|
||
private class BlockData { | ||
|
||
@Getter | ||
private final Material type; | ||
@Getter | ||
private final byte data; | ||
|
||
@SuppressWarnings("deprecation") | ||
public BlockData(final Block block) { | ||
this.type = block.getType(); | ||
this.data = block.getData(); | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/main/java/me/realized/de/arenaregen/util/CompatUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package me.realized.de.arenaregen.util; | ||
|
||
import org.bukkit.Bukkit; | ||
|
||
public final class CompatUtil { | ||
|
||
private static final int SUB_VERSION; | ||
|
||
static { | ||
final String packageName = Bukkit.getServer().getClass().getPackage().getName(); | ||
SUB_VERSION = NumberUtil.parseInt(packageName.substring(packageName.lastIndexOf('.') + 1).split("_")[1]).orElse(0); | ||
} | ||
|
||
private CompatUtil() {} | ||
|
||
public static boolean isPre1_8() { | ||
return SUB_VERSION < 8; | ||
} | ||
|
||
public static boolean isPre1_13() { | ||
return SUB_VERSION < 13; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package me.realized.de.arenaregen.util; | ||
|
||
import java.lang.reflect.Constructor; | ||
import java.lang.reflect.Method; | ||
import java.util.Collection; | ||
import org.bukkit.Chunk; | ||
import org.bukkit.Material; | ||
import org.bukkit.block.Block; | ||
import org.bukkit.entity.Player; | ||
|
||
public final class NMSUtil { | ||
|
||
private static Method GET_HANDLE; | ||
private static Method FROM_LEGACY_DATA; | ||
private static Method GET_BLOCK_DATA; | ||
private static Method GET_BLOCK; | ||
private static Method SET_BLOCK_7; | ||
private static Method SET_BLOCK_12; | ||
private static Method SET_BLOCK; | ||
private static Constructor<?> BLOCK_POS_CONSTRUCTOR; | ||
|
||
static { | ||
try { | ||
// PLAYER_GET_HANDLE = ReflectionUtil.getMethod(ReflectionUtil.getCBClass("entity.CraftPlayer"), "getHandle"); | ||
// CHUNK_QUEUE = ReflectionUtil.getField(ReflectionUtil.getNMSClass("EntityPlayer"), "chunkCoordIntPairQueue"); | ||
// CHUNK_PAIR_CONSTRUCTOR = ReflectionUtil.getConstructor(ReflectionUtil.getNMSClass("ChunkCoordIntPair"), Integer.TYPE, Integer.TYPE); | ||
GET_HANDLE = ReflectionUtil.getMethod(ReflectionUtil.getCBClass("CraftChunk"), "getHandle"); | ||
final Class<?> BLOCK = ReflectionUtil.getNMSClass("Block"); | ||
FROM_LEGACY_DATA = ReflectionUtil.getMethod(BLOCK, "fromLegacyData", Integer.TYPE); | ||
GET_BLOCK_DATA = ReflectionUtil.getMethod(BLOCK, "getBlockData"); | ||
final Class<?> BLOCK_POS = ReflectionUtil.getNMSClass("BlockPosition"); | ||
BLOCK_POS_CONSTRUCTOR = ReflectionUtil.getConstructor(BLOCK_POS, Double.TYPE, Double.TYPE, Double.TYPE); | ||
GET_BLOCK = ReflectionUtil.getMethod(ReflectionUtil.getCBClass("util.CraftMagicNumbers"), "getBlock", Material.class); | ||
final Class<?> CHUNK = ReflectionUtil.getNMSClass("Chunk"); | ||
SET_BLOCK_7 = ReflectionUtil.getMethod(CHUNK, "a", Integer.TYPE, Integer.TYPE, Integer.TYPE, BLOCK, Integer.TYPE); | ||
final Class<?> BLOCK_DATA = ReflectionUtil.getNMSClass("IBlockData"); | ||
SET_BLOCK_12 = ReflectionUtil.getMethod(CHUNK, "a", BLOCK_POS, BLOCK_DATA); | ||
SET_BLOCK = ReflectionUtil.getMethod(CHUNK, "a", BLOCK_POS, BLOCK_DATA, Boolean.TYPE); | ||
} catch (Throwable ex) { | ||
ex.printStackTrace(); | ||
} | ||
} | ||
|
||
private NMSUtil() {} | ||
|
||
public static boolean setBlockFast(final Block block, final Material material, final int data) { | ||
return setBlockFast(block.getChunk(), block.getX(), block.getY(), block.getZ(), material, data); | ||
} | ||
|
||
public static boolean setBlockFast(final Chunk chunk, final int x, final int y, final int z, final Material material, final int data) { | ||
try { | ||
final Object chunkHandle = GET_HANDLE.invoke(chunk); | ||
Object nmsBlock = GET_BLOCK.invoke(null, material); | ||
|
||
if (CompatUtil.isPre1_8()) { | ||
SET_BLOCK_7.invoke(chunkHandle, x & 0x0f, y, z & 0x0f, nmsBlock, data); | ||
} else if (CompatUtil.isPre1_13()) { | ||
nmsBlock = FROM_LEGACY_DATA.invoke(nmsBlock, data); | ||
SET_BLOCK_12.invoke(chunkHandle, BLOCK_POS_CONSTRUCTOR.newInstance(x & 0xF, y, z & 0xF), nmsBlock); | ||
} else { | ||
SET_BLOCK.invoke(chunkHandle, BLOCK_POS_CONSTRUCTOR.newInstance(x, y, z), GET_BLOCK_DATA.invoke(nmsBlock), true); | ||
} | ||
} catch (Throwable ex) { | ||
ex.printStackTrace(); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
public static void update(final Player player, final Collection<Chunk> chunks) { | ||
chunks.forEach(chunk -> player.getWorld().refreshChunk(chunk.getX(), chunk.getZ())); | ||
// | ||
// try { | ||
// final Object handle = PLAYER_GET_HANDLE.invoke(player); | ||
// final List queue = (List) CHUNK_QUEUE.get(handle); | ||
// | ||
// for (final Chunk chunk : chunks) { | ||
// queue.add(CHUNK_PAIR_CONSTRUCTOR.newInstance(chunk.getX(), chunk.getZ())); | ||
// } | ||
// } catch (Throwable ex) { | ||
// ex.printStackTrace(); | ||
// } | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
src/main/java/me/realized/de/arenaregen/util/NumberUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package me.realized.de.arenaregen.util; | ||
|
||
import java.util.OptionalInt; | ||
|
||
public final class NumberUtil { | ||
|
||
private NumberUtil() {} | ||
|
||
/** | ||
* Copy of {@link Integer#parseInt(String)} (String)} but returns an empty {@link OptionalInt} instead of throwing a {@link NumberFormatException}. | ||
* | ||
* @param s String to parse. | ||
* @return {@link OptionalInt} instance with parsed value inside or empty if string is invalid. | ||
*/ | ||
public static OptionalInt parseInt(final String s) { | ||
if (s == null) { | ||
return OptionalInt.empty(); | ||
} | ||
|
||
int result = 0; | ||
boolean negative = false; | ||
int i = 0, len = s.length(); | ||
int limit = -Integer.MAX_VALUE; | ||
int multmin; | ||
int digit; | ||
|
||
if (len > 0) { | ||
char firstChar = s.charAt(0); | ||
|
||
if (firstChar < '0') { // Possible leading "+" or "-" | ||
if (firstChar == '-') { | ||
negative = true; | ||
limit = Integer.MIN_VALUE; | ||
} else if (firstChar != '+') { | ||
return OptionalInt.empty(); | ||
} | ||
|
||
if (len == 1) { // Cannot have lone "+" or "-" | ||
return OptionalInt.empty(); | ||
} | ||
|
||
i++; | ||
} | ||
|
||
multmin = limit / 10; | ||
|
||
while (i < len) { | ||
// Accumulating negatively avoids surprises near MAX_VALUE | ||
digit = Character.digit(s.charAt(i++), 10); | ||
if (digit < 0) { | ||
return OptionalInt.empty(); | ||
} | ||
|
||
if (result < multmin) { | ||
return OptionalInt.empty(); | ||
} | ||
|
||
result *= 10; | ||
|
||
if (result < limit + digit) { | ||
return OptionalInt.empty(); | ||
} | ||
|
||
result -= digit; | ||
} | ||
} else { | ||
return OptionalInt.empty(); | ||
} | ||
|
||
return OptionalInt.of(negative ? result : -result); | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
src/main/java/me/realized/de/arenaregen/util/ReflectionUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package me.realized.de.arenaregen.util; | ||
|
||
import java.lang.reflect.Constructor; | ||
import java.lang.reflect.Field; | ||
import java.lang.reflect.Method; | ||
import org.bukkit.Bukkit; | ||
|
||
public final class ReflectionUtil { | ||
|
||
private final static String VERSION; | ||
|
||
static { | ||
VERSION = Bukkit.getServer().getClass().getName().split("\\.")[3]; | ||
} | ||
|
||
private ReflectionUtil() {} | ||
|
||
public static Class<?> getNMSClass(final String name) { | ||
try { | ||
return Class.forName("net.minecraft.server." + VERSION + "." + name); | ||
} catch (ClassNotFoundException ex) { | ||
return null; | ||
} | ||
} | ||
|
||
public static Class<?> getCBClass(final String path) { | ||
try { | ||
return Class.forName("org.bukkit.craftbukkit." + VERSION + "." + path); | ||
} catch (ClassNotFoundException ex) { | ||
return null; | ||
} | ||
} | ||
|
||
public static Method getMethod(final Class<?> clazz, final String name, final Class<?>... parameters) { | ||
try { | ||
return clazz.getMethod(name, parameters); | ||
} catch (Throwable throwable) { | ||
return null; | ||
} | ||
} | ||
|
||
public static Field getField(final Class<?> clazz, final String name) { | ||
try { | ||
return clazz.getField(name); | ||
} catch (Throwable throwable) { | ||
return null; | ||
} | ||
} | ||
|
||
public static Constructor<?> getConstructor(final Class<?> clazz, final Class<?>... parameters) { | ||
try { | ||
return clazz.getConstructor(parameters); | ||
} catch (Throwable throwable) { | ||
return null; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
name: ArenaRegen | ||
version: @VERSION@ | ||
main: me.realized.de.arenaregen.ArenaRegen | ||
authors: [Realized] | ||
description: Create automatically resetting arenas! | ||
website: not released |