第一次提交

This commit is contained in:
YuTian 2024-07-05 00:07:50 +08:00
commit 910c578f99
16 changed files with 1543 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/ColorblindWar.iml
/.idea/
/target/

84
pom.xml Normal file
View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.io.yutian</groupId>
<artifactId>ColorblindWar</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ColorblindWar</name>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>papermc-repo</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
<repository>
<id>public</id>
<url>http://111.230.48.153:18081/repository/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.18.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fastasyncworldedit.bukkit</groupId>
<artifactId>FastAsyncWorldEdit</artifactId>
<version>2.9.1</version>
<classifier>660</classifier>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,86 @@
package com.io.yutian.colorblindwar;
import com.io.yutian.colorblindwar.game.DirectionPoint;
import com.io.yutian.colorblindwar.game.Game;
import com.io.yutian.colorblindwar.listener.PlayerListener;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
public final class ColorblindWar extends JavaPlugin {
private static ColorblindWar instance;
private static Game game;
@Override
public void onEnable() {
instance = this;
game = new Game();
Bukkit.getPluginManager().registerEvents(new PlayerListener(), this);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
sender.sendMessage("/cw create - 创建游戏");
sender.sendMessage("/cw start - 开始游戏");
sender.sendMessage("/cw stop - 结束游戏");
sender.sendMessage("/gw reload - 重载");
return true;
} else {
String subCommand = args[0];
if (subCommand.equalsIgnoreCase("create")) {
if (!(sender instanceof Player)) {
sender.sendMessage("非玩家无法创建游戏");
return true;
}
Player player = (Player) sender;
game.setWorld(player.getWorld());
game.setSpawnPoint(DirectionPoint.of(player.getLocation()));
game.reload();
player.sendMessage("成功创建游戏");
} else if (subCommand.equalsIgnoreCase("start")) {
if (!(sender instanceof Player)) {
sender.sendMessage("非玩家无法开始游戏");
return true;
}
if (game.isStarted()) {
sender.sendMessage("游戏已开始");
return true;
}
Player player = (Player) sender;
game.start(player);
} else if (subCommand.equalsIgnoreCase("stop")) {
if (!game.isStarted()) {
sender.sendMessage("游戏未开始");
return true;
}
Player player = (Player) sender;
game.stop(false);
} else if (subCommand.equalsIgnoreCase("reload")) {
game.reload();
sender.sendMessage("重载成功");
} else if (subCommand.equalsIgnoreCase("test")) {
if (args[1].equalsIgnoreCase("spawn")) {
game.spawnBuild();
} else if (args[1].equalsIgnoreCase("clear")) {
game.clearBlock();
} else if (args[1].equalsIgnoreCase("v")) {
game.vanishBlock();
}
}
}
return true;
}
public static ColorblindWar inst() {
return instance;
}
public static Game getGame() {
return game;
}
}

View File

@ -0,0 +1,84 @@
package com.io.yutian.colorblindwar.game;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import java.util.Objects;
public class DirectionPoint extends Point {
private float yaw;
private float pitch;
public DirectionPoint(int x, int y, int z, float yaw, float pitch) {
super(x, y, z);
this.yaw = yaw;
this.pitch = pitch;
}
public DirectionPoint(double x, double y, double z) {
this(x, y, z, 0f, 0f);
}
public DirectionPoint(double x, double y, double z, float yaw, float pitch) {
super(x, y, z);
this.yaw = yaw;
this.pitch = pitch;
}
public float getPitch() {
return pitch;
}
public float getYaw() {
return yaw;
}
public void setYaw(float yaw) {
this.yaw = yaw;
}
public void setPitch(float pitch) {
this.pitch = pitch;
}
@Override
public Location toLocation(World world) {
return new Location(world, getX(), getY(), getZ(), yaw, pitch);
}
public static DirectionPoint of(Location location) {
return new DirectionPoint(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
@Override
public String toString() {
return "DirectionPoint{" +
"x=" + getX() +
", y=" + getY() +
", z=" + getZ() +
", yaw=" + yaw +
", pitch=" + pitch +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
DirectionPoint that = (DirectionPoint) o;
return super.equals(o) && Float.compare(that.yaw, yaw) == 0 && Float.compare(that.pitch, pitch) == 0;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), yaw, pitch);
}
public static DirectionPoint deserialize(ConfigurationSection section) {
return new DirectionPoint(section.getDouble("x"), section.getDouble("y"), section.getDouble("z"), (float) section.getDouble("yaw"), (float) section.getDouble("pitch"));
}
}

View File

