DungeonsXL/core/src/main/java/de/erethon/dungeonsxl/global/DPortal.java

409 lines
12 KiB
Java

/*
* Copyright (C) 2012-2022 Frank Baumann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.erethon.dungeonsxl.global;
import de.erethon.caliburn.item.ExItem;
import de.erethon.caliburn.item.VanillaItem;
import de.erethon.dungeonsxl.DungeonsXL;
import de.erethon.dungeonsxl.api.dungeon.Dungeon;
import de.erethon.dungeonsxl.api.dungeon.Game;
import de.erethon.dungeonsxl.api.player.PlayerGroup;
import de.erethon.dungeonsxl.api.world.GameWorld;
import de.erethon.dungeonsxl.config.DMessage;
import de.erethon.dungeonsxl.dungeon.DGame;
import de.erethon.dungeonsxl.player.DGamePlayer;
import de.erethon.dungeonsxl.player.DGlobalPlayer;
import de.erethon.bedrock.chat.MessageUtil;
import de.erethon.bedrock.misc.BlockUtil;
import java.util.HashSet;
import java.util.Set;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
/**
* A portal that leads into a dungeon.
*
* @author Frank Baumann, Daniel Saukel
*/
public class DPortal extends GlobalProtection {
private Block block1;
private Block block2;
private ExItem material = VanillaItem.NETHER_PORTAL;
private boolean zAxis;
private boolean active;
private Set<Block> blocks;
public DPortal(DungeonsXL plugin, int id, World world, ExItem material, boolean active) {
super(plugin, world, id);
this.material = material;
this.active = active;
}
public DPortal(DungeonsXL plugin, World world, int id, ConfigurationSection config) {
super(plugin, world, id);
block1 = world.getBlockAt(config.getInt("loc1.x"), config.getInt("loc1.y"), config.getInt("loc1.z"));
block2 = world.getBlockAt(config.getInt("loc2.x"), config.getInt("loc2.y"), config.getInt("loc2.z"));
material = plugin.getCaliburn().getExItem(config.getString("material"));
if (material == null) {
material = VanillaItem.NETHER_PORTAL;
}
String axis = config.getString("axis");
zAxis = axis != null && axis.equalsIgnoreCase("z");
active = true;
create(null);
}
/**
* @return the block1
*/
public Block getBlock1() {
return block1;
}
/**
* @param block1 the block1 to set
*/
public void setBlock1(Block block1) {
this.block1 = block1;
}
/**
* @return the block2
*/
public Block getBlock2() {
return block2;
}
/**
* @param block2 the block2 to set
*/
public void setBlock2(Block block2) {
this.block2 = block2;
}
/**
* @return if the portal is active
*/
public boolean isActive() {
return active;
}
/**
* @param active set the DPortal active
*/
public void setActive(boolean active) {
this.active = active;
}
/**
* Create a new DPortal
*
* @param player the creator
*/
public void create(DGlobalPlayer player) {
if (block1 == null || block2 == null) {
delete();
return;
}
if (player != null && material == VanillaItem.NETHER_PORTAL) {
float yaw = player.getPlayer().getLocation().getYaw();
if (yaw >= 45 & yaw < 135 || yaw >= 225 & yaw < 315) {
zAxis = true;
} else if (yaw >= 315 | yaw < 45 || yaw >= 135 & yaw < 225) {
zAxis = false;
}
}
int x1 = block1.getX(), y1 = block1.getY(), z1 = block1.getZ();
int x2 = block2.getX(), y2 = block2.getY(), z2 = block2.getZ();
int xcount = 0, ycount = 0, zcount = 0;
if (x1 > x2) {
xcount = -1;
} else if (x1 < x2) {
xcount = 1;
}
if (y1 > y2) {
ycount = -1;
} else if (y1 < y2) {
ycount = 1;
}
if (z1 > z2) {
zcount = -1;
} else if (z1 < z2) {
zcount = 1;
}
int xx = x1;
do {
int yy = y1;
do {
int zz = z1;
do {
Material type = getWorld().getBlockAt(xx, yy, zz).getType();
if (!type.isSolid()) {
Block block = getWorld().getBlockAt(xx, yy, zz);
block.setType(material.getMaterial(), false);
if (material == VanillaItem.NETHER_PORTAL) {
DungeonsXL.BLOCK_ADAPTER.setAxis(block, zAxis);
}
}
zz = zz + zcount;
} while (zz != z2 + zcount);
yy = yy + ycount;
} while (yy != y2 + ycount);
xx = xx + xcount;
} while (xx != x2 + xcount);
if (player == null) {
return;
}
player.getPlayer().getInventory().setItemInHand(player.getCachedItem());
player.setCachedItem(null);
if (material != VanillaItem.NETHER_PORTAL) {
player.sendMessage(DMessage.PLAYER_PORTAL_CREATED.getMessage());
player.setCreatingPortal(null);
} else {
ClickEvent onClickYes = new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/dungeonsxl portal " + VanillaItem.NETHER_PORTAL.getId() + " -rotate");
TextComponent yes = new TextComponent(DMessage.BUTTON_ACCEPT.getMessage());
yes.setClickEvent(onClickYes);
ClickEvent onClickNo = new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/dungeonsxl portal " + VanillaItem.NETHER_PORTAL.getId() + " -norotate");
TextComponent no = new TextComponent(DMessage.BUTTON_DENY.getMessage());
no.setClickEvent(onClickNo);
player.sendMessage(DMessage.PLAYER_PORTAL_ROTATE.getMessage());
player.getPlayer().spigot().sendMessage(yes, new TextComponent(" "), no);
}
}
public void rotate() {
zAxis = !zAxis;
for (Block block : getBlocks()) {
if (block.getType() == VanillaItem.NETHER_PORTAL.getMaterial()) {
DungeonsXL.BLOCK_ADAPTER.setAxis(block, zAxis);
}
}
}
/**
* @param player the player to teleport into his dungeon
*/
public void teleport(Player player) {
if (plugin.isLoadingWorld()) {
return;
}
PlayerGroup group = plugin.getPlayerGroup(player);
if (group == null) {
MessageUtil.sendActionBarMessage(player, DMessage.ERROR_JOIN_GROUP.getMessage());
return;
}
Dungeon dungeon = group.getDungeon();
if (dungeon == null) {
MessageUtil.sendActionBarMessage(player, DMessage.ERROR_NO_SUCH_DUNGEON.getMessage());
return;
}
if (!plugin.getPlayerCache().get(player).checkRequirements(dungeon)) {
return;
}
Game game = group.getGame();
if (game == null) {
game = new DGame(plugin, dungeon, group);
}
GameWorld target = game.ensureWorldIsLoaded(false);
if (target == null) {
MessageUtil.sendActionBarMessage(player, DMessage.ERROR_TOO_MANY_INSTANCES.getMessage());
return;
}
new DGamePlayer(plugin, player, target);
}
@Override
public Set<Block> getBlocks() {
if (blocks == null) {
if (block1 != null && block2 != null) {
blocks = BlockUtil.getBlocksBetween(block1, block2);
} else {
blocks = new HashSet<>();
}
}
return blocks;
}
@Override
public String getDataPath() {
return "protections.portals";
}
@Override
public void save(ConfigurationSection config) {
if (!active) {
return;
}
config.set("loc1.x", block1.getX());
config.set("loc1.y", block1.getY());
config.set("loc1.z", block1.getZ());
config.set("loc2.x", block2.getX());
config.set("loc2.y", block2.getY());
config.set("loc2.z", block2.getZ());
config.set("material", material.getId());
if (material == VanillaItem.NETHER_PORTAL) {
config.set("axis", zAxis ? "z" : "x");
}
}
@Override
public void delete() {
plugin.getGlobalProtectionCache().removeProtection(this);
if (block1 == null || block2 == null) {
return;
}
int x1 = block1.getX(), y1 = block1.getY(), z1 = block1.getZ();
int x2 = block2.getX(), y2 = block2.getY(), z2 = block2.getZ();
int xcount = 0, ycount = 0, zcount = 0;
if (x1 > x2) {
xcount = -1;
} else if (x1 < x2) {
xcount = 1;
}
if (y1 > y2) {
ycount = -1;
} else if (y1 < y2) {
ycount = 1;
}
if (z1 > z2) {
zcount = -1;
} else if (z1 < z2) {
zcount = 1;
}
int xx = x1;
do {
int yy = y1;
do {
int zz = z1;
do {
Material type = getWorld().getBlockAt(xx, yy, zz).getType();
if (material.getMaterial() == type) {
getWorld().getBlockAt(xx, yy, zz).setType(Material.AIR);
}
zz = zz + zcount;
} while (zz != z2 + zcount);
yy = yy + ycount;
} while (yy != y2 + ycount);
xx = xx + xcount;
} while (xx != x2 + xcount);
}
/* Statics */
/**
* @param plugin the plugin instance
* @param location a location covered by the returned portal
* @return the portal at the location, null if there is none
*/
public static DPortal getByLocation(DungeonsXL plugin, Location location) {
return getByBlock(plugin, location.getBlock());
}
/**
* @param plugin the plugin instance
* @param block a block covered by the returned portal
* @return the portal that the block belongs to, null if it belongs to none
*/
public static DPortal getByBlock(DungeonsXL plugin, Block block) {
if (plugin.isInstance(block.getWorld())) {
return null;
}
for (GlobalProtection protection : plugin.getGlobalProtectionCache().getProtections(DPortal.class)) {
DPortal portal = (DPortal) protection;
if (!portal.getWorld().equals(block.getWorld()) || portal.getBlock1() == null || portal.getBlock2() == null) {
continue;
}
int x1 = portal.block1.getX(), y1 = portal.block1.getY(), z1 = portal.block1.getZ();
int x2 = portal.block2.getX(), y2 = portal.block2.getY(), z2 = portal.block2.getZ();
int x3 = block.getX(), y3 = block.getY(), z3 = block.getZ();
if (x1 > x2) {
if (x3 < x2 || x3 > x1) {
continue;
}
} else if (x3 > x2 || x3 < x1) {
continue;
}
if (y1 > y2) {
if (y3 < y2 || y3 > y1) {
continue;
}
} else if (y3 > y2 || y3 < y1) {
continue;
}
if (z1 > z2) {
if (z3 < z2 || z3 > z1) {
continue;
}
} else if (z3 > z2 || z3 < z1) {
continue;
}
return portal;
}
return null;
}
}