Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Realizedd committed Aug 3, 2018
0 parents commit d7d7541
Show file tree
Hide file tree
Showing 7 changed files with 392 additions and 0 deletions.
114 changes: 114 additions & 0 deletions src/main/java/me/realized/de/arenaregen/ArenaRegen.java
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);
}
}
}
34 changes: 34 additions & 0 deletions src/main/java/me/realized/de/arenaregen/BlockChange.java
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 src/main/java/me/realized/de/arenaregen/util/CompatUtil.java
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;
}
}
85 changes: 85 additions & 0 deletions src/main/java/me/realized/de/arenaregen/util/NMSUtil.java
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 src/main/java/me/realized/de/arenaregen/util/NumberUtil.java
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 src/main/java/me/realized/de/arenaregen/util/ReflectionUtil.java
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;
}
}

}
6 changes: 6 additions & 0 deletions src/main/resources/extension.yml
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

0 comments on commit d7d7541

Please sign in to comment.