@ -0,0 +1,359 @@
package com.io.yutian.colorblindwar.game;
import com.io.yutian.colorblindwar.ColorblindWar;
import com.io.yutian.colorblindwar.util.*;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.function.mask.InverseSingleBlockTypeMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BlockTypes;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.*;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import java.util.*;
public class Game {
private static final List<Material> MATERIAL_LIST = Arrays.asList(Material.WHITE_WOOL, Material.BLACK_WOOL, Material.BROWN_WOOL, Material.BLUE_WOOL, Material.GREEN_WOOL, Material.RED_WOOL, Material.YELLOW_WOOL, Material.PURPLE_WOOL, Material.ORANGE_WOOL, Material.PINK_WOOL, Material.LIGHT_BLUE_WOOL, Material.LIME_WOOL);
private World world;
private DirectionPoint spawnPoint;
private Player player;
private BossBar bossBar1;
private BossBar bossBar2;
private BossBar bossBar3;
private BossBar bossBar4;
private List<BukkitTask> tasks = new ArrayList<>();
private List<Entity> entities = new ArrayList<>();
private int challengeAmount = 0;
private int vanishCountdown = 0;
private int vanishCooldown = 0;
private Material vanishMaterial = Material.AIR;
private boolean started = false;
private GameConfig gameConfig;
private BuildSpawner buildSpawner;
public Game() {
reload();
this.bossBar1 = Bukkit.createBossBar("今日挑战进度", BarColor.WHITE, BarStyle.SEGMENTED_10);
this.bossBar2 = Bukkit.createBossBar("爬塔进度", BarColor.WHITE, BarStyle.SEGMENTED_20);
this.bossBar3 = Bukkit.createBossBar("方块消失倒计时", BarColor.WHITE, BarStyle.SOLID);
this.bossBar4 = Bukkit.createBossBar("方块出现倒计时", BarColor.WHITE, BarStyle.SOLID);
}
public void reload() {
ColorblindWar.inst().saveDefaultConfig();
ColorblindWar.inst().reloadConfig();
FileConfiguration config = ColorblindWar.inst().getConfig();
if (config.contains("world")) {
this.world = Bukkit.getWorld(config.getString("world"));
}
if (config.contains("spawnPoint") && config.isConfigurationSection("spawnPoint")) {
this.spawnPoint = DirectionPoint.deserialize(config.getConfigurationSection("spawnPoint"));
}
if (world == null || spawnPoint == null) {
return;
}
BuildSpawner.Direction initialDirection = BuildSpawner.Direction.NORTH;
int chunkWight = 2;
int chunkLength = 2;
int ladderLength = 3;
int ladderAmount = 5;
int platformWidth = 3;
int platformLength = 7;
int levelAmount = 10;
BuildSpawner.SpawnMode spawnMode = BuildSpawner.SpawnMode.MODE_2;
int completeAmount = config.getInt("completeAmount", 10);
int countdownTime = config.getInt("countdownTime", 15);
this.gameConfig = new GameConfig(initialDirection, chunkWight, chunkLength, ladderLength, ladderAmount, platformWidth, platformLength, levelAmount, spawnMode, MATERIAL_LIST, completeAmount, countdownTime);
this.buildSpawner = gameConfig.getSpawner(world, spawnPoint);
this.vanishCountdown = gameConfig.getCountdownTime() * 20;
}
public void start(Player player) {
if (started) {
return;
}
if (world == null || spawnPoint == null) {
return;
}
this.started = true;
this.player = player;
this.challengeAmount = 0;
this.vanishCountdown = gameConfig.getCountdownTime() * 20;
initWorld();
updateBossBar();
this.bossBar1.addPlayer(player);
this.bossBar2.addPlayer(player);
this.bossBar3.addPlayer(player);
this.bossBar4.addPlayer(player);
spawnBuild();
changeVanishMaterial();
player.teleport(spawnPoint.toLocation(world));
this.tasks.add(new BukkitRunnable() {
@Override
public void run() {
updateBossBar();
}
}.runTaskTimer(ColorblindWar.inst(), 0L, 10L));
this.tasks.add(new BukkitRunnable() {
@Override
public void run() {
updateVanishCountdown();
}
}.runTaskTimer(ColorblindWar.inst(), 0L, 1L));
}
private void initWorld() {
this.world.setGameRule(GameRule.DO_DAYLIGHT_CYCLE, false);
this.world.setGameRule(GameRule.DO_WEATHER_CYCLE, false);
this.world.setGameRule(GameRule.DO_MOB_SPAWNING, false);
this.world.setGameRule(GameRule.DO_MOB_LOOT, false);
this.world.setGameRule(GameRule.MOB_GRIEFING, false);
this.world.setTime(6000);
}
public void stop(boolean win) {
if (!started) {
return;
}
this.started = false;
for (Entity entity : entities) {
entity.remove();
}
this.bossBar1.removeAll();
this.bossBar2.removeAll();
this.bossBar3.removeAll();
this.bossBar4.removeAll();
this.player.getInventory().clear();
this.player.teleport(spawnPoint.toLocation(world));
this.entities.clear();
if (win) {
new BukkitRunnable() {
private int i = 0;
@Override
public void run() {
if (i >= 20) {
cancel();
return;
}
player.getWorld().spawn(player.getLocation(), Firework.class, (firework -> {
FireworkMeta fireworkMeta = firework.getFireworkMeta();
fireworkMeta.addEffect(FireworkEffect.builder().withColor(Color.TEAL, Color.RED, Color.GREEN, Color.YELLOW, Color.LIME).trail(true).build());
Random random = new Random();
for (int i = 0; i < RandomUtil.getRandomInt(1, 2); i++) {
FireworkEffect effect = FireworkEffect.builder().flicker(random.nextBoolean()).withColor(Color.fromRGB(RandomUtil.getRandomInt(100, 255), RandomUtil.getRandomInt(100, 255), RandomUtil.getRandomInt(100, 255))).withFade(Color.fromRGB(RandomUtil.getRandomInt(100, 255), RandomUtil.getRandomInt(100, 255), RandomUtil.getRandomInt(100, 255))).with(FireworkEffect.Type.values()[random.nextInt(FireworkEffect.Type.values().length)]).trail(random.nextBoolean()).build();
fireworkMeta.addEffect(effect);
}
fireworkMeta.setPower(random.nextInt(2));
firework.setFireworkMeta(fireworkMeta);
}));
i++;
}
}.runTaskTimer(ColorblindWar.inst(), 0L, 5L);
player.sendMessage("§c[系统]§ a今日挑战已完成! 恭喜你!");
start(player);
} else {
player.sendMessage("§c[系统] §a游戏已被强制结束!");
}
tasks.forEach(task -> {
if (!task.isCancelled()) {
task.cancel();
}
});
}
private void updateBossBar() {
int completeAmount = gameConfig.getCompleteAmount();
double d = (double) challengeAmount / (double) completeAmount;
bossBar1.setTitle("§6今日挑战进度: §f"+challengeAmount+"/"+completeAmount);
if (d < 0) {
d = 0;
}
bossBar1.setProgress(d);
bossBar1.setColor(BossBarUtil.getBarColor(d));
int maxHeight = spawnPoint.getBlockY() + buildSpawner.getHeight();
int nowHeight = player.getLocation().getBlockY();
int c1 = nowHeight - spawnPoint.getBlockY();
c1 = Math.max(c1, 0);
double d1 = (double) c1 / (double) buildSpawner.getHeight();
d1 = Math.min(d1, 1.0);
double d2 = MathUtil.round(d1 * 100, 2);
bossBar2.setTitle("§6爬塔进度: §f"+c1+"/"+buildSpawner.getHeight()+" §b("+d2+"%)");
bossBar2.setProgress(d1);
bossBar2.setColor(BossBarUtil.getBarColor(d1));
sendActionBar();
}
private void updateVanishCountdown() {
if (vanishCooldown > 0) {
vanishCooldown--;
if (bossBar3.isVisible()) {
bossBar3.setVisible(false);
}
if (!bossBar4.isVisible()) {
bossBar4.setVisible(true);
}
bossBar4.setTitle("§6方块出现倒计时: §f"+ MathUtil.round(vanishCooldown / (double) 20, 1) +"s");
double p = vanishCooldown / (double) 60;
bossBar4.setProgress(p);
bossBar4.setColor(BossBarUtil.getBarColor(p));
if (vanishCooldown == 0) {
bossBar4.setVisible(false);
startVanishCountdown();
return;
}
return;
} else {
if (!bossBar3.isVisible()) {
bossBar3.setVisible(true);
}
if (bossBar4.isVisible()) {
bossBar4.setVisible(false);
}
}
if (vanishCountdown > 0) {
vanishCountdown--;
if (vanishCountdown <= 100 && vanishCountdown % 20 == 0) {
player.playSound(player.getLocation(), Sound.BLOCK_NOTE_BLOCK_GUITAR, 1.0F, 1.0F);
}
bossBar3.setTitle("§6方块消失倒计时: §f"+ MathUtil.round(vanishCountdown / (double) 20, 1) +"s");
double p = vanishCountdown / (double) (gameConfig.getCountdownTime() * 20);
bossBar3.setProgress(p);
bossBar3.setColor(BossBarUtil.getBarColor(p));
} else {
vanishBlock();
for (int i = 0; i < 9; i++) {
player.getInventory().setItem(i, null);
}
vanishCooldown = 60;
bossBar3.setVisible(false);
}
}
private void startVanishCountdown() {
vanishCountdown = gameConfig.getCountdownTime() * 20;
spawnBuild();
changeVanishMaterial();
}
private void changeVanishMaterial() {
vanishMaterial = buildSpawner.getRandomMaterial();
ItemStack itemStack = new ItemStack(vanishMaterial);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setDisplayName("");
itemStack.setItemMeta(itemMeta);
for (int i = 0; i < 9; i++) {
player.getInventory().setItem(i, itemStack);
}
}
private void sendActionBar() {
Component message = Component.text("§l"+ ColorUtil.getColorName(vanishMaterial))
.color(TextColor.fromHexString(ColorUtil.getColorHex(vanishMaterial)));
player.sendActionBar(message);
}
public void spawnBuild() {
buildSpawner.spawn();
}
public void vanishBlock() {
Material material = vanishMaterial;
Region region = buildSpawner.getEffectiveRegion(world);
Point minPoint = region.getMin();
Point maxPoint = region.getMax();
BlockVector3 newVector1 = BlockVector3.at(minPoint.getX(), minPoint.getY(), minPoint.getZ());
BlockVector3 newVector2 = BlockVector3.at(maxPoint.getX(), maxPoint.getY(), maxPoint.getZ());
CuboidRegion cuboidRegion = new CuboidRegion(BukkitAdapter.adapt(region.getWorld()),newVector1,newVector2);
try (EditSession editSession = WorldEdit.getInstance().newEditSession(BukkitAdapter.adapt(region.getWorld()))) {
Mask mask = new InverseSingleBlockTypeMask(editSession, BukkitAdapter.asBlockType(material));
editSession.replaceBlocks(cuboidRegion, mask, BlockTypes.AIR.getDefaultState());
Operations.complete(editSession.commit());
} catch (Exception e) {
e.printStackTrace();
}
}
public void clearBlock() {
Region region = buildSpawner.getEffectiveRegion(world);
Point minPoint = region.getMin();
Point maxPoint = region.getMax();
BlockVector3 newVector1 = BlockVector3.at(minPoint.getX(), minPoint.getY(), minPoint.getZ());
BlockVector3 newVector2 = BlockVector3.at(maxPoint.getX(), maxPoint.getY(), maxPoint.getZ());
CuboidRegion cuboidRegion = new CuboidRegion(BukkitAdapter.adapt(region.getWorld()),newVector1,newVector2);
try (EditSession editSession = WorldEdit.getInstance().newEditSession(BukkitAdapter.adapt(region.getWorld()))) {
editSession.setBlocks((com.sk89q.worldedit.regions.Region) cuboidRegion, BlockTypes.AIR.getDefaultState());
Operations.complete(editSession.commit());
} catch (Exception e) {
e.printStackTrace();
}
}
public void setWorld(World world) {
this.world = world;
FileConfiguration config = ColorblindWar.inst().getConfig();
config.set("world", world.getName());
ColorblindWar.inst().saveConfig();
}
public void setSpawnPoint(DirectionPoint spawnPoint) {
this.spawnPoint = spawnPoint;
FileConfiguration config = ColorblindWar.inst().getConfig();
ConfigurationSection section1 = config.getConfigurationSection("spawnPoint");
section1.set("x", spawnPoint.getX());
section1.set("y", spawnPoint.getY());
section1.set("z", spawnPoint.getZ());
section1.set("yaw", spawnPoint.getYaw());
section1.set("pitch", spawnPoint.getPitch());
ColorblindWar.inst().saveConfig();
}
public boolean isStarted() {
return started;
}
public World getWorld() {
return world;
}
public Point getSpawnPoint() {
return spawnPoint;
}
public GameConfig getGameConfig() {
return gameConfig;
}
public BuildSpawner getBuildSpawner() {
return buildSpawner;
}
}

