use of net.countercraft.movecraft.WorldHandler 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.WorldHandler in project Movecraft by APDevTeam.
the class CraftTranslateCommand 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();
World oldWorld = craft.getWorld();
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()) {
// translate the craft
Movecraft.getInstance().getWorldHandler().translateCraft(craft, displacement, world);
craft.setWorld(world);
// trigger sign events
sendSignEvents();
} else {
SetHitBox originalLocations = new SetHitBox();
for (MovecraftLocation movecraftLocation : craft.getHitBox()) {
originalLocations.add(movecraftLocation.subtract(displacement));
}
final Set<MovecraftLocation> to = Sets.difference(craft.getHitBox().asSet(), originalLocations.asSet());
// place phased blocks
for (MovecraftLocation location : to) {
var data = location.toBukkit(world).getBlock().getBlockData();
if (passthroughBlocks.contains(data.getMaterial())) {
craft.getPhaseBlocks().put(location.toBukkit(world), data);
}
}
// The subtraction of the set of coordinates in the HitBox cube and the HitBox itself
final var invertedHitBox = Sets.difference(craft.getHitBox().boundingHitBox().asSet(), craft.getHitBox().asSet());
// place phased blocks
final Set<Location> overlap = new HashSet<>(craft.getPhaseBlocks().keySet());
overlap.removeIf((location -> !craft.getHitBox().contains(MathUtils.bukkit2MovecraftLoc(location))));
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)) };
final SetHitBox validExterior = new SetHitBox();
for (HitBox hitBox : surfaces) {
validExterior.addAll(Sets.difference(hitBox.asSet(), craft.getHitBox().asSet()));
}
// Check to see which locations in the from set are actually outside of the craft
final Set<MovecraftLocation> confirmed = craft instanceof SinkingCraft ? invertedHitBox.copyInto(new LinkedHashSet<>()) : verifyExterior(invertedHitBox, validExterior);
// A set of locations that are confirmed to be "exterior" locations
final Set<MovecraftLocation> failed = Sets.difference(invertedHitBox, confirmed).copyInto(new LinkedHashSet<>());
final WorldHandler handler = Movecraft.getInstance().getWorldHandler();
for (MovecraftLocation location : failed) {
var data = location.toBukkit(world).getBlock().getBlockData();
if (!passthroughBlocks.contains(data.getMaterial()))
continue;
craft.getPhaseBlocks().put(location.toBukkit(world), data);
}
// translate the craft
handler.translateCraft(craft, displacement, world);
craft.setWorld(world);
// trigger sign events
sendSignEvents();
for (MovecraftLocation l : failed) {
MovecraftLocation orig = l.subtract(displacement);
if (craft.getHitBox().contains(orig) || failed.contains(orig)) {
continue;
}
confirmed.add(orig);
}
// place confirmed blocks if they have been un-phased
for (MovecraftLocation location : confirmed) {
Location bukkit = location.toBukkit(craft.getWorld());
if (!craft.getPhaseBlocks().containsKey(bukkit))
continue;
// Do not place if it is at a collapsed HitBox location
if (!craft.getCollapsedHitBox().isEmpty() && craft.getCollapsedHitBox().contains(location))
continue;
var phaseBlock = craft.getPhaseBlocks().remove(bukkit);
handler.setBlockFast(bukkit, phaseBlock);
craft.getPhaseBlocks().remove(bukkit);
}
for (MovecraftLocation location : originalLocations) {
Location bukkit = location.toBukkit(oldWorld);
if (!craft.getHitBox().contains(location) && craft.getPhaseBlocks().containsKey(bukkit)) {
var phaseBlock = craft.getPhaseBlocks().remove(bukkit);
handler.setBlockFast(bukkit, phaseBlock);
}
}
for (MovecraftLocation location : failed) {
Location bukkit = location.toBukkit(oldWorld);
var data = bukkit.getBlock().getBlockData();
if (passthroughBlocks.contains(data.getMaterial())) {
craft.getPhaseBlocks().put(bukkit, data);
handler.setBlockFast(bukkit, Material.AIR.createBlockData());
}
}
// waterlog();
}
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()) + ". Displacement of: " + displacement);
// Only add cruise time if cruising
if (craft.getCruising() && displacement.getY() == 0 && (displacement.getX() == 0 || displacement.getZ() == 0))
craft.addCruiseTime(time / 1e9f);
}
Aggregations