diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CEntity.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CEntity.java new file mode 100644 index 00000000..373a2acf --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CEntity.java @@ -0,0 +1,67 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.entity; + +import org.bukkit.Location; +import org.bukkit.entity.EntityType; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * CEntities are Entities that are a compound of other Entities. + */ +public class CEntity extends REntity { + + protected List entities = new ArrayList<>(); + + public CEntity(REntityServer server) { + super(server, EntityType.MARKER, new Location(null, 0, 0, 0)); + } + + public List getEntities() { + return new ArrayList<>(entities); + } + + public List getEntitiesByType(Class clazz) { + return entities.stream().filter(clazz::isInstance).map(clazz::cast).collect(Collectors.toList()); + } + + @Override + void tick() { + entities.forEach(REntity::tick); + } + + @Override + public void hide(boolean hide) { + super.hide(hide); + entities.forEach(rEntity -> { + rEntity.hide(hide); + }); + } + + @Override + public void die() { + super.die(); + entities.forEach(REntity::die); + entities.clear(); + } +} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CLine.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CLine.java new file mode 100644 index 00000000..f3b02deb --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CLine.java @@ -0,0 +1,243 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.entity; + +import org.bukkit.Location; +import org.bukkit.block.data.BlockData; +import org.bukkit.entity.Display; +import org.bukkit.entity.Player; +import org.bukkit.util.Consumer; +import org.bukkit.util.Transformation; +import org.bukkit.util.Vector; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import java.util.Objects; + +public class CLine extends CEntity { + + public static final float DEFAULT_WIDTH = 1 / 16f; + private static final float offset = 1 / 1024f; + private static final Vector offsetVec = new Vector(offset, offset, offset); + + private Location from; + private Location to; + private float width = DEFAULT_WIDTH; + private BlockData blockData = RBlockDisplay.DEFAULT_BLOCK; + private boolean hide = false; + + public CLine(REntityServer server) { + super(server); + } + + private CLine checkAndSet(T currentValue, T newValue, Consumer setter) { + if (Objects.equals(currentValue, newValue)) return this; + setter.accept(newValue); + tick(); + return this; + } + + public CLine setFrom(Location from) { + return checkAndSet(this.from, from, location -> this.from = location); + } + + public CLine setTo(Location to) { + return checkAndSet(this.to, to, location -> this.to = location); + } + + public CLine setWidth(float width) { + return checkAndSet(this.width, width, w -> this.width = w); + } + + public CLine setBlock(BlockData blockData) { + if (this.blockData.equals(blockData)) return this; + if (blockData == null) { + this.blockData = RBlockDisplay.DEFAULT_BLOCK; + } else { + this.blockData = blockData; + } + getEntitiesByType(RBlockDisplay.class).forEach(display -> { + display.setBlock(blockData); + }); + return this; + } + + @Override + public void hide(boolean hide) { + if (hide == this.hide) return; + this.hide = hide; + if (hide) { + if (startLine != null) startLine.hide(true); + if (middleLine != null) middleLine.hide(true); + if (endLine != null) endLine.hide(true); + } else { + tick(); + } + } + + @Override + void tick() { + if (from == null || to == null) return; + if (hide) return; + updateStart(); + updateMiddle(); + updateEnd(); + } + + private RBlockDisplay startLine; + private void updateStart() { + Vector vec = to.clone().subtract(from).toVector(); + if (vec.length() > 35) vec.normalize().multiply(35); + + if (startLine == null) { + startLine = new RBlockDisplay(server, new Location(null, 0, 0, 0)); + startLine.setBrightness(new Display.Brightness(15, 15)); + startLine.setViewRange(560); + startLine.setBlock(blockData); + entities.add(startLine); + } else { + startLine.hide(false); + } + + startLine.move(from.clone().subtract(offsetVec)); + startLine.setTransform(new Transformation(new Vector3f(0, 0, 0), new Quaternionf(0, 0, 0, 1), addWidth(vec).toVector3f(), new Quaternionf(0, 0, 0, 1))); + } + + private RBlockDisplay middleLine; + private void updateMiddle() { + Vector vec = to.clone().subtract(from).toVector(); + if (vec.length() <= 70) { + if (middleLine != null) middleLine.hide(true); + return; + } + if (vec.length() > 280) vec.normalize().multiply(280); + else vec = vec.clone().normalize().multiply(vec.length() - 60); + + if (middleLine == null) { + middleLine = new RBlockDisplay(server, new Location(null, 0, 0, 0)); + middleLine.setBrightness(new Display.Brightness(15, 15)); + middleLine.setViewRange(560); + middleLine.setBlock(blockData); + entities.add(middleLine); + } else { + middleLine.hide(false); + } + + Player player = server.getPlayers().stream().findFirst().orElse(null); + if (player == null) return; + + Vector tempVector = vec.clone().normalize().multiply(30); + Location from = this.from.clone().add(tempVector); + Location to = this.to.clone().subtract(tempVector); + + Vector lineVec = to.clone().subtract(from).toVector(); + Vector playerVec = player.getLocation().toVector().subtract(from.toVector()); + double lineVecDotItself = lineVec.dot(lineVec); + Vector projectionVec = lineVec.clone().multiply(lineVec.dot(playerVec)).divide(new Vector(lineVecDotItself, lineVecDotItself, lineVecDotItself)); + + Vector moveVec = from.toVector().add(projectionVec); + if (moveVec.getX() < from.getX()) { + moveVec.setX(from.getX()); + } + if (moveVec.getX() > to.getX()) { + moveVec.setX(to.getX()); + } + if (moveVec.getY() < from.getY()) { + moveVec.setY(from.getY()); + } + if (moveVec.getY() > to.getY()) { + moveVec.setY(to.getY()); + } + if (moveVec.getZ() < from.getZ()) { + moveVec.setZ(from.getZ()); + } + if (moveVec.getZ() > to.getZ()) { + moveVec.setZ(to.getZ()); + } + + Vector translation = vec.clone().divide(new Vector(2, 2, 2)); + translation.setX(-translation.getX()); + translation.setY(-translation.getY()); + translation.setZ(-translation.getZ()); + + Vector first = moveVec.clone().add(translation).subtract(from.toVector()); + if (first.getX() < 0) { + translation.setX(translation.getX() - first.getX()); + } + if (first.getY() < 0) { + translation.setY(translation.getY() - first.getY()); + } + if (first.getZ() < 0) { + translation.setZ(translation.getZ() - first.getZ()); + } + + Vector second = to.toVector().subtract(moveVec.clone().subtract(translation)); + if (second.getX() < 0) { + translation.setX(translation.getX() + second.getX()); + } + if (second.getY() < 0) { + translation.setY(translation.getY() + second.getY()); + } + if (second.getZ() < 0) { + translation.setZ(translation.getZ() + second.getZ()); + } + + middleLine.move(moveVec.toLocation(player.getWorld()).subtract(offsetVec)); + middleLine.setTransform(new Transformation(translation.toVector3f(), new Quaternionf(0, 0, 0, 1), addWidth(vec).toVector3f(), new Quaternionf(0, 0, 0, 1))); + } + + private RBlockDisplay endLine; + private void updateEnd() { + Vector vec = to.clone().subtract(from).toVector(); + if (vec.length() <= 35) { + if (endLine != null) endLine.hide(true); + return; + } + if (vec.length() > 35) vec.normalize().multiply(35); + + if (endLine == null) { + endLine = new RBlockDisplay(server, new Location(null, 0, 0, 0)); + endLine.setBrightness(new Display.Brightness(15, 15)); + endLine.setViewRange(560); + endLine.setBlock(blockData); + entities.add(endLine); + } else { + endLine.hide(false); + } + + endLine.move(to.clone().subtract(offsetVec)); + endLine.setTransform(new Transformation(vec.toVector3f().negate(), new Quaternionf(0, 0, 0, 1), addWidth(vec).toVector3f(), new Quaternionf(0, 0, 0, 1))); + } + + private Vector addWidth(Vector vector) { + vector = vector.clone(); + if (vector.getX() == 0) { + vector.setX(vector.getX() + width); + } + if (vector.getY() == 0) { + vector.setY(vector.getY() + width); + } + if (vector.getZ() == 0) { + vector.setZ(vector.getZ() + width); + } + vector.add(offsetVec).add(offsetVec); + return vector; + } +} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CWireframe.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CWireframe.java new file mode 100644 index 00000000..cf15912d --- /dev/null +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/CWireframe.java @@ -0,0 +1,103 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.entity; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.data.BlockData; +import org.bukkit.util.Consumer; +import org.bukkit.util.Vector; + +import java.util.List; +import java.util.Objects; + +/** + * Compound Box (12 CLine) + */ +public class CWireframe extends CEntity { + + public static final float DEFAULT_WIDTH = 1 / 16f; + private float width = DEFAULT_WIDTH; + + private Location pos1; + private Location pos2; + + public CWireframe(REntityServer server) { + super(server); + for (int i = 0; i < 12; i++) { + entities.add(new CLine(server)); + } + } + + public CWireframe setPos1(Location pos1) { + this.pos1 = pos1; + updateAndSpawnLines(); + return this; + } + + public CWireframe setPos2(Location pos2) { + this.pos2 = pos2; + updateAndSpawnLines(); + return this; + } + + public CWireframe setWidth(float width) { + this.width = width; + updateAndSpawnLines(); + getEntitiesByType(CLine.class).forEach(haaLine -> { + haaLine.setWidth(width); + }); + return this; + } + + public CWireframe setBlock(BlockData blockData) { + getEntitiesByType(CLine.class).forEach(haaLine -> { + haaLine.setBlock(blockData); + }); + return this; + } + + private void updateAndSpawnLines() { + if (pos1 == null || pos2 == null) return; + + World world = pos1.getWorld(); + Vector min = Vector.getMinimum(pos1.toVector(), pos2.toVector()); + Vector max = Vector.getMaximum(pos1.toVector(), pos2.toVector()) + .add(new Vector(1 - width, 1 - width, 1 - width)); + + List lines = getEntitiesByType(CLine.class); + lines.forEach(line -> line.setFrom(null).setTo(null)); + + lines.get(0).setFrom(new Vector(min.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX() + width, min.getY(), min.getZ()).toLocation(world)); + lines.get(1).setFrom(new Vector(min.getX(), max.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX() + width, max.getY(), min.getZ()).toLocation(world)); + lines.get(2).setFrom(new Vector(min.getX(), min.getY(), max.getZ()).toLocation(world)).setTo(new Vector(max.getX() + width, min.getY(), max.getZ()).toLocation(world)); + lines.get(3).setFrom(new Vector(min.getX(), max.getY(), max.getZ()).toLocation(world)).setTo(new Vector(max.getX() + width, max.getY(), max.getZ()).toLocation(world)); + + lines.get(4).setFrom(new Vector(min.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(min.getX(), max.getY() + width, min.getZ()).toLocation(world)); + lines.get(5).setFrom(new Vector(max.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX(), max.getY() + width, min.getZ()).toLocation(world)); + lines.get(6).setFrom(new Vector(min.getX(), min.getY(), max.getZ()).toLocation(world)).setTo(new Vector(min.getX(), max.getY() + width, max.getZ()).toLocation(world)); + lines.get(7).setFrom(new Vector(max.getX(), min.getY(), max.getZ()).toLocation(world)).setTo(new Vector(max.getX(), max.getY() + width, max.getZ()).toLocation(world)); + + lines.get(8).setFrom(new Vector(min.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(min.getX(), min.getY(), max.getZ() + width).toLocation(world)); + lines.get(9).setFrom(new Vector(max.getX(), min.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX(), min.getY(), max.getZ() + width).toLocation(world)); + lines.get(10).setFrom(new Vector(min.getX(), max.getY(), min.getZ()).toLocation(world)).setTo(new Vector(min.getX(), max.getY(), max.getZ() + width).toLocation(world)); + lines.get(11).setFrom(new Vector(max.getX(), max.getY(), min.getZ()).toLocation(world)).setTo(new Vector(max.getX(), max.getY(), max.getZ() + width).toLocation(world)); + } +} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/REntityServer.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/REntityServer.java index d5ced550..2d19e22c 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/REntityServer.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/REntityServer.java @@ -291,10 +291,8 @@ public class REntityServer implements Listener { } public void tick() { - for(HashSet entitiesInChunk : entities.values()) { - for(REntity entity : entitiesInChunk) { - entity.tick(); - } + for (REntity entity : entityMap.values()) { + entity.tick(); } }