View File

@ -0,0 +1,91 @@
package com.io.yutian.colorblindwar.game;
import com.io.yutian.colorblindwar.util.BuildSpawner;
import org.bukkit.Material;
import org.bukkit.World;
import java.util.List;
public class GameConfig {
private BuildSpawner.Direction initialDirection;
private int chunkWight;
private int chunkHeight;
private int ladderLength;
private int ladderAmount;
private int platformWidth;
private int platformLength;
private int levelAmount;
private BuildSpawner.SpawnMode spawnMode;
private List<Material> materials;
private int completeAmount = 10;
private int countdownTime = 15;
public GameConfig(BuildSpawner.Direction initialDirection, int chunkWight, int chunkHeight, int ladderLength, int ladderAmount, int platformWidth, int platformLength, int levelAmount, BuildSpawner.SpawnMode spawnMode, List<Material> materials, int completeAmount, int countdownTime) {
this.initialDirection = initialDirection;
this.chunkWight = chunkWight;
this.chunkHeight = chunkHeight;
this.ladderLength = ladderLength;
this.ladderAmount = ladderAmount;
this.platformWidth = platformWidth;
this.platformLength = platformLength;
this.levelAmount = levelAmount;
this.spawnMode = spawnMode;
this.materials = materials;
this.completeAmount = completeAmount;
this.countdownTime = countdownTime;
}
public BuildSpawner.Direction getInitialDirection() {
return initialDirection;
}
public int getChunkWight() {
return chunkWight;
}
public int getChunkHeight() {
return chunkHeight;
}
public int getLadderLength() {
return ladderLength;
}
public int getLadderAmount() {
return ladderAmount;
}
public int getPlatformWidth() {
return platformWidth;
}
public int getPlatformLength() {
return platformLength;
}
public int getLevelAmount() {
return levelAmount;
}
public BuildSpawner.SpawnMode getSpawnMode() {
return spawnMode;
}
public List<Material> getMaterials() {
return materials;
}
public int getCompleteAmount() {
return completeAmount;
}
public int getCountdownTime() {
return countdownTime;
}
public BuildSpawner getSpawner(World world, Point point) {
return new BuildSpawner(world, initialDirection, point.getBlockX(), point.getBlockY() - 1, point.getBlockZ(), chunkWight, chunkHeight, ladderLength, ladderAmount, platformWidth, platformLength, levelAmount, spawnMode, materials);
}
}

