From a68f45d82472201b3396f5ad020fd59a1f989ee0 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sun, 19 Mar 2023 20:23:16 +0100 Subject: [PATCH] Add basic TNT Signed-off-by: yoyosource --- .../features/simulator/Simulator15.java | 23 ++ .../features/simulator/Simulator19.java | 37 ++ .../bausystem/features/simulator/TNT.java | 327 ++++++++++++++++++ .../features/simulator/Simulator.java | 30 ++ .../features/simulator/TestCommand.java | 37 ++ 5 files changed, 454 insertions(+) create mode 100644 BauSystem_15/src/de/steamwar/bausystem/features/simulator/Simulator15.java create mode 100644 BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java create mode 100644 BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/Simulator.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TestCommand.java diff --git a/BauSystem_15/src/de/steamwar/bausystem/features/simulator/Simulator15.java b/BauSystem_15/src/de/steamwar/bausystem/features/simulator/Simulator15.java new file mode 100644 index 00000000..5576ff45 --- /dev/null +++ b/BauSystem_15/src/de/steamwar/bausystem/features/simulator/Simulator15.java @@ -0,0 +1,23 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.bausystem.features.simulator; + +public class Simulator15 implements Simulator { +} diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java new file mode 100644 index 00000000..0afd4a54 --- /dev/null +++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/Simulator19.java @@ -0,0 +1,37 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.bausystem.features.simulator; + +import org.bukkit.Bukkit; +import org.bukkit.World; + +public class Simulator19 implements Simulator { + + public static final World WORLD = Bukkit.getWorlds().get(0); + + @Override + public void run() { + TNT tnt = new TNT(0, 120, 0); + do { + System.out.println(tnt); + } while (!tnt.tick()); + System.out.println(tnt); + } +} diff --git a/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java new file mode 100644 index 00000000..4c1c267f --- /dev/null +++ b/BauSystem_19/src/de/steamwar/bausystem/features/simulator/TNT.java @@ -0,0 +1,327 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.bausystem.features.simulator; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.core.EnumDirection; +import net.minecraft.world.level.RayTrace; +import net.minecraft.world.phys.AxisAlignedBB; +import net.minecraft.world.phys.MovingObjectPosition; +import net.minecraft.world.phys.Vec3D; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.phys.shapes.VoxelShapes; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Bed; +import org.bukkit.block.data.type.Fence; +import org.bukkit.block.data.type.Gate; +import org.bukkit.block.data.type.Wall; +import org.bukkit.craftbukkit.v1_19_R2.CraftWorld; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.util.Vector; + +import java.util.List; +import java.util.Random; + +@Getter +@Setter +public class TNT { + + private static final Random R = new Random(); + + // Bottom left corner + private double x; + private double y; + private double z; + + private double vx; + private double vy; + private double vz; + + private int fuse; + + private boolean onGround = false; + private float fallDistance = 0; + + private boolean horizontalCollision = false; + private boolean verticalCollision = false; + private Vector movementMultiplier = new Vector(0, 0, 0); + + public TNT(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + + double seed = R.nextDouble() * 6.2831854820251465; + this.vx = -Math.sin(seed) * 0.02; + this.vy = 0.20000000298023224; + this.vz = -Math.cos(seed) * 0.02; + + this.fuse = 80; + } + + public boolean tick() { + this.vy -= 0.04; + + move(new Vector(this.vx, this.vy, this.vz)); + + this.vx *= 0.98; + this.vy *= 0.98; + this.vz *= 0.98; + + this.fuse--; + if (this.fuse <= 0) { + // TODO: Add explosion + return true; + } + return false; + } + + private void move(Vector movement) { + if (movement.lengthSquared() > 1.0E-7) { + movement.multiply(movementMultiplier); + movementMultiplier = new Vector(0, 0, 0); + vx = 0; + vy = 0; + vz = 0; + } + + Vector vec3d = adjustMovementForCollisions(movement); + double lengthSquared = vec3d.lengthSquared(); + if (lengthSquared > 1.0E-7) { + if (fallDistance != 0.0F) { + // TODO: This could be wrong + MovingObjectPosition movingObjectPosition = ((CraftWorld) Simulator19.WORLD).getHandle().a(new RayTrace(new Vec3D(x, y, z), new Vec3D(x + vx, y + vy, z + vz), RayTrace.BlockCollisionOption.d, RayTrace.FluidCollisionOption.d, null)); + if (movingObjectPosition.c() != MovingObjectPosition.EnumMovingObjectType.a) { + onLanding(); + } + } + + this.x += movement.getX(); + this.y += movement.getY(); + this.z += movement.getZ(); + } + + boolean bl = !approximatelyEquals(movement.getX(), vec3d.getX()); + boolean bl2 = !approximatelyEquals(movement.getZ(), vec3d.getZ()); + this.horizontalCollision = bl || bl2; + this.verticalCollision = movement.getY() != vec3d.getY(); + + this.onGround = this.verticalCollision && movement.getY() < 0.0D; + Vector blockPos = getLandingPos(); + Block block = Simulator19.WORLD.getBlockAt(blockPos.getBlockX(), blockPos.getBlockY(), blockPos.getBlockZ()); + fall(vec3d.getX(), onGround, block, blockPos); + + if (horizontalCollision) { + this.vx = bl ? 0.0 : this.vx; + this.vz = bl2 ? 0.0 : this.vz; + } + + if (movement.getY() != vec3d.getY()) { + if (block.getType() == Material.SLIME_BLOCK) { + if (this.vy < 0.0) { + this.vy = -this.vy * 0.8; + } + } + if (block.getBlockData() instanceof Bed) { + if (this.vy < 0.0) { + this.vy = -this.vy * 0.6600000262260437 * 0.8; + } + } + } + + if (onGround) { + if (block.getType() == Material.SLIME_BLOCK) { + double cy = Math.abs(this.vy); + if (cy < 0.1) { + double cy2 = 0.4 + cy * 0.2; + this.vx = vy * cy2; + this.vz = vz * cy2; + } + } + } + + checkBlockCollision(); + float j = this.getVelocityMultiplier(); + this.vy *= j; + this.vx *= j; + } + + private Vector adjustMovementForCollisions(Vector movement) { + AxisAlignedBB boundingBox = new AxisAlignedBB(x, y, z, x + 0.98, y + 0.98, z + 0.98); + return movement.lengthSquared() == 0.0 ? movement : adjustMovementForCollisions(null, movement, boundingBox, Simulator19.WORLD); + } + + public static Vector adjustMovementForCollisions(Entity entity, Vector movement, AxisAlignedBB entityBoundingBox, World world) { + Iterable voxelShapes = ((CraftWorld) world).getHandle().d(((CraftEntity) entity).getHandle(), entityBoundingBox); + List collisions = new java.util.ArrayList<>(); + voxelShapes.forEach(collisions::add); + + return adjustMovementForCollisions(movement, entityBoundingBox, collisions); + } + + private static Vector adjustMovementForCollisions(Vector movement, AxisAlignedBB entityBoundingBox, List collisions) { + if (collisions.isEmpty()) { + return movement; + } else { + double d = movement.getX(); + double e = movement.getY(); + double f = movement.getZ(); + if (e != 0.0) { + e = VoxelShapes.a(EnumDirection.EnumAxis.b, entityBoundingBox, collisions, e); + if (e != 0.0) { + entityBoundingBox = entityBoundingBox.c(0.0, e, 0.0); + } + } + + boolean bl = Math.abs(d) < Math.abs(f); + if (bl && f != 0.0) { + f = VoxelShapes.a(EnumDirection.EnumAxis.c, entityBoundingBox, collisions, f); + if (f != 0.0) { + entityBoundingBox = entityBoundingBox.c(0.0, 0.0, f); + } + } + + if (d != 0.0) { + d = VoxelShapes.a(EnumDirection.EnumAxis.a, entityBoundingBox, collisions, d); + if (!bl && d != 0.0) { + entityBoundingBox = entityBoundingBox.c(d, 0.0, 0.0); + } + } + + if (!bl && f != 0.0) { + f = VoxelShapes.a(EnumDirection.EnumAxis.c, entityBoundingBox, collisions, f); + } + + return new Vector(d, e, f); + } + } + + private boolean approximatelyEquals(double a, double b) { + return Math.abs(b - a) < 9.999999747378752E-6; + } + + private int floor(double value) { + int i = (int)value; + return value < (double)i ? i - 1 : i; + } + + private Vector getLandingPos() { + int x = floor(this.x); + int y = floor(this.y - 0.2F); + int z = floor(this.z); + + if (Simulator19.WORLD.getBlockAt(x, y, z).isEmpty()) { + Block block = Simulator19.WORLD.getBlockAt(x, y - 1, z); + BlockData blockData = block.getBlockData(); + if (blockData instanceof Fence || blockData instanceof Wall || blockData instanceof Gate) { + return new Vector(x, y - 1, z); + } + } + return new Vector(x, y, z); + } + + private void fall(double heightDifference, boolean onGround, Block state, Vector landedPosition) { + if (onGround) { + if (this.fallDistance > 0.0F) { + state.getBlock().onLandedUpon(this.world, state, landedPosition, this, this.fallDistance); + } + + this.onLanding(); + } else if (heightDifference < 0.0) { + this.fallDistance -= (float)heightDifference; + } + } + + private void checkBlockCollision() { + int x1 = floor(x + 1.0E-7); + int y1 = floor(y + 1.0E-7); + int z1 = floor(z + 1.0E-7); + int x2 = floor(x + 0.98 - 1.0E-7); + int y2 = floor(y + 0.98 - 1.0E-7); + int z2 = floor(z + 0.98 - 1.0E-7); + + for (int x = x1; x <= x2; x++) { + for (int y = y1; y <= y2; y++) { + for (int z = z1; z <= z2; z++) { + Block block = Simulator19.WORLD.getBlockAt(x, y, z); + + if (block.getType() == Material.POWDER_SNOW) { + slowMovement(new Vector(0.8999999761581421, 1.5, 0.8999999761581421)); + } else if (block.getType() == Material.HONEY_BLOCK) { + if (isSliding(new Vector(x, y, z))) { + updateSlidingVelocity(); + } + } else if (block.getType() == Material.COBWEB) { + slowMovement(new Vector(0.25, 0.05000000074505806, 0.25)); + } else if (block.getType() == Material.BUBBLE_COLUMN) { + // TODO: Bubble column + } + } + } + } + } + + private void slowMovement(Vector movementMultiplier) { + onLanding(); + this.movementMultiplier = movementMultiplier; + } + + private void updateSlidingVelocity() { + if (vy < -0.13) { + double d = -0.05 / vy; + vx *= d; + vz *= d; + } + vy = -0.05; + onLanding(); + } + + private boolean isSliding(Vector pos) { + if (onGround) return false; + if (y > pos.getY() + 0.9375 - 1.0E-7) return false; + if (vy >= -0.08) return false; + double d = Math.abs(pos.getX() + 0.5 - x); + double e = Math.abs(pos.getZ() + 0.5 - z); + double f = 0.4375 + 0.98 / 2.0; + return d + 1.0E-7 > f || e + 1.0E-7 > f; + } + + private void onLanding() { + this.fallDistance = 0.0F; + } + + @Override + public String toString() { + return "TNT{" + + "x=" + x + + ", y=" + y + + ", z=" + z + + ", vx=" + vx + + ", vy=" + vy + + ", vz=" + vz + + ", fuse=" + fuse + + '}'; + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/Simulator.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/Simulator.java new file mode 100644 index 00000000..6e1a8ab6 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/Simulator.java @@ -0,0 +1,30 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.bausystem.features.simulator; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.core.VersionDependent; + +public interface Simulator { + Simulator impl = VersionDependent.getVersionImpl(BauSystem.getInstance()); + + default void run() { + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TestCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TestCommand.java new file mode 100644 index 00000000..c0869fd6 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/simulator/TestCommand.java @@ -0,0 +1,37 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.bausystem.features.simulator; + +import de.steamwar.command.SWCommand; +import de.steamwar.linkage.Linked; +import org.bukkit.entity.Player; + +@Linked +public class TestCommand extends SWCommand { + + public TestCommand() { + super("test"); + } + + @Register + public void genericCommand(Player player) { + Simulator.impl.run(); + } +}