use of net.countercraft.movecraft.craft.SinkingCraft in project Movecraft by APDevTeam.
the class ScuttleSign method scuttle.
private void scuttle(Craft craft, CommandSender commandSender) {
if (craft instanceof SinkingCraft) {
commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Scuttle - Craft Already Sinking"));
return;
}
if (!commandSender.hasPermission("movecraft." + craft.getType().getStringProperty(CraftType.NAME) + ".scuttle")) {
commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Insufficient Permissions"));
return;
}
CraftScuttleEvent e = new CraftScuttleEvent(craft, (Player) commandSender);
Bukkit.getServer().getPluginManager().callEvent(e);
if (e.isCancelled())
return;
craft.setCruising(false);
CraftManager.getInstance().sink(craft);
commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Scuttle - Scuttle Activated"));
}
use of net.countercraft.movecraft.craft.SinkingCraft in project Movecraft by APDevTeam.
the class CraftRotateCommand method doUpdate.
@Override
public void doUpdate() {
final Logger logger = Movecraft.getInstance().getLogger();
if (craft.getHitBox().isEmpty()) {
logger.warning("Attempted to move craft with empty HashHitBox!");
CraftManager.getInstance().release(craft, CraftReleaseEvent.Reason.EMPTY, false);
return;
}
long time = System.nanoTime();
final Set<Material> passthroughBlocks = new HashSet<>(craft.getType().getMaterialSetProperty(CraftType.PASSTHROUGH_BLOCKS));
if (craft instanceof SinkingCraft) {
passthroughBlocks.addAll(Tags.FLUID);
passthroughBlocks.addAll(Tag.LEAVES.getValues());
passthroughBlocks.addAll(Tags.SINKING_PASSTHROUGH);
}
if (!passthroughBlocks.isEmpty()) {
SetHitBox originalLocations = new SetHitBox();
final MovecraftRotation counterRotation = rotation == MovecraftRotation.CLOCKWISE ? MovecraftRotation.ANTICLOCKWISE : MovecraftRotation.CLOCKWISE;
for (MovecraftLocation movecraftLocation : craft.getHitBox()) {
originalLocations.add(MathUtils.rotateVec(counterRotation, movecraftLocation.subtract(originLocation)).add(originLocation));
}
final HitBox to = craft.getHitBox().difference(originalLocations);
for (MovecraftLocation location : to) {
var data = location.toBukkit(craft.getWorld()).getBlock().getBlockData();
if (passthroughBlocks.contains(data.getMaterial())) {
craft.getPhaseBlocks().put(location.toBukkit(craft.getWorld()), data);
}
}
// The subtraction of the set of coordinates in the HitBox cube and the HitBox itself
final HitBox invertedHitBox = new SetHitBox(craft.getHitBox().boundingHitBox()).difference(craft.getHitBox());
// A set of locations that are confirmed to be "exterior" locations
final SetHitBox exterior = new SetHitBox();
final SetHitBox interior = new SetHitBox();
// place phased blocks
final Set<Location> overlap = new HashSet<>(craft.getPhaseBlocks().keySet());
overlap.retainAll(craft.getHitBox().asSet().stream().map(l -> l.toBukkit(craft.getWorld())).collect(Collectors.toSet()));
final int minX = craft.getHitBox().getMinX();
final int maxX = craft.getHitBox().getMaxX();
final int minY = craft.getHitBox().getMinY();
final int maxY = overlap.isEmpty() ? craft.getHitBox().getMaxY() : Collections.max(overlap, Comparator.comparingInt(Location::getBlockY)).getBlockY();
final int minZ = craft.getHitBox().getMinZ();
final int maxZ = craft.getHitBox().getMaxZ();
final HitBox[] surfaces = { new SolidHitBox(new MovecraftLocation(minX, minY, minZ), new MovecraftLocation(minX, maxY, maxZ)), new SolidHitBox(new MovecraftLocation(minX, minY, minZ), new MovecraftLocation(maxX, maxY, minZ)), new SolidHitBox(new MovecraftLocation(maxX, minY, maxZ), new MovecraftLocation(minX, maxY, maxZ)), new SolidHitBox(new MovecraftLocation(maxX, minY, maxZ), new MovecraftLocation(maxX, maxY, minZ)), new SolidHitBox(new MovecraftLocation(minX, minY, minZ), new MovecraftLocation(maxX, minY, maxZ)) };
// Valid exterior starts as the 6 surface planes of the HitBox with the locations that lie in the HitBox removed
final SetHitBox validExterior = new SetHitBox();
for (HitBox hitBox : surfaces) {
validExterior.addAll(hitBox.difference(craft.getHitBox()));
}
// Check to see which locations in the from set are actually outside of the craft
for (MovecraftLocation location : validExterior) {
if (craft.getHitBox().contains(location) || exterior.contains(location)) {
continue;
}
// use a modified BFS for multiple origin elements
SetHitBox visited = new SetHitBox();
Queue<MovecraftLocation> queue = new LinkedList<>();
queue.add(location);
while (!queue.isEmpty()) {
MovecraftLocation node = queue.poll();
// If the node is already a valid member of the exterior of the HitBox, continued search is unitary.
for (MovecraftLocation neighbor : CollectionUtils.neighbors(invertedHitBox, node)) {
if (visited.contains(neighbor)) {
continue;
}
visited.add(neighbor);
queue.add(neighbor);
}
}
exterior.addAll(visited);
}
interior.addAll(invertedHitBox.difference(exterior));
final WorldHandler handler = Movecraft.getInstance().getWorldHandler();
for (MovecraftLocation location : invertedHitBox.difference(exterior)) {
var data = location.toBukkit(craft.getWorld()).getBlock().getBlockData();
if (!passthroughBlocks.contains(data.getMaterial())) {
continue;
}
craft.getPhaseBlocks().put(location.toBukkit(craft.getWorld()), data);
}
// translate the craft
handler.rotateCraft(craft, originLocation, rotation);
// trigger sign events
sendSignEvents();
// place confirmed blocks if they have been un-phased
for (MovecraftLocation location : exterior) {
Location bukkit = location.toBukkit(craft.getWorld());
if (!craft.getPhaseBlocks().containsKey(bukkit)) {
continue;
}
var phaseBlock = craft.getPhaseBlocks().remove(bukkit);
handler.setBlockFast(bukkit, phaseBlock);
craft.getPhaseBlocks().remove(bukkit);
}
for (MovecraftLocation location : originalLocations.boundingHitBox()) {
Location bukkit = location.toBukkit(craft.getWorld());
if (!craft.getHitBox().inBounds(location) && craft.getPhaseBlocks().containsKey(bukkit)) {
var phaseBlock = craft.getPhaseBlocks().remove(bukkit);
handler.setBlockFast(bukkit, phaseBlock);
}
}
for (MovecraftLocation location : interior) {
Location bukkit = location.toBukkit(craft.getWorld());
var data = bukkit.getBlock().getBlockData();
if (passthroughBlocks.contains(data.getMaterial())) {
craft.getPhaseBlocks().put(bukkit, data);
handler.setBlockFast(bukkit, Material.AIR.createBlockData());
}
}
} else {
// translate the craft
Movecraft.getInstance().getWorldHandler().rotateCraft(craft, originLocation, rotation);
// trigger sign events
sendSignEvents();
}
if (!craft.isNotProcessing())
craft.setProcessing(false);
time = System.nanoTime() - time;
if (Settings.Debug)
logger.info("Total time: " + (time / 1e6) + " milliseconds. Moving with cooldown of " + craft.getTickCooldown() + ". Speed of: " + String.format("%.2f", craft.getSpeed()));
}
use of net.countercraft.movecraft.craft.SinkingCraft in project Movecraft by APDevTeam.
the class AsyncTask method checkFuel.
protected boolean checkFuel() {
// check for fuel, burn some from a furnace if needed. Blocks of coal are supported, in addition to coal and charcoal
double fuelBurnRate = (double) craft.getType().getPerWorldProperty(CraftType.PER_WORLD_FUEL_BURN_RATE, craft.getWorld());
if (fuelBurnRate == 0.0 || craft instanceof SinkingCraft)
return true;
if (craft.getBurningFuel() >= fuelBurnRate) {
double burningFuel = craft.getBurningFuel();
// call event
final FuelBurnEvent event = new FuelBurnEvent(craft, burningFuel, fuelBurnRate);
Bukkit.getPluginManager().callEvent(event);
if (event.getBurningFuel() != burningFuel)
burningFuel = event.getBurningFuel();
if (event.getFuelBurnRate() != fuelBurnRate)
fuelBurnRate = event.getFuelBurnRate();
craft.setBurningFuel(burningFuel - fuelBurnRate);
return true;
}
Block fuelHolder = null;
var v = craft.getType().getObjectProperty(CraftType.FUEL_TYPES);
if (!(v instanceof Map<?, ?>))
throw new IllegalStateException("FUEL_TYPES must be of type Map");
var fuelTypes = (Map<?, ?>) v;
for (var e : fuelTypes.entrySet()) {
if (!(e.getKey() instanceof Material))
throw new IllegalStateException("Keys in FUEL_TYPES must be of type Material");
if (!(e.getValue() instanceof Double))
throw new IllegalStateException("Values in FUEL_TYPES must be of type Double");
}
for (MovecraftLocation bTest : craft.getHitBox()) {
Block b = craft.getWorld().getBlockAt(bTest.getX(), bTest.getY(), bTest.getZ());
if (Tags.FURNACES.contains(b.getType())) {
InventoryHolder inventoryHolder = (InventoryHolder) b.getState();
for (ItemStack stack : inventoryHolder.getInventory()) {
if (stack == null || !fuelTypes.containsKey(stack.getType()))
continue;
fuelHolder = b;
break;
}
}
}
if (fuelHolder == null) {
return false;
}
InventoryHolder inventoryHolder = (InventoryHolder) fuelHolder.getState();
for (ItemStack iStack : inventoryHolder.getInventory()) {
if (iStack == null)
continue;
if (!fuelTypes.containsKey(iStack.getType()))
continue;
double burningFuel = (double) fuelTypes.get(iStack.getType());
// call event
final FuelBurnEvent event = new FuelBurnEvent(craft, burningFuel, fuelBurnRate);
Bukkit.getPluginManager().callEvent(event);
if (event.getBurningFuel() != burningFuel)
burningFuel = event.getBurningFuel();
if (event.getFuelBurnRate() != fuelBurnRate)
fuelBurnRate = event.getFuelBurnRate();
if (burningFuel == 0.0) {
continue;
}
int amount = iStack.getAmount();
int minAmount = 1;
if (burningFuel < fuelBurnRate) {
minAmount = (int) fuelBurnRate;
}
if (Tags.BUCKETS.contains(iStack.getType())) {
// If buckets are accepted as fuel, replace with an empty bucket
iStack.setType(Material.BUCKET);
} else if (amount == minAmount) {
inventoryHolder.getInventory().remove(iStack);
} else if (amount < minAmount) {
inventoryHolder.getInventory().remove(iStack);
final ItemStack secStack = inventoryHolder.getInventory().getItem(inventoryHolder.getInventory().first(iStack.getType()));
secStack.setAmount(secStack.getAmount() - (minAmount - amount));
} else {
iStack.setAmount(amount - minAmount);
}
craft.setBurningFuel(craft.getBurningFuel() + burningFuel);
break;
}
return true;
}
use of net.countercraft.movecraft.craft.SinkingCraft in project Movecraft by APDevTeam.
the class RotationTask method execute.
@Override
protected void execute() {
if (oldHitBox.isEmpty())
return;
if (getCraft().getDisabled() && !(craft instanceof SinkingCraft)) {
failed = true;
failMessage = I18nSupport.getInternationalisedString("Translation - Failed Craft Is Disabled");
}
// check for fuel, burn some from a furnace if needed. Blocks of coal are supported, in addition to coal and charcoal
if (!checkFuel()) {
failMessage = I18nSupport.getInternationalisedString("Translation - Failed Craft out of fuel");
failed = true;
return;
}
// if a subcraft, find the parent craft. If not a subcraft, it is it's own parent
Set<Craft> craftsInWorld = CraftManager.getInstance().getCraftsInWorld(getCraft().getWorld());
Craft parentCraft = getCraft();
for (Craft craft : craftsInWorld) {
if (craft != getCraft() && !craft.getHitBox().intersection(oldHitBox).isEmpty()) {
parentCraft = craft;
break;
}
}
for (MovecraftLocation originalLocation : oldHitBox) {
MovecraftLocation newLocation = MathUtils.rotateVec(rotation, originalLocation.subtract(originPoint)).add(originPoint);
newHitBox.add(newLocation);
Material oldMaterial = originalLocation.toBukkit(w).getBlock().getType();
// prevent chests collision
if (Tags.CHESTS.contains(oldMaterial) && !checkChests(oldMaterial, newLocation)) {
failed = true;
failMessage = String.format(I18nSupport.getInternationalisedString("Rotation - Craft is obstructed") + " @ %d,%d,%d", newLocation.getX(), newLocation.getY(), newLocation.getZ());
break;
}
if (!withinWorldBorder(craft.getWorld(), newLocation)) {
failMessage = I18nSupport.getInternationalisedString("Rotation - Failed Craft cannot pass world border") + String.format(" @ %d,%d,%d", newLocation.getX(), newLocation.getY(), newLocation.getZ());
failed = true;
return;
}
Material newMaterial = newLocation.toBukkit(w).getBlock().getType();
if (newMaterial.isAir() || (newMaterial == Material.PISTON_HEAD) || craft.getType().getMaterialSetProperty(CraftType.PASSTHROUGH_BLOCKS).contains(newMaterial))
continue;
if (!oldHitBox.contains(newLocation)) {
failed = true;
failMessage = String.format(I18nSupport.getInternationalisedString("Rotation - Craft is obstructed") + " @ %d,%d,%d", newLocation.getX(), newLocation.getY(), newLocation.getZ());
break;
}
}
if (!oldFluidList.isEmpty()) {
for (MovecraftLocation fluidLoc : oldFluidList) {
newFluidList.add(MathUtils.rotateVec(rotation, fluidLoc.subtract(originPoint)).add(originPoint));
}
}
if (failed) {
if (this.isSubCraft && parentCraft != getCraft()) {
parentCraft.setProcessing(false);
}
return;
}
// call event
CraftRotateEvent event = new CraftRotateEvent(craft, rotation, originPoint, oldHitBox, newHitBox);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
failed = true;
failMessage = event.getFailMessage();
return;
}
if (parentCraft != craft) {
parentCraft.getFluidLocations().removeAll(oldFluidList);
parentCraft.getFluidLocations().addAll(newFluidList);
}
updates.add(new CraftRotateCommand(getCraft(), originPoint, rotation));
// rotate entities in the craft
Location tOP = new Location(getCraft().getWorld(), originPoint.getX(), originPoint.getY(), originPoint.getZ());
tOP.setX(tOP.getBlockX() + 0.5);
tOP.setZ(tOP.getBlockZ() + 0.5);
if (!(craft instanceof SinkingCraft && craft.getType().getBoolProperty(CraftType.ONLY_MOVE_PLAYERS)) && craft.getType().getBoolProperty(CraftType.MOVE_ENTITIES)) {
Location midpoint = new Location(craft.getWorld(), (oldHitBox.getMaxX() + oldHitBox.getMinX()) / 2.0, (oldHitBox.getMaxY() + oldHitBox.getMinY()) / 2.0, (oldHitBox.getMaxZ() + oldHitBox.getMinZ()) / 2.0);
for (Entity entity : craft.getWorld().getNearbyEntities(midpoint, oldHitBox.getXLength() / 2.0 + 1, oldHitBox.getYLength() / 2.0 + 2, oldHitBox.getZLength() / 2.0 + 1)) {
if (!craft.getType().getBoolProperty(CraftType.ONLY_MOVE_PLAYERS) || ((entity.getType() == EntityType.PLAYER || entity.getType() == EntityType.PRIMED_TNT) && !(craft instanceof SinkingCraft))) {
// Player is onboard this craft
Location adjustedPLoc = entity.getLocation().subtract(tOP);
double[] rotatedCoords = MathUtils.rotateVecNoRound(rotation, adjustedPLoc.getX(), adjustedPLoc.getZ());
float newYaw = rotation == MovecraftRotation.CLOCKWISE ? 90F : -90F;
EntityUpdateCommand eUp = new EntityUpdateCommand(entity, rotatedCoords[0] + tOP.getX() - entity.getLocation().getX(), 0, rotatedCoords[1] + tOP.getZ() - entity.getLocation().getZ(), newYaw, 0);
updates.add(eUp);
}
}
}
if (getCraft().getCruising()) {
if (rotation == MovecraftRotation.ANTICLOCKWISE) {
// ship faces west
switch(getCraft().getCruiseDirection()) {
case WEST:
getCraft().setCruiseDirection(CruiseDirection.SOUTH);
break;
// ship faces east
case EAST:
getCraft().setCruiseDirection(CruiseDirection.NORTH);
break;
// ship faces north
case SOUTH:
getCraft().setCruiseDirection(CruiseDirection.EAST);
break;
// ship faces south
case NORTH:
getCraft().setCruiseDirection(CruiseDirection.WEST);
break;
}
} else if (rotation == MovecraftRotation.CLOCKWISE) {
// ship faces west
switch(getCraft().getCruiseDirection()) {
case WEST:
getCraft().setCruiseDirection(CruiseDirection.NORTH);
break;
// ship faces east
case EAST:
getCraft().setCruiseDirection(CruiseDirection.SOUTH);
break;
// ship faces north
case SOUTH:
getCraft().setCruiseDirection(CruiseDirection.WEST);
break;
// ship faces south
case NORTH:
getCraft().setCruiseDirection(CruiseDirection.EAST);
break;
}
}
}
// if you rotated a subcraft, update the parent with the new blocks
if (this.isSubCraft) {
// also find the furthest extent from center and notify the player of the new direction
int farthestX = 0;
int farthestZ = 0;
for (MovecraftLocation loc : newHitBox) {
if (Math.abs(loc.getX() - originPoint.getX()) > Math.abs(farthestX))
farthestX = loc.getX() - originPoint.getX();
if (Math.abs(loc.getZ() - originPoint.getZ()) > Math.abs(farthestZ))
farthestZ = loc.getZ() - originPoint.getZ();
}
Component faceMessage = I18nSupport.getInternationalisedComponent("Rotation - Farthest Extent Facing").append(Component.text(" "));
if (Math.abs(farthestX) > Math.abs(farthestZ)) {
if (farthestX > 0) {
faceMessage = faceMessage.append(I18nSupport.getInternationalisedComponent("Contact/Subcraft Rotate - East"));
} else {
faceMessage = faceMessage.append(I18nSupport.getInternationalisedComponent("Contact/Subcraft Rotate - West"));
}
} else {
if (farthestZ > 0) {
faceMessage = faceMessage.append(I18nSupport.getInternationalisedComponent("Contact/Subcraft Rotate - South"));
} else {
faceMessage = faceMessage.append(I18nSupport.getInternationalisedComponent("Contact/Subcraft Rotate - North"));
}
}
getCraft().getAudience().sendMessage(faceMessage);
craftsInWorld = CraftManager.getInstance().getCraftsInWorld(getCraft().getWorld());
for (Craft craft : craftsInWorld) {
if (!newHitBox.intersection(craft.getHitBox()).isEmpty() && craft != getCraft()) {
// craft.setHitBox(newHitBox);
if (Settings.Debug) {
Bukkit.broadcastMessage(String.format("Size of %s hitbox: %d, Size of %s hitbox: %d", this.craft.getType().getStringProperty(CraftType.NAME), newHitBox.size(), craft.getType().getStringProperty(CraftType.NAME), craft.getHitBox().size()));
}
craft.setHitBox(craft.getHitBox().difference(oldHitBox).union(newHitBox));
if (Settings.Debug) {
Bukkit.broadcastMessage(String.format("Hitbox of craft %s intersects hitbox of craft %s", this.craft.getType().getStringProperty(CraftType.NAME), craft.getType().getStringProperty(CraftType.NAME)));
Bukkit.broadcastMessage(String.format("Size of %s hitbox: %d, Size of %s hitbox: %d", this.craft.getType().getStringProperty(CraftType.NAME), newHitBox.size(), craft.getType().getStringProperty(CraftType.NAME), craft.getHitBox().size()));
}
break;
}
}
}
}
use of net.countercraft.movecraft.craft.SinkingCraft in project Movecraft by APDevTeam.
the class CraftReportCommand method onCommand.
@Override
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
if (commandSender.getName().equalsIgnoreCase("craftreport"))
return false;
if (!commandSender.hasPermission("movecraft.commands") && !commandSender.hasPermission("movecraft.commands.craftreport")) {
commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Insufficient Permissions"));
return true;
}
int page;
try {
if (args.length == 0)
page = 1;
else
page = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Paginator - Invalid Page") + "\"" + args[0] + "\"");
return true;
}
if (CraftManager.getInstance().isEmpty()) {
commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Craft Report - None Found"));
return true;
}
TopicPaginator paginator = new TopicPaginator(I18nSupport.getInternationalisedString("Craft Report"));
for (Craft craft : CraftManager.getInstance()) {
HitBox hitBox = craft.getHitBox();
paginator.addLine((craft instanceof SinkingCraft ? ChatColor.RED : craft.getDisabled() ? ChatColor.BLUE : "") + craft.getType().getStringProperty(CraftType.NAME) + " " + ChatColor.RESET + (craft instanceof PilotedCraft ? ((PilotedCraft) craft).getPilot().getName() : I18nSupport.getInternationalisedString("None")) + " " + hitBox.size() + " @ " + hitBox.getMinX() + "," + hitBox.getMinY() + "," + hitBox.getMinZ() + " - " + String.format("%.2f", 1000 * craft.getMeanCruiseTime()) + "ms");
}
if (!paginator.isInBounds(page)) {
commandSender.sendMessage(MOVECRAFT_COMMAND_PREFIX + I18nSupport.getInternationalisedString("Paginator - Invalid page") + "\"" + page + "\"");
return true;
}
for (String line : paginator.getPage(page)) commandSender.sendMessage(line);
return true;
}
Aggregations