View File

@ -0,0 +1,106 @@
package com.io.yutian.colorblindwar.game;
import com.sk89q.worldedit.math.BlockVector3;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import java.util.Objects;
public class Point {
private double x;
private double y;
private double z;
public Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public Point(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public int getBlockX() {
return (int) Math.floor(x);
}
public int getBlockY() {
return (int) Math.floor(y);
}
public int getBlockZ() {
return (int) Math.floor(z);
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setZ(double z) {
this.z = z;
}
public Point clone() {
return new Point(x, y, z);
}
public Location toLocation(World world) {
return new Location(world, x, y, z, 0, 0);
}
public static Point of(Location location) {
return new Point(location.getX(), location.getY(), location.getZ());
}
public static Point deserialize(ConfigurationSection section) {
return new Point(section.getDouble("x"), section.getDouble("y"), section.getDouble("z"));
}
public BlockVector3 toBlockVector3() {
return BlockVector3.at(x, y, z);
}
@Override
public String toString() {
return "Point{" +
"x=" + x +
", y=" + y +
", z=" + z +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return Double.compare(point.x, x) == 0 && Double.compare(point.y, y) == 0 && Double.compare(point.z, z) == 0;
}
@Override
public int hashCode() {
return Objects.hash(x, y, z);
}
}

View File

@ -0,0 +1,51 @@
package com.io.yutian.colorblindwar.game;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
public class Region {
private World world;
private Point min;
private Point max;
public Region(World world, Point min, Point max) {
this.world = world;
this.min = min;
this.max = max;
}
public World getWorld() {
return world;
}
public Point getMin() {
return min;
}
public Point getMax() {
return max;
}
public static Region deserialize(ConfigurationSection section) {
World world1 = Bukkit.getWorld(section.getString("world"));
Point point1 = Point.deserialize(section.getConfigurationSection("min"));
Point point2 = Point.deserialize(section.getConfigurationSection("max"));
return new Region(world1, point1, point2);
}
public boolean isInRegion(Location location) {
if (!location.getWorld().getName().equalsIgnoreCase(world.getName())) {
return false;
}
return (location.getBlockX() >= this.min.getX()
&& location.getBlockX() <= this.max.getX()
&& location.getBlockY() >= this.min.getY()
&& location.getBlockY() <= this.max.getY()
&& location.getBlockZ() >= this.min.getZ()
&& location.getBlockZ() <= this.max.getZ());
}
}

View File

@ -0,0 +1,85 @@
package com.io.yutian.colorblindwar.listener;
import com.io.yutian.colorblindwar.ColorblindWar;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.*;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.weather.WeatherChangeEvent;
public class PlayerListener implements Listener {
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
if (ColorblindWar.getGame().isStarted()) {
ColorblindWar.getGame().stop(false);
}
}
@EventHandler
public void onPlayerDropItem(PlayerDropItemEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.setCancelled(true);
}
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.setCancelled(true);
}
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.setCancelled(true);
}
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.setCancelled(true);
}
}
@EventHandler
public void onEntityExplode(EntityExplodeEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.blockList().clear();
}
}
@EventHandler
public void onBlockExplode(BlockExplodeEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.blockList().clear();
}
}
@EventHandler
public void onWeatherChange(WeatherChangeEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.setCancelled(true);
}
}
@EventHandler
public void onBlockFire(BlockBurnEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.setCancelled(true);
}
}
@EventHandler
public void onBlockIgnite(BlockIgniteEvent event) {
if (ColorblindWar.getGame().isStarted()) {
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,17 @@
package com.io.yutian.colorblindwar.util;
import org.bukkit.boss.BarColor;
public class BossBarUtil {
public static BarColor getBarColor(double d) {
if (d >= 0 && d <= 0.3333) {
return BarColor.RED;
} else if (d <= 0.6666) {
return BarColor.YELLOW;
} else {
return BarColor.GREEN;
}
}
}

View File

@ -0,0 +1,415 @@
package com.io.yutian.colorblindwar.util;
import com.io.yutian.colorblindwar.game.Point;
import com.io.yutian.colorblindwar.game.Region;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.util.Vector;
import java.util.List;
public class BuildSpawner {
private World world;
private Direction initialDirection;
private int originX;
private int originY;
private int originZ;
private int chunkWight;
private int chunkLength;
private int ladderLength;
private int ladderAmount;
private int platformWidth;
private int platformLength;
private int levelAmount;
private SpawnMode spawnMode;
private int nowX;
private int nowY;
private int nowZ;
private Direction nowDirection;
private List<Material> materials;
protected ISpawnModeHander spawnModeHander;
public BuildSpawner(World world, Direction initialDirection, int originX, int originY, int originZ, int chunkWight, int chunkLength, int ladderLength, int ladderAmount, int platformWidth, int platformLength, int levelAmount, SpawnMode spawnMode, List<Material> materials) {
this.world = world;
this.initialDirection = initialDirection;
this.originX = originX;
this.originY = originY;
this.originZ = originZ;
this.chunkWight = chunkWight;
this.chunkLength = chunkLength;
this.ladderLength = ladderLength;
this.ladderAmount = ladderAmount;
this.platformWidth = platformWidth;
this.platformLength = platformLength;
this.levelAmount = levelAmount;
this.spawnMode = spawnMode;
this.materials = materials;
nowX = originX;
nowY = originY;
nowZ = originZ;
nowDirection = initialDirection;
if (spawnMode == SpawnMode.MODE_1) {
spawnModeHander = new SpawnModeHandler_1();
} else if (spawnMode == SpawnMode.MODE_2) {
spawnModeHander = new SpawnModeHandler_2();
}
}
public void spawn() {
nowX = originX;
nowY = originY;
nowZ = originZ;
nowDirection = initialDirection;
if (spawnModeHander != null) {
spawnModeHander.spawn();
}
}
private void spawnPlatform(int x, int y, int z, Direction direction) {
if (direction == Direction.EAST || direction == Direction.WEST) {
for (int i = 0; i < platformLength; i++) {
for (int j = 0; j < platformWidth; j++) {
int x1 = x + (i * chunkWight) * direction.getPlatformVector().getBlockX();
int z1 = z + (j * chunkLength) * direction.getPlatformVector().getBlockZ();
spawnPlatformChunk(x1, y, z1, direction);
}
}
} else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
for (int i = 0; i < platformLength; i++) {
for (int j = 0; j < platformWidth; j++) {
int x1 = x + (j * chunkLength) * direction.getPlatformVector().getBlockX();
int z1 = z + (i * chunkWight) * direction.getPlatformVector().getBlockZ();
spawnPlatformChunk(x1, y, z1, direction);
}
}
}
}
private void spawnLadder(int x, int y, int z, Direction direction) {
for (int i = 0; i < ladderAmount; i++) {
for (int j = 0; j < ladderLength; j++) {
int x1 = getLadderX(i, j, x, z, direction);
int z1 = getLadderZ(i, j, x, z, direction);
spawnLadderChunk(x1, y + i + 1, z1, direction);
}
}
}
private int getLadderX(int i, int j, int x, int z, Direction direction) {
switch (direction) {
case EAST:
case WEST:
return x + (i * chunkWight) * direction.getLadderVector().getBlockX();
case SOUTH:
case NORTH:
return x + (j * chunkLength) * direction.getLadderVector().getBlockX();
}
return x;
}
private int getLadderZ(int i, int j, int x, int z, Direction direction) {
switch (direction) {
case EAST:
case WEST:
return z + (j * chunkLength) * direction.getLadderVector().getBlockZ();
case SOUTH:
case NORTH:
return z + (i * chunkWight) * direction.getLadderVector().getBlockZ();
}
return z;
}
private void spawnPlatformChunk(int x, int y, int z, Direction direction) {
Material material = getRandomMaterial();
if (direction == Direction.EAST || direction == Direction.WEST) {
for (int i = 0; i < chunkWight; i++) {
for (int j = 0; j < chunkLength; j++) {
int x1 = x + i * direction.getPlatformVector().getBlockX();
int z1 = z + j * direction.getPlatformVector().getBlockZ();
world.getBlockAt(x1, y, z1).setType(material);
}
}
} else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
for (int i = 0; i < chunkWight; i++) {
for (int j = 0; j < chunkLength; j++) {
int x1 = x + j * direction.getPlatformVector().getBlockX();
int z1 = z + i * direction.getPlatformVector().getBlockZ();
world.getBlockAt(x1, y, z1).setType(material);
}
}
}
}
private void spawnLadderChunk(int x, int y, int z, Direction direction) {
Material material = getRandomMaterial();
if (direction == Direction.EAST || direction == Direction.WEST) {
for (int i = 0; i < chunkWight; i++) {
for (int j = 0; j < chunkLength; j++) {
int x1 = x + i * direction.getLadderVector().getBlockX();
int z1 = z + j * direction.getLadderVector().getBlockZ();
world.getBlockAt(x1, y, z1).setType(material);
}
}
} else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
for (int i = 0; i < chunkLength; i++) {
for (int j = 0; j < chunkWight; j++) {
int x1 = x + i * direction.getLadderVector().getBlockX();
int z1 = z + j * direction.getLadderVector().getBlockZ();
world.getBlockAt(x1, y, z1).setType(material);
}
}
}
}
private void transformDirection() {
nowDirection = nowDirection.getRightDirection();
}
private enum TransformType {
PLATFORM,
LADDER
}
public enum Direction {
NORTH(new Vector(1.0, 1.0, -1.0), new Vector(-1.0, 1.0, -1.0), new Vector(1.0, 1.0, -1.0)),
EAST(new Vector(1.0, 1.0, 1.0), new Vector(1.0, 1.0, -1.0), new Vector(1.0, 1.0, 1.0)),
SOUTH(new Vector(-1.0, 1.0, 1.0), new Vector(1.0, 1.0, 1.0), new Vector(-1.0, 1.0, 1.0)),
WEST(new Vector(-1.0, 1.0, -1.0), new Vector(-1.0, 1.0, 1.0), new Vector(-1.0, 1.0, -1.0));
private final Vector vector;
private final Vector platformVector;
private final Vector ladderVector;
Direction(Vector vector, Vector platformVector, Vector ladderVector) {
this.vector = vector;
this.platformVector = platformVector;
this.ladderVector = ladderVector;
}
public Vector getVector() {
return vector;
}
public Vector getPlatformVector() {
return platformVector;
}
public Vector getLadderVector() {
return ladderVector;
}
public Direction getRightDirection() {
switch (this) {
case NORTH:
return EAST;
case EAST:
return SOUTH;
case SOUTH:
return WEST;
case WEST:
return NORTH;
}
return null;
}
}
public Region getEffectiveRegion(World world) {
return spawnModeHander.getEffectiveRegion(world);
}
public int getHeight() {
return spawnModeHander.getHeight();
}
public enum SpawnMode {
MODE_1,
MODE_2;
}
private class SpawnModeHandler_1 implements ISpawnModeHander {
@Override
public void spawn() {
for (int i = 0; i < levelAmount; i++) {
spawnPlatform(nowX, nowY, nowZ, nowDirection);
transformXYZ(TransformType.PLATFORM, nowDirection);
transformDirection();
spawnLadder(nowX, nowY, nowZ, nowDirection);
transformXYZ(TransformType.LADDER, nowDirection);
transformDirection();
}
spawnPlatform(nowX, nowY, nowZ, nowDirection);
}
@Override
public Region getEffectiveRegion(World world) {
if (initialDirection == Direction.NORTH || initialDirection == Direction.SOUTH) {
int minX = originX + (platformWidth * chunkWight) * initialDirection.getPlatformVector().getBlockX();
int minY = originY;
int minZ = originZ;
int maxX = originX + ladderAmount * ladderLength * chunkLength * initialDirection.getLadderVector().getBlockX() + (platformWidth * chunkWight) * initialDirection.getPlatformVector().getBlockX() + 1;
int maxY = originY + levelAmount * 5 + 1;
int maxZ = originZ + (platformLength * chunkLength) * initialDirection.getPlatformVector().getBlockZ() + 1;
return new Region(world, new Point(minX, minY, minZ), new Point(maxX, maxY, maxZ));
} else if (initialDirection == Direction.EAST || initialDirection == Direction.WEST) {
int minX = originX;
int minY = originY;
int minZ = originZ + (platformWidth * chunkWight) * initialDirection.getPlatformVector().getBlockZ();
int maxX = originX + (platformLength * chunkLength) * initialDirection.getPlatformVector().getBlockX() + 1;
int maxY = originY + levelAmount * 5 + 1;
int maxZ = originZ + ladderAmount * ladderLength * chunkLength * initialDirection.getLadderVector().getBlockX() + (platformWidth * chunkWight) * initialDirection.getPlatformVector().getBlockZ() + 1;
return new Region(world, new Point(minX, minY, minZ), new Point(maxX, maxY, maxZ));
}
return null;
}
@Override
public int getHeight() {
return levelAmount * 5;
}
private void transformXYZ(TransformType transformType, Direction direction) {
if (transformType == TransformType.PLATFORM) {
if (direction == Direction.EAST || direction == Direction.WEST) {
nowX += (platformLength * chunkWight - 1) * direction.getPlatformVector().getX();
} else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
nowZ += (platformLength * chunkWight - 1) * direction.getPlatformVector().getZ();
}
switch (nowDirection) {
case EAST:
nowZ += 1;
break;
case SOUTH:
nowX -= 1;
break;
case WEST:
nowZ -= 1;
break;
case NORTH:
nowX += 1;
break;
}
} else if (transformType == TransformType.LADDER) {
nowY += ladderAmount;
if (direction == Direction.EAST || direction == Direction.WEST) {
nowX += (ladderAmount * chunkWight) * direction.getLadderVector().getBlockX();
} else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
nowZ += (ladderAmount * chunkWight) * direction.getLadderVector().getBlockZ();
}
}
}
}
private class SpawnModeHandler_2 implements ISpawnModeHander {
@Override
public void spawn() {
for (int i = 0; i < levelAmount; i++) {
spawnPlatform(nowX, nowY, nowZ, nowDirection);
transformXYZ(TransformType.PLATFORM, nowDirection, 0);
spawnLadder(nowX, nowY, nowZ, nowDirection);
transformXYZ(TransformType.LADDER, nowDirection, 0);
transformDirection();
}
spawnPlatform(nowX, nowY, nowZ, nowDirection);
}
@Override
public Region getEffectiveRegion(World world) {
if (initialDirection == Direction.NORTH || initialDirection == Direction.SOUTH) {
int minX = originX + (platformWidth * chunkWight) * initialDirection.getPlatformVector().getBlockX();
int minZ = originZ;
minZ += (platformLength * chunkLength) * initialDirection.getPlatformVector().getBlockZ();
minZ += (ladderAmount * chunkLength) * initialDirection.getLadderVector().getBlockZ();
minZ += (platformWidth * chunkWight) * initialDirection.getRightDirection().getPlatformVector().getBlockZ();
int maxX = originX + ladderAmount * ladderLength * chunkLength * initialDirection.getLadderVector().getBlockX() + (platformWidth * chunkWight) * initialDirection.getPlatformVector().getBlockX()+ 1;
int maxZ = originZ;
int maxY = originY + levelAmount * 5 + 1;
return new Region(world, new Point(minX, originY, minZ), new Point(maxX, maxY, maxZ));
} else if (initialDirection == Direction.EAST || initialDirection == Direction.WEST) {
int minX = originX;
int minZ = originZ + (platformWidth * chunkWight) * initialDirection.getPlatformVector().getBlockZ();
minX += (platformLength * chunkLength) * initialDirection.getPlatformVector().getBlockX();
minX += (ladderAmount * chunkLength) * initialDirection.getLadderVector().getBlockX();
minX += (platformWidth * chunkWight) * initialDirection.getRightDirection().getPlatformVector().getBlockX();
int maxX = originX;
int maxZ = originZ + ladderAmount * ladderLength * chunkLength * initialDirection.getLadderVector().getBlockZ() + (platformWidth * chunkWight) * initialDirection.getPlatformVector().getBlockZ()+ 1;
int maxY = originY + levelAmount * 5 + 1;
return new Region(world, new Point(minX, originY, minZ), new Point(maxX, maxY, maxZ));
}
return null;
}
@Override
public int getHeight() {
return levelAmount * 5;
}
private void transformXYZ(TransformType transformType, Direction direction, int type) {
if (transformType == TransformType.PLATFORM) {
if (type == 0) {
if (direction == Direction.EAST || direction == Direction.WEST) {
nowX += (platformLength * chunkWight) * direction.getPlatformVector().getX();
nowZ += (platformWidth * chunkLength - 1) * direction.getPlatformVector().getZ();
} else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
nowX += (platformWidth * chunkLength - 1) * direction.getPlatformVector().getX();
nowZ += (platformLength * chunkWight) * direction.getPlatformVector().getZ();
}
} else if (type == 1) {
if (direction == Direction.EAST || direction == Direction.WEST) {
nowX += (platformLength * chunkWight - 1) * direction.getPlatformVector().getX();
} else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
nowZ += (platformLength * chunkWight - 1) * direction.getPlatformVector().getZ();
}
switch (nowDirection) {
case EAST:
nowZ += 1;
break;
case SOUTH:
nowX -= 1;
break;
case WEST:
nowZ -= 1;
break;
case NORTH:
nowX += 1;
break;
}
}
} else if (transformType == TransformType.LADDER) {
nowY += ladderAmount;
if (direction == Direction.EAST || direction == Direction.WEST) {
nowX += (ladderAmount * chunkWight) * direction.getLadderVector().getBlockX();
} else if (direction == Direction.NORTH || direction == Direction.SOUTH) {
nowZ += (ladderAmount * chunkWight) * direction.getLadderVector().getBlockZ();
}
}
}
}
public void setInitialDirection(Direction initialDirection) {
this.initialDirection = initialDirection;
}
private interface ISpawnModeHander {
void spawn();
Region getEffectiveRegion(World world);
int getHeight();
}
public Material getRandomMaterial() {
return materials.get(RandomUtil.getRandomInt(0, materials.size() - 1));
}
}

