From 2ea1bd5e67e0962537986ef40521ab180af84620 Mon Sep 17 00:00:00 2001 From: Daniel Mills Date: Sun, 19 Jan 2020 07:11:11 -0500 Subject: [PATCH] Schematics --- src/main/java/ninja/bytecode/iris/Iris.java | 4 +- .../java/ninja/bytecode/iris/Settings.java | 1 + .../iris/controller/WandController.java | 272 +++++++++++++----- .../iris/generator/IrisGenerator.java | 27 +- .../iris/generator/genobject/GenObject.java | 29 +- .../genobject/GenObjectDecorator.java | 34 ++- .../generator/genobject/PlacedObject.java | 95 ++++++ .../java/ninja/bytecode/iris/util/GRT.java | 10 + .../ninja/bytecode/iris/util/GlossGlower.java | 106 +++++++ .../ninja/bytecode/iris/util/GlowManager.java | 14 + .../java/ninja/bytecode/iris/util/Glower.java | 20 ++ .../bytecode/iris/util/GlowingBlock.java | 179 ++++++++++++ .../bytecode/iris/util/PacketCategory.java | 9 + .../ninja/bytecode/iris/util/PacketGate.java | 129 +++++++++ 14 files changed, 845 insertions(+), 84 deletions(-) create mode 100644 src/main/java/ninja/bytecode/iris/generator/genobject/PlacedObject.java create mode 100644 src/main/java/ninja/bytecode/iris/util/GRT.java create mode 100644 src/main/java/ninja/bytecode/iris/util/GlossGlower.java create mode 100644 src/main/java/ninja/bytecode/iris/util/GlowManager.java create mode 100644 src/main/java/ninja/bytecode/iris/util/Glower.java create mode 100644 src/main/java/ninja/bytecode/iris/util/GlowingBlock.java create mode 100644 src/main/java/ninja/bytecode/iris/util/PacketCategory.java create mode 100644 src/main/java/ninja/bytecode/iris/util/PacketGate.java diff --git a/src/main/java/ninja/bytecode/iris/Iris.java b/src/main/java/ninja/bytecode/iris/Iris.java index dfebe5ce7..25c4f3b96 100644 --- a/src/main/java/ninja/bytecode/iris/Iris.java +++ b/src/main/java/ninja/bytecode/iris/Iris.java @@ -11,6 +11,7 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import ninja.bytecode.iris.controller.PackController; +import ninja.bytecode.iris.controller.WandController; import ninja.bytecode.iris.generator.IrisGenerator; import ninja.bytecode.iris.util.Direction; import ninja.bytecode.iris.util.IrisController; @@ -58,10 +59,11 @@ public class Iris extends JavaPlugin implements Listener public void onDisable() { getController(PackController.class).dispose(); + getController(WandController.class).dispose(); controllerSet.stopControllers(); HandlerList.unregisterAll((Plugin) this); Bukkit.getScheduler().cancelTasks(this); - + if(Iris.settings.performance.debugMode) { for(World i : Bukkit.getWorlds()) diff --git a/src/main/java/ninja/bytecode/iris/Settings.java b/src/main/java/ninja/bytecode/iris/Settings.java index 58a76b595..b1e4a6e04 100644 --- a/src/main/java/ninja/bytecode/iris/Settings.java +++ b/src/main/java/ninja/bytecode/iris/Settings.java @@ -18,6 +18,7 @@ public class Settings public boolean interpolation = true; public boolean surfaceNoise = true; public boolean verbose = false; + public int placeHistoryLimit = 8192; } public static class GeneratorSettings diff --git a/src/main/java/ninja/bytecode/iris/controller/WandController.java b/src/main/java/ninja/bytecode/iris/controller/WandController.java index c092b299d..6d4b23a8c 100644 --- a/src/main/java/ninja/bytecode/iris/controller/WandController.java +++ b/src/main/java/ninja/bytecode/iris/controller/WandController.java @@ -21,20 +21,33 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.util.BlockVector; import org.bukkit.util.Vector; +import mortar.compute.math.M; +import mortar.util.text.C; import ninja.bytecode.iris.Iris; +import ninja.bytecode.iris.generator.IrisGenerator; import ninja.bytecode.iris.generator.genobject.GenObject; +import ninja.bytecode.iris.generator.genobject.GenObjectGroup; +import ninja.bytecode.iris.generator.genobject.PlacedObject; +import ninja.bytecode.iris.pack.IrisBiome; import ninja.bytecode.iris.util.Cuboid; import ninja.bytecode.iris.util.IrisController; import ninja.bytecode.iris.util.MB; import ninja.bytecode.iris.util.ParticleEffect; import ninja.bytecode.iris.util.ParticleRedstone; import ninja.bytecode.shuriken.collections.GList; +import ninja.bytecode.shuriken.collections.GMap; +import ninja.bytecode.shuriken.format.F; public class WandController implements IrisController { + private GMap goc; + private GMap gog; + @Override public void onStart() { + goc = new GMap<>(); + gog = new GMap<>(); // TODO: Optimize Bukkit.getScheduler().scheduleSyncRepeatingTask(Iris.instance, () -> { @@ -58,81 +71,13 @@ public class WandController implements IrisController { if(isWand(p.getInventory().getItemInMainHand())) { + if(Iris.settings.performance.debugMode && p.getWorld().getGenerator() instanceof IrisGenerator) + { + tickHighlight(p, (IrisGenerator) p.getWorld().getGenerator()); + } + Location[] d = getCuboid(p.getInventory().getItemInMainHand()); - ParticleEffect.CRIT_MAGIC.display(0.1f, 1, d[0].clone().add(0.5, 0.5, 0.5).clone().add(Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65)), p); - ParticleEffect.CRIT.display(0.1f, 1, d[1].clone().add(0.5, 0.5, 0.5).clone().add(Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65)), p); - - if(!d[0].getWorld().equals(d[1].getWorld())) - { - return; - } - - if(d[0].distanceSquared(d[1]) > 64 * 64) - { - return; - } - - int minx = Math.min(d[0].getBlockX(), d[1].getBlockX()); - int miny = Math.min(d[0].getBlockY(), d[1].getBlockY()); - int minz = Math.min(d[0].getBlockZ(), d[1].getBlockZ()); - int maxx = Math.max(d[0].getBlockX(), d[1].getBlockX()); - int maxy = Math.max(d[0].getBlockY(), d[1].getBlockY()); - int maxz = Math.max(d[0].getBlockZ(), d[1].getBlockZ()); - - for(double j = minx - 1; j < maxx + 1; j += 0.25) - { - for(double k = miny - 1; k < maxy + 1; k += 0.25) - { - for(double l = minz - 1; l < maxz + 1; l += 0.25) - { - boolean jj = j == minx || j == maxx; - boolean kk = k == miny || k == maxy; - boolean ll = l == minz || l == maxz; - double aa = j; - double bb = k; - double cc = l; - - if((jj && kk) || (jj && ll) || (ll && kk)) - { - Vector push = new Vector(0, 0, 0); - - if(j == minx) - { - push.add(new Vector(-0.55, 0, 0)); - } - - if(k == miny) - { - push.add(new Vector(0, -0.55, 0)); - } - - if(l == minz) - { - push.add(new Vector(0, 0, -0.55)); - } - - if(j == maxx) - { - push.add(new Vector(0.55, 0, 0)); - } - - if(k == maxy) - { - push.add(new Vector(0, 0.55, 0)); - } - - if(l == maxz) - { - push.add(new Vector(0, 0, 0.55)); - } - - Location lv = new Location(d[0].getWorld(), aa, bb, cc).clone().add(0.5, 0.5, 0.5).clone().add(push); - int color = Color.getHSBColor((float) (0.5f + (Math.sin((aa + bb + cc + (p.getTicksLived() / 2)) / 20f) / 2)), 1, 1).getRGB(); - new ParticleRedstone().setColor(new Color(color)).play(lv, p); - } - } - } - } + draw(d, p); } } @@ -142,6 +87,179 @@ public class WandController implements IrisController } } + private void draw(Location[] d, Player p) + { + ParticleEffect.CRIT_MAGIC.display(0.1f, 1, d[0].clone().add(0.5, 0.5, 0.5).clone().add(Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65)), p); + ParticleEffect.CRIT.display(0.1f, 1, d[1].clone().add(0.5, 0.5, 0.5).clone().add(Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65)), p); + + if(!d[0].getWorld().equals(d[1].getWorld())) + { + return; + } + + if(d[0].distanceSquared(d[1]) > 64 * 64) + { + return; + } + + int minx = Math.min(d[0].getBlockX(), d[1].getBlockX()); + int miny = Math.min(d[0].getBlockY(), d[1].getBlockY()); + int minz = Math.min(d[0].getBlockZ(), d[1].getBlockZ()); + int maxx = Math.max(d[0].getBlockX(), d[1].getBlockX()); + int maxy = Math.max(d[0].getBlockY(), d[1].getBlockY()); + int maxz = Math.max(d[0].getBlockZ(), d[1].getBlockZ()); + + for(double j = minx - 1; j < maxx + 1; j += 0.25) + { + for(double k = miny - 1; k < maxy + 1; k += 0.25) + { + for(double l = minz - 1; l < maxz + 1; l += 0.25) + { + if(M.r(0.25)) + { + boolean jj = j == minx || j == maxx; + boolean kk = k == miny || k == maxy; + boolean ll = l == minz || l == maxz; + double aa = j; + double bb = k; + double cc = l; + + if((jj && kk) || (jj && ll) || (ll && kk)) + { + Vector push = new Vector(0, 0, 0); + + if(j == minx) + { + push.add(new Vector(-0.55, 0, 0)); + } + + if(k == miny) + { + push.add(new Vector(0, -0.55, 0)); + } + + if(l == minz) + { + push.add(new Vector(0, 0, -0.55)); + } + + if(j == maxx) + { + push.add(new Vector(0.55, 0, 0)); + } + + if(k == maxy) + { + push.add(new Vector(0, 0.55, 0)); + } + + if(l == maxz) + { + push.add(new Vector(0, 0, 0.55)); + } + + Location lv = new Location(d[0].getWorld(), aa, bb, cc).clone().add(0.5, 0.5, 0.5).clone().add(push); + int color = Color.getHSBColor((float) (0.5f + (Math.sin((aa + bb + cc + (p.getTicksLived() / 2)) / 20f) / 2)), 1, 1).getRGB(); + new ParticleRedstone().setColor(new Color(color)).play(lv, p); + } + } + } + } + } + } + + private void tickHighlight(Player p, IrisGenerator generator) + { + Location l = p.getTargetBlock(null, 32).getLocation(); + PlacedObject po = generator.nearest(l, 12); + + if(po != null) + { + if(!goc.containsKey(po.getF())) + { + String root = po.getF().split("\\Q:\\E")[0]; + String n = po.getF().split("\\Q:\\E")[1]; + GenObjectGroup gg = generator.getDimension().getObjectGroup(root); + gog.put(root, gg); + + for(GenObject i : gg.getSchematics()) + { + if(i.getName().equals(n)) + { + goc.put(po.getF(), i); + break; + } + } + + if(!goc.containsKey(po.getF())) + { + goc.put(po.getF(), new GenObject(0, 0, 0)); + } + } + + GenObjectGroup ggg = gog.get(po.getF().split("\\Q:\\E")[0]); + GenObject g = goc.get(po.getF()); + + if(g != null) + { + Location point = new Location(l.getWorld(), po.getX(), po.getY(), po.getZ()); + IrisBiome biome = generator.getBiome((int) generator.getOffsetX(po.getX()), (int) generator.getOffsetZ(po.getZ())); + String gg = po.getF().split("\\Q:\\E")[0]; + + for(int j = 0; j < 10; j++) + { + p.sendMessage(" "); + } + + p.sendMessage(C.DARK_GREEN + C.BOLD.toString() + gg + C.GRAY + "/" + C.RESET + C.ITALIC + C.GRAY + g.getName() + C.RESET + C.WHITE + " (1 of " + F.f(generator.getDimension().getObjectGroup(gg).size()) + " variants)"); + + if(biome.getSchematicGroups().containsKey(gg)) + { + String f = ""; + double percent = biome.getSchematicGroups().get(gg); + + if(percent > 1D) + { + f = (int) percent + " + " + F.pc(percent - (int) percent, percent - (int) percent >= 0.01 ? 0 : 3); + } + + else + { + f = F.pc(percent, percent >= 0.01 ? 0 : 3); + } + + p.sendMessage(C.GOLD + "Spawn Chance in " + C.YELLOW + biome.getName() + C.RESET + ": " + C.BOLD + C.WHITE + f); + } + + try + { + int a = 0; + int b = 0; + double c = 0; + + for(GenObject i : ggg.getSchematics()) + { + a += i.getSuccesses(); + b += i.getPlaces(); + } + + c = ((double) a / (double) b); + p.sendMessage(C.GRAY + "Grp: " + C.DARK_AQUA + F.f(a) + C.GRAY + " of " + C.AQUA + F.f(b) + C.GRAY + " placements (" + C.DARK_AQUA + F.pc(c, 0) + C.GRAY + ")"); + } + + catch(Throwable e) + { + e.printStackTrace(); + } + + p.sendMessage(C.GRAY + "Var: " + C.DARK_AQUA + F.f(g.getSuccesses()) + C.GRAY + " of " + C.AQUA + F.f(g.getPlaces()) + C.GRAY + " placements (" + C.DARK_AQUA + F.pc(g.getSuccess(), 0) + C.GRAY + ")"); + + draw(new Location[] {point.clone().add(g.getW() / 2, g.getH() / 2, g.getD() / 2), point.clone().subtract(g.getW() / 2, g.getH() / 2, g.getD() / 2) + }, p); + } + } + } + @EventHandler public void on(PlayerInteractEvent e) { @@ -260,6 +378,12 @@ public class WandController implements IrisController return createWand(left ? a : other, left ? other : a); } + public void dispose() + { + goc.clear(); + gog.clear(); + } + public static ItemStack createWand(Location a, Location b) { ItemStack is = new ItemStack(Material.BLAZE_ROD); diff --git a/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java b/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java index b2287409e..f02bd97cf 100644 --- a/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java +++ b/src/main/java/ninja/bytecode/iris/generator/IrisGenerator.java @@ -3,15 +3,18 @@ package ninja.bytecode.iris.generator; import java.util.List; import java.util.Random; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Biome; import org.bukkit.generator.BlockPopulator; +import org.bukkit.util.NumberConversions; import mortar.util.text.C; import ninja.bytecode.iris.Iris; import ninja.bytecode.iris.controller.PackController; import ninja.bytecode.iris.generator.genobject.GenObjectDecorator; +import ninja.bytecode.iris.generator.genobject.PlacedObject; import ninja.bytecode.iris.generator.layer.GenLayerBiome; import ninja.bytecode.iris.generator.layer.GenLayerCarving; import ninja.bytecode.iris.generator.layer.GenLayerCaverns; @@ -62,6 +65,7 @@ public class IrisGenerator extends ParallelChunkGenerator private MB PACKED_ICE = new MB(Material.PACKED_ICE); private MB WATER = new MB(Material.STATIONARY_WATER); private MB BEDROCK = new MB(Material.BEDROCK); + private GenObjectDecorator god; private GenLayerLayeredNoise glLNoise; private GenLayerBiome glBiome; private GenLayerCaves glCaves; @@ -350,7 +354,7 @@ public class IrisGenerator extends ParallelChunkGenerator if(Iris.settings.gen.genObjects) { - p.add(new GenObjectDecorator(this)); + p.add(god = new GenObjectDecorator(this)); } return p; @@ -408,4 +412,25 @@ public class IrisGenerator extends ParallelChunkGenerator { return disposed; } + + public PlacedObject nearest(Location o, int i) + { + PlacedObject f = null; + double d = Integer.MAX_VALUE; + if(god != null) + { + for(PlacedObject j : god.getHistory()) + { + double dx = Math.abs(NumberConversions.square(j.getX() - o.getX()) + NumberConversions.square(j.getY() - o.getY()) + NumberConversions.square(j.getZ() - o.getZ())); + + if(dx < d) + { + d = dx; + f = j; + } + } + } + + return f; + } } \ No newline at end of file diff --git a/src/main/java/ninja/bytecode/iris/generator/genobject/GenObject.java b/src/main/java/ninja/bytecode/iris/generator/genobject/GenObject.java index 62ac1f567..00521e640 100644 --- a/src/main/java/ninja/bytecode/iris/generator/genobject/GenObject.java +++ b/src/main/java/ninja/bytecode/iris/generator/genobject/GenObject.java @@ -44,6 +44,8 @@ public class GenObject private int w; private int h; private int d; + private int failures; + private int successes; private String name = "?"; private final GMap s; private BlockVector mount; @@ -290,14 +292,10 @@ public class GenObject L.w(C.WHITE + "Object " + C.YELLOW + getName() + C.WHITE + " failed to place in " + C.YELLOW + m.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(f.getBlockX()) + " " + F.f(f.getBlockY()) + " " + F.f(f.getBlockZ())); } + failures++; return null; } - if(b.material.equals(Material.SKULL)) - { - continue; - } - try { undo.put(f, placer.get(f)); @@ -310,6 +308,7 @@ public class GenObject } } + successes++; return start; } @@ -592,6 +591,26 @@ public class GenObject } } + public double getSuccess() + { + return (double) successes / ((double) successes + (double) failures); + } + + public int getFailures() + { + return failures; + } + + public int getSuccesses() + { + return successes; + } + + public int getPlaces() + { + return successes + failures; + } + public void dispose() { s.clear(); diff --git a/src/main/java/ninja/bytecode/iris/generator/genobject/GenObjectDecorator.java b/src/main/java/ninja/bytecode/iris/generator/genobject/GenObjectDecorator.java index 5911907fb..57069954f 100644 --- a/src/main/java/ninja/bytecode/iris/generator/genobject/GenObjectDecorator.java +++ b/src/main/java/ninja/bytecode/iris/generator/genobject/GenObjectDecorator.java @@ -32,6 +32,7 @@ import ninja.bytecode.shuriken.math.M; public class GenObjectDecorator extends BlockPopulator { + private GList placeHistory; private GMap> orderCache; private GMap> populationCache; private IPlacer placer; @@ -42,6 +43,7 @@ public class GenObjectDecorator extends BlockPopulator public GenObjectDecorator(IrisGenerator generator) { this.g = generator; + placeHistory = new GList<>(); populationCache = new GMap<>(); orderCache = new GMap<>(); ex = Executors.newSingleThreadExecutor(); @@ -103,6 +105,7 @@ public class GenObjectDecorator extends BlockPopulator { if(g.isDisposed()) { + placeHistory.clear(); return; } @@ -156,7 +159,11 @@ public class GenObjectDecorator extends BlockPopulator if(!t.isSolid() || !biome.isSurface(t)) { - L.w(C.WHITE + "Object " + C.YELLOW + i.getName() + "/*" + C.WHITE + " failed to place in " + C.YELLOW + t.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(b.getX()) + " " + F.f(b.getY()) + " " + F.f(b.getZ())); + if(Iris.settings.performance.verbose) + { + L.w(C.WHITE + "Object " + C.YELLOW + i.getName() + "/*" + C.WHITE + " failed to place in " + C.YELLOW + t.toString().toLowerCase() + C.WHITE + " at " + C.YELLOW + F.f(b.getX()) + " " + F.f(b.getY()) + " " + F.f(b.getZ())); + } + continue; } @@ -178,9 +185,25 @@ public class GenObjectDecorator extends BlockPopulator { Location start = g.place(x, b.getY(), z, placer); - if(start != null && Iris.settings.performance.verbose) + if(start != null) { - L.v(C.GRAY + "Placed " + C.DARK_GREEN + i.getName() + C.WHITE + "/" + C.DARK_GREEN + g.getName() + C.GRAY + " at " + C.DARK_GREEN + F.f(start.getBlockX()) + " " + F.f(start.getBlockY()) + " " + F.f(start.getBlockZ())); + if(Iris.settings.performance.verbose) + { + L.v(C.GRAY + "Placed " + C.DARK_GREEN + i.getName() + C.WHITE + "/" + C.DARK_GREEN + g.getName() + C.GRAY + " at " + C.DARK_GREEN + F.f(start.getBlockX()) + " " + F.f(start.getBlockY()) + " " + F.f(start.getBlockZ())); + } + + if(Iris.settings.performance.debugMode) + { + placeHistory.add(new PlacedObject(start.getBlockX(), start.getBlockY(), start.getBlockZ(), i.getName() + ":" + g.getName())); + + if(placeHistory.size() > Iris.settings.performance.placeHistoryLimit) + { + while(placeHistory.size() > Iris.settings.performance.placeHistoryLimit) + { + placeHistory.remove(0); + } + } + } } }); } @@ -214,4 +237,9 @@ public class GenObjectDecorator extends BlockPopulator return floor; } + + public GList getHistory() + { + return placeHistory; + } } diff --git a/src/main/java/ninja/bytecode/iris/generator/genobject/PlacedObject.java b/src/main/java/ninja/bytecode/iris/generator/genobject/PlacedObject.java new file mode 100644 index 000000000..62cd4b50f --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/generator/genobject/PlacedObject.java @@ -0,0 +1,95 @@ +package ninja.bytecode.iris.generator.genobject; + +public class PlacedObject +{ + private int x; + private int y; + private int z; + private String f; + + public PlacedObject(int x, int y, int z, String f) + { + this.x = x; + this.y = y; + this.z = z; + this.f = f; + } + + public int getX() + { + return x; + } + + public void setX(int x) + { + this.x = x; + } + + public int getY() + { + return y; + } + + public void setY(int y) + { + this.y = y; + } + + public int getZ() + { + return z; + } + + public void setZ(int z) + { + this.z = z; + } + + public String getF() + { + return f; + } + + public void setF(String f) + { + this.f = f; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((f == null) ? 0 : f.hashCode()); + result = prime * result + x; + result = prime * result + y; + result = prime * result + z; + return result; + } + + @Override + public boolean equals(Object obj) + { + if(this == obj) + return true; + if(obj == null) + return false; + if(getClass() != obj.getClass()) + return false; + PlacedObject other = (PlacedObject) obj; + if(f == null) + { + if(other.f != null) + return false; + } + else if(!f.equals(other.f)) + return false; + if(x != other.x) + return false; + if(y != other.y) + return false; + if(z != other.z) + return false; + return true; + } +} diff --git a/src/main/java/ninja/bytecode/iris/util/GRT.java b/src/main/java/ninja/bytecode/iris/util/GRT.java new file mode 100644 index 000000000..9285a4d9f --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/GRT.java @@ -0,0 +1,10 @@ +package ninja.bytecode.iris.util; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +@FunctionalInterface +public interface GRT +{ + public Glower getGlower(Entity entity, Player observer); +} diff --git a/src/main/java/ninja/bytecode/iris/util/GlossGlower.java b/src/main/java/ninja/bytecode/iris/util/GlossGlower.java new file mode 100644 index 000000000..0d1006e5b --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/GlossGlower.java @@ -0,0 +1,106 @@ +package ninja.bytecode.iris.util; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import mortar.api.nms.NMP; +import mortar.util.text.C; + +public class GlossGlower implements Glower +{ + private final Player observer; + private final Entity entity; + private ChatColor color; + private boolean sentTeam; + + public GlossGlower(Entity entity, Player observer) + { + sentTeam = false; + this.entity = entity; + this.observer = observer; + this.color = ChatColor.WHITE; + } + + @Override + public Entity getEntity() + { + return entity; + } + + @Override + public ChatColor getColor() + { + return color; + } + + @Override + public void setColor(ChatColor color) + { + if(color.isFormat()) + { + throw new UnsupportedOperationException("You cannot use format codes for glow colors"); + } + + this.color = color; + + if(observer == null) + { + for(Player i : entity.getWorld().getPlayers()) + { + NMP.host.sendGlowingColorMeta(i, getEntity(), C.values()[color.ordinal()]); + } + } + + else + { + NMP.host.sendGlowingColorMeta(getObserver(), getEntity(), C.values()[color.ordinal()]); + } + } + + @Override + public void setGlowing(boolean glowing) + { + if(observer == null) + { + for(Player i : entity.getWorld().getPlayers()) + { + NMP.host.sendEntityMetadata(i, getEntity().getEntityId(), NMP.host.getMetaEntityProperties(false, false, false, false, false, glowing, false)); + } + } + + else + { + NMP.host.sendEntityMetadata(observer, getEntity().getEntityId(), NMP.host.getMetaEntityProperties(false, false, false, false, false, glowing, false)); + } + } + + @Override + public void destroy() + { + setGlowing(false); + + if(sentTeam) + { + if(observer == null) + { + for(Player i : entity.getWorld().getPlayers()) + { + NMP.host.sendRemoveGlowingColorMeta(i, getEntity()); + } + } + + else + { + NMP.host.sendRemoveGlowingColorMeta(getObserver(), getEntity()); + } + + } + } + + @Override + public Player getObserver() + { + return observer; + } +} diff --git a/src/main/java/ninja/bytecode/iris/util/GlowManager.java b/src/main/java/ninja/bytecode/iris/util/GlowManager.java new file mode 100644 index 000000000..2933abe26 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/GlowManager.java @@ -0,0 +1,14 @@ +package ninja.bytecode.iris.util; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +public class GlowManager +{ + public static GRT f = null; + + public static Glower create(Entity e, Player observer) + { + return f.getGlower(e, observer); + } +} diff --git a/src/main/java/ninja/bytecode/iris/util/Glower.java b/src/main/java/ninja/bytecode/iris/util/Glower.java new file mode 100644 index 000000000..c99fd420a --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/Glower.java @@ -0,0 +1,20 @@ +package ninja.bytecode.iris.util; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +public interface Glower +{ + public Player getObserver(); + + public Entity getEntity(); + + public ChatColor getColor(); + + public void setColor(ChatColor color); + + public void setGlowing(boolean glowing); + + public void destroy(); +} diff --git a/src/main/java/ninja/bytecode/iris/util/GlowingBlock.java b/src/main/java/ninja/bytecode/iris/util/GlowingBlock.java new file mode 100644 index 000000000..08b5592e8 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/GlowingBlock.java @@ -0,0 +1,179 @@ +package ninja.bytecode.iris.util; + +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import mortar.api.nms.NMP; +import mortar.api.world.MaterialBlock; +import mortar.compute.math.M; +import mortar.util.text.C; + +public class GlowingBlock +{ + private static int idd = 123456789; + private int id; + private UUID uid; + private Location location; + private Location current; + private Player player; + private double factor; + private Vector velocity; + private boolean active; + private long mv = M.ms(); + private MaterialBlock mb; + private ChatColor c; + + public GlowingBlock(Player player, Location init, MaterialBlock mb, ChatColor c) + { + this.mb = mb; + this.uid = UUID.randomUUID(); + this.id = idd--; + location = init; + current = init.clone(); + this.player = player; + factor = Math.PI; + active = false; + velocity = new Vector(); + this.c = c; + } + + public int getId() + { + return id; + } + + public void sendMetadata(boolean glowing) + { + PacketGate.mark(PacketCategory.EFFECT); + NMP.host.sendEntityMetadata(player, id, NMP.host.getMetaEntityProperties(false, false, false, false, false, glowing, false)); + } + + public void sendMetadata(ChatColor c) + { + PacketGate.mark(PacketCategory.EFFECT); + //NMP.host.sendGlowingColorMetaEntity(getPlayer(), uid, C.values()[c.ordinal()]); + } + + public void update() + { + if(M.ms() - mv < 50) + { + return; + } + + if(location.getX() == current.getX() && location.getY() == current.getY() && location.getZ() == current.getZ()) + { + return; + } + + mv = M.ms(); + + if(location.distanceSquared(current) > 16) + { + if(PacketGate.can(PacketCategory.EFFECT)) + { + sendTeleport(location); + current = location; + } + } + + else + { + if(PacketGate.can(PacketCategory.EFFECT)) + { + double dx = location.getX() - current.getX(); + double dy = location.getY() - current.getY(); + double dz = location.getZ() - current.getZ(); + dx += velocity.getX(); + dy += velocity.getY(); + dz += velocity.getZ(); + dx = M.clip(dx, -8, 8); + dy = M.clip(dy, -8, 8); + dz = M.clip(dz, -8, 8); + sendMove(dx / factor, dy / factor, dz / factor); + current.add(dx / factor, dy / factor, dz / factor); + current.setX(Math.abs(location.getX() - current.getX()) < 0.00001 ? location.getX() : current.getX()); + current.setY(Math.abs(location.getY() - current.getY()) < 0.00001 ? location.getY() : current.getY()); + current.setZ(Math.abs(location.getZ() - current.getZ()) < 0.00001 ? location.getZ() : current.getZ()); + + if(location.getX() == current.getX() && location.getY() == current.getY() && location.getZ() == current.getZ()) + { + if(PacketGate.can(PacketCategory.EFFECT)) + { + sendTeleport(location); + current = location; + } + } + } + } + } + + public Location getPosition() + { + return location.clone(); + } + + public void setPosition(Location l) + { + location = l; + } + + public Player getPlayer() + { + return player; + } + + public void destroy() + { + sendDestroy(); + } + + public void create() + { + sendSpawn(); + } + + public boolean isActive() + { + return active; + } + + public void setFactor(int i) + { + factor = i; + } + + private void sendTeleport(Location l) + { + NMP.host.teleportEntity(id, player, l, false); + } + + private void sendMove(double x, double y, double z) + { + NMP.host.moveEntityRelative(id, player, x, y, z, false); + } + + public void sendDestroy() + { + active = false; + NMP.host.removeEntity(id, player); + NMP.host.sendRemoveGlowingColorMetaEntity(getPlayer(), uid); + sendMetadata(false); + PacketGate.mark(PacketCategory.EFFECT); + PacketGate.mark(PacketCategory.EFFECT); + } + + public void sendSpawn() + { + NMP.host.spawnFallingBlock(id, uid, location, player, mb); + sendMetadata(c); + sendMetadata(true); + active = true; + PacketGate.mark(PacketCategory.EFFECT); + PacketGate.mark(PacketCategory.EFFECT); + } +} diff --git a/src/main/java/ninja/bytecode/iris/util/PacketCategory.java b/src/main/java/ninja/bytecode/iris/util/PacketCategory.java new file mode 100644 index 000000000..cc5be7905 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/PacketCategory.java @@ -0,0 +1,9 @@ +package ninja.bytecode.iris.util; + +public enum PacketCategory +{ + BOARD, + HOLOGRAM, + EFFECT, + TABLIST; +} diff --git a/src/main/java/ninja/bytecode/iris/util/PacketGate.java b/src/main/java/ninja/bytecode/iris/util/PacketGate.java new file mode 100644 index 000000000..a03026a34 --- /dev/null +++ b/src/main/java/ninja/bytecode/iris/util/PacketGate.java @@ -0,0 +1,129 @@ +package ninja.bytecode.iris.util; + +import mortar.compute.math.RollingAverage; +import mortar.lang.collection.GMap; + +public class PacketGate +{ + private static final GMap gates = new GMap<>(); + private final RollingAverage average; + private final int pps; + private int sent; + + private PacketGate(int pps) + { + sent = 0; + this.pps = pps; + average = new RollingAverage(100); + } + + public void tick() + { + average.put(sent * 20D); + sent = 0; + } + + public boolean can() + { + if(should()) + { + mark(); + return true; + } + + return false; + } + + public boolean should() + { + if(average.get() < pps) + { + return true; + } + + return false; + } + + public void mark() + { + sent++; + } + + private double getAveragePPS() + { + return average.get(); + } + + public static int getTotalPPS() + { + double m = 0; + + for(PacketCategory i : PacketCategory.values()) + { + m += getAveragePPS(i); + } + + return (int) m; + } + + public static void tickAll() + { + if(gates.isEmpty()) + { + reset(); + } + + for(PacketCategory i : PacketCategory.values()) + { + gates.get(i).tick(); + } + } + + public static double getAveragePPS(PacketCategory cat) + { + if(!gates.containsKey(cat)) + { + reset(); + } + + return gates.get(cat).getAveragePPS(); + } + + public static boolean can(PacketCategory cat) + { + if(!gates.containsKey(cat)) + { + reset(); + } + + return gates.get(cat).can(); + } + + public static void mark(PacketCategory cat) + { + if(!gates.containsKey(cat)) + { + reset(); + } + + gates.get(cat).mark(); + } + + public static boolean should(PacketCategory cat) + { + if(!gates.containsKey(cat)) + { + reset(); + } + + return gates.get(cat).should(); + } + + public static void reset() + { + gates.put(PacketCategory.BOARD, new PacketGate(100)); + gates.put(PacketCategory.EFFECT, new PacketGate(100)); + gates.put(PacketCategory.HOLOGRAM, new PacketGate(100)); + gates.put(PacketCategory.TABLIST, new PacketGate(100)); + } +}