View File

@ -0,0 +1,77 @@
package com.io.yutian.colorblindwar.util;
import org.bukkit.Material;
public class ColorUtil {
public static String getColorName(Material material) {
switch (material) {
case WHITE_WOOL:
return "白色";
case BLACK_WOOL:
return "黑色";
case BROWN_WOOL:
return "棕色";
case BLUE_WOOL:
return "蓝色";
case GREEN_WOOL:
return "绿色";
case RED_WOOL:
return "红色";
case YELLOW_WOOL:
return "黄色";
case PURPLE_WOOL:
return "紫色";
case ORANGE_WOOL:
return "橙色";
case PINK_WOOL:
return "粉色";
case LIGHT_BLUE_WOOL:
return "淡蓝色";
case LIME_WOOL:
return "黄绿色";
default:
return "未知";
}
}
public static String getColorHex(Material material) {
switch (material) {
case WHITE_WOOL:
return "#DDDDDD";
case ORANGE_WOOL:
return "#DB7D3E";
case MAGENTA_WOOL:
return "#B350BC";
case LIGHT_BLUE_WOOL:
return "#6B8AC9";
case YELLOW_WOOL:
return "#E0C240";
case LIME_WOOL:
return "#41AE38";
case PINK_WOOL:
return "#D08499";
case GRAY_WOOL:
return "#404040";
case LIGHT_GRAY_WOOL:
return "#9A9A9A";
case CYAN_WOOL:
return "#2E6E89";
case PURPLE_WOOL:
return "#7E3DB5";
case BLUE_WOOL:
return "#2E388D";
case BROWN_WOOL:
return "#4F321F";
case GREEN_WOOL:
return "#35461B";
case RED_WOOL:
return "#C05A5A";
case BLACK_WOOL:
return "#191616";
default:
return "#000000";
}
}
}

View File

@ -0,0 +1,29 @@
package com.io.yutian.colorblindwar.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class MathUtil {
public static double round(double d) {
return new BigDecimal(Double.toString(d)).setScale(2, RoundingMode.HALF_UP).doubleValue();
}
public static double round(double d, int scale) {
return new BigDecimal(Double.toString(d)).setScale(scale, RoundingMode.HALF_UP).doubleValue();
}
public static int clamp(int value, int min, int max) {
return Math.max(min, Math.min(max, value));
}
public static double clamp(double value, double min, double max) {
return Math.max(min, Math.min(max, value));
}
public static float clamp(float value, float min, float max) {
return Math.max(min, Math.min(max, value));
}
}

View File

@ -0,0 +1,45 @@
package com.io.yutian.colorblindwar.util;
import com.io.yutian.colorblindwar.game.Point;
import com.io.yutian.colorblindwar.game.Region;
import org.bukkit.Location;
import org.bukkit.World;
import java.util.Random;
public class RandomUtil {
public static Location getRandomLocation(Region region) {
Point min = region.getMin();
Point max = region.getMax();
return getRandomLocation(region.getWorld(), min.getX(), max.getX(), min.getY(), max.getY(), min.getZ(), max.getZ());
}
public static boolean random(double d) {
return d >= new Random().nextFloat();
}
public static int getRandomInt(int min, int max) {
if (min == max) {
return max;
}
Random r = new Random();
int i = min < max ? min : max;
int a = min < max ? max : min;
return r.nextInt(a - i + 1) + i;
}
public static double getRandomDouble(double min, double max, int scl) {
int pow = (int) Math.pow(10, scl);
return Math.floor((Math.random() * (max - min) + min) * pow) / pow;
}
public static Location getRandomLocation(World world, double minX, double maxX, double minY, double maxY, double minZ, double maxZ) {
double rx = getRandomDouble(minX, maxX, 3);
double ry = getRandomDouble(minY, maxY, 3);
double rz = getRandomDouble(minZ, maxZ, 3);
Location location = new Location(world, rx, ry, rz);
return location;
}
}

View File

@ -0,0 +1,2 @@
completeAmount: 10
countdownTime: 10

View File

@ -0,0 +1,9 @@
name: ColorblindWar
version: '${project.version}'
main: com.io.yutian.colorblindwar.ColorblindWar
api-version: '1.18'
depend:
- WorldEdit
commands:
colorblindwar:
aliases: [cw]