Skip to content

Commit

Permalink
Flight calculations optimizations (#224)
Browse files Browse the repository at this point in the history
  • Loading branch information
CommandrMoose authored Apr 21, 2024
1 parent 52d6b9c commit 5d5e3ba
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import whocraft.tardis_refined.TardisRefined;
import whocraft.tardis_refined.common.capability.TardisLevelOperator;
import whocraft.tardis_refined.common.entity.ControlEntity;
import whocraft.tardis_refined.common.tardis.TardisNavLocation;
import whocraft.tardis_refined.common.tardis.control.Control;
import whocraft.tardis_refined.common.tardis.manager.TardisPilotingManager;
import whocraft.tardis_refined.common.tardis.themes.ConsoleTheme;
Expand All @@ -21,9 +21,11 @@ protected CoordinateControl(CoordinateButton button, ResourceLocation id, String
super(id, langId);
this.button = button;
}

protected CoordinateControl(CoordinateButton button, ResourceLocation id) {
this(button, id, "control." + id.getNamespace() + ".cord_" + button.name().toLowerCase());
}

public CoordinateControl(CoordinateButton button, String modid) {
this(button, new ResourceLocation(modid, button.name().toLowerCase() + "_cord"));
}
Expand All @@ -38,21 +40,23 @@ public boolean onLeftClick(TardisLevelOperator operator, ConsoleTheme theme, Con
return this.changeCoord(operator, theme, controlEntity, player, false);
}

private boolean changeCoord(TardisLevelOperator operator, ConsoleTheme theme, ControlEntity controlEntity, Player player, boolean addValue){
if (!operator.getLevel().isClientSide()){
private boolean changeCoord(TardisLevelOperator operator, ConsoleTheme theme, ControlEntity controlEntity, Player player, boolean addValue) {
if (!operator.getLevel().isClientSide()) {
TardisPilotingManager pilotManager = operator.getPilotingManager();

int increment = pilotManager.getCordIncrement();
int incrementAmount = addValue ? increment : -increment;
BlockPos potentialPos = pilotManager.getTargetLocation().getPosition();
TardisNavLocation targetLocation = pilotManager.getTargetLocation();
BlockPos potentialPos = targetLocation.getPosition();

switch (button){
switch (button) {
case X -> potentialPos = potentialPos.offset(incrementAmount, 0, 0);
case Y -> potentialPos = potentialPos.offset(0, incrementAmount, 0);
case Z -> potentialPos = potentialPos.offset(0, 0, incrementAmount);
}

if (pilotManager.getTargetLocation().getLevel().isInWorldBounds(potentialPos)){ //Use vanilla check which accounts for both world height and horizontal bounds
//Use vanilla check which accounts for both world height and horizontal bounds
if (pilotManager.getTargetLocation().getLevel().isInWorldBounds(potentialPos)) {

pilotManager.setTargetPosition(potentialPos); //Only update target position if it is within both vertical and horizontal bounds.

Expand All @@ -62,12 +66,12 @@ private boolean changeCoord(TardisLevelOperator operator, ConsoleTheme theme, Co

PlayerUtil.sendMessage(player, Component.translatable(pilotManager.getTargetLocation().getPosition().toShortString()), true);
return true;
}
else {
} else {
return false;
}
}
return false;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import whocraft.tardis_refined.api.event.TardisEvents;
import whocraft.tardis_refined.common.block.console.GlobalConsoleBlock;
Expand All @@ -31,7 +32,10 @@
import whocraft.tardis_refined.constants.NbtConstants;
import whocraft.tardis_refined.registry.TRSoundRegistry;

import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

public class TardisPilotingManager extends BaseHandler {

Expand Down Expand Up @@ -211,7 +215,7 @@ private void onFlightTick(Level level) {
ticksInFlight++;

// Removing fuel once every 2.5 seconds
if (ticksInFlight % (5) == 0) {
if (ticksInFlight % (45) == 0) {
this.removeFuel(this.getFlightFuelCost() * throttleStage);
}

Expand Down Expand Up @@ -319,119 +323,99 @@ public TardisNavLocation findClosestValidPosition(TardisNavLocation location) {
var maxBuildHeight = level.getMaxBuildHeight();
var minHeight = level.getMinBuildHeight();

var failOffset = 1;
var attempts = 20;
return findValidLocationInColumn(location, level, minHeight, maxBuildHeight);
}

var originalY = location.getPosition().getY();
private TardisNavLocation findValidLocationInColumn(TardisNavLocation location, ServerLevel level, int minHeight, int maxBuildHeight) {

// Do any specific dimension checks
//TODO: Handle dimension checks in a dedicated function, we already have duplicated codfein #getLegalPosition
if (level.dimension() == Level.NETHER) {
if (location.getPosition().getY() > 127) {
maxBuildHeight = 125;
failOffset = 10;
location.setPosition(new BlockPos(location.getPosition().getX(), 80, location.getPosition().getZ())); //TODO: Remove this hardcoding to continue searching for a spot
}
}
ChunkPos chunkPos = level.getChunk(location.getPosition()).getPos();
//Force load chunk
level.setChunkForced(chunkPos.x, chunkPos.z, true); //Set chunk to be force loaded to properly remove block

boolean isTargetFine = !isSolidBlock(level, location.getPosition()) && !isSolidBlock(level, location.getPosition().above()) && isSolidBlock(level, location.getPosition().below());
if (isTargetFine) {
var safeDir = findSafeDirection(location);
if (safeDir != null) {
return safeDir;
}
}
// Fetch the row of blocks and filter them all out to air.
List<BlockPos> blockColumn = getBlockPosColumn(location.getPosition(), minHeight, maxBuildHeight);
List<BlockPos> filteredForAir = blockColumn.stream().filter(x -> isLegalLandingBlock(level, x)).toList();
List<BlockPos> filteredForNonAir = blockColumn.stream().filter(x -> !isLegalLandingBlock(level, x)).toList();

for (int i = 0; i < attempts; i++) {
List<TardisNavLocation> solutionsInRow = new ArrayList<>();
for (BlockPos airPos : filteredForAir) {

location.setPosition(getLegalPosition(location.getLevel(), location.getPosition(), originalY));
var result = scanUpwardsFromCord(location, maxBuildHeight);
if (result != null && location.getPosition().getY() < maxBuildHeight && location.getPosition().getY() > minHeight) {
return result;
// Ignore any higher scans above the roof.
if (level.dimension() == Level.NETHER && airPos.getY() > 125) {
continue;
}

location.setPosition(getLegalPosition(location.getLevel(), location.getPosition(), originalY));
result = scanDownwardsFromCord(location, minHeight);
if (result != null && location.getPosition().getY() < maxBuildHeight && location.getPosition().getY() > minHeight) {
return result;
}
BlockPos below = airPos.below();
BlockPos above = airPos.above();

// Try the next interval in the rotation.
location.setPosition(getLegalPosition(location.getLevel(), location.getPosition(), originalY));
location.setPosition(location.getPosition().offset(location.getDirection().getNormal().multiply((int) (failOffset * (1 + ((float) i * 0.1f))))));
}
// Does this position have the space for a TARDIS?
if (filteredForNonAir.contains(below) && filteredForAir.contains(above)) {

// Can we find a rotation for the TARDIS?

return location;
}
// Check front
Direction[] directions = new Direction[]{location.getDirection(), location.getDirection().getOpposite(), Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST};

public BlockPos getLegalPosition(Level level, BlockPos pos, int originalY) {
if (level.dimension() == Level.NETHER) {
for (Direction direction : directions) {
BlockPos directionOffset = BlockPos.of(BlockPos.offset(airPos.asLong(), direction));
// Check that the column in the direction is empty and doesn't have a drop.
if (isLegalLandingBlock(level, directionOffset)) {
if (isLegalLandingBlock(level, directionOffset.above()) && !isLegalLandingBlock(level, directionOffset.below()) && !isLegalLandingBlock(level, directionOffset.below(2))) {
solutionsInRow.add(new TardisNavLocation(airPos, direction, location.getLevel()));

}
}
}

if (pos.getY() > level.getMaxBuildHeight() || originalY > level.getMaxBuildHeight()) {
return new BlockPos(pos.getX(), 60, pos.getZ()); //TODO: Remove this hardcoding and run a search below max height
}
}

return new BlockPos(pos.getX(), originalY, pos.getZ());
}

/**
* Checks the tardis nav location for a variety of reasons that a given position would be unsafe to land at.
*
* @param location the coordinates to check against
* @return true if safe to land, otherwise false
*/
public boolean isSafeToLand(TardisNavLocation location) {
if (!isSolidBlock(location.getLevel(), location.getPosition()) && isSolidBlock(location.getLevel(), location.getPosition().below()) && !isSolidBlock(location.getLevel(), location.getPosition().above())) {
return !location.getLevel().getBlockState(location.getPosition().below()).getFluidState().is(FluidTags.LAVA) && !location.getLevel().getBlockState(location.getPosition().below()).getFluidState().is(FluidTags.WATER);
}
return false;
}
// We have all solutions. Let's find the closest.

public TardisNavLocation scanUpwardsFromCord(TardisNavLocation location, int maxHeight) {

int startingHeight = location.getPosition().getY();
for (int i = startingHeight; i < maxHeight; i++) {
if (isSafeToLand(location)) {
return findSafeDirection(location);
}
if (solutionsInRow.size() > 0) {

location.setPosition(location.getPosition().above(1));
}
TardisNavLocation closest = null;
int distance = Integer.MAX_VALUE;

return null;
}
for (TardisNavLocation potentialLocation : solutionsInRow) {
int distanceBetween = Math.abs(potentialLocation.getPosition().distManhattan(location.getPosition()));
if (distanceBetween < distance) {
distance = distanceBetween;
closest = potentialLocation;
}
}

public TardisNavLocation scanDownwardsFromCord(TardisNavLocation location, int minHeight) {
return closest;

int startingHeight = location.getPosition().getY();
for (int i = startingHeight; i >= minHeight; i--) {
if (isSafeToLand(location)) {
return findSafeDirection(location);
}
} else {

location.setPosition(location.getPosition().below(1));
BlockPos directionOffset = BlockPos.of(BlockPos.offset(location.getPosition().asLong(), location.getDirection()));
TardisNavLocation nextLocation = new TardisNavLocation(directionOffset, location.getDirection(), location.getLevel());
return findValidLocationInColumn(nextLocation, level, minHeight, maxBuildHeight);
}

return null;
}

public TardisNavLocation findSafeDirection(TardisNavLocation location) {
private List<BlockPos> getBlockPosColumn(BlockPos referencePoint, int bottomLevel, int topLevel) {

Direction[] directions = new Direction[]{location.getDirection(), location.getDirection().getOpposite(), Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST};
for (Direction dir : directions) {
BlockPos basePos = BlockPos.of(BlockPos.offset(location.getPosition().asLong(), dir));
if (!isSolidBlock(location.getLevel(), basePos) && !isSolidBlock(location.getLevel(), basePos.above())) {
return new TardisNavLocation(location.getPosition(), dir, location.getLevel());
}
List<BlockPos> positions = new ArrayList<>();

for (int i = bottomLevel; i <= topLevel; i++) {
positions.add(new BlockPos(referencePoint.getX(), i, referencePoint.getZ()));
}

return null;
return positions;
}

public boolean isSolidBlock(ServerLevel level, BlockPos pos) {
return level.getBlockState(pos).isSolid() || level.getBlockState(pos).liquid();

/**
* Check if the block at the target position is a valid block to land inside.
* **/
public boolean isLegalLandingBlock(ServerLevel level, BlockPos pos) {
BlockState state = level.getBlockState(pos);
// Can land in air or override any block that can be marked as "replaceable" such as snow, tall grass etc.
return state.isAir() || (state.canBeReplaced() && state.getFluidState().isEmpty());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
import net.minecraft.world.level.block.entity.BlockEntityType;
import whocraft.tardis_refined.TardisRefined;
import whocraft.tardis_refined.common.blockentity.console.GlobalConsoleBlockEntity;
import whocraft.tardis_refined.common.blockentity.device.ArtronPillarBlockEntity;
import whocraft.tardis_refined.common.blockentity.device.AstralManipulatorBlockEntity;
import whocraft.tardis_refined.common.blockentity.device.*;
import whocraft.tardis_refined.common.blockentity.door.RootShellDoorBlockEntity;
import whocraft.tardis_refined.common.blockentity.door.BulkHeadDoorBlockEntity;
import whocraft.tardis_refined.common.blockentity.door.GlobalDoorBlockEntity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ public class TRSoundRegistry {
public static final RegistrySupplier<SoundEvent> CORRIDOR_TELEPORTER = setUpSound("corridor_teleporter");
public static final RegistrySupplier<SoundEvent> CORRIDOR_TELEPORTER_SUCCESS = setUpSound("corridor_teleporter_success");



// Hums

public static final RegistrySupplier<SoundEvent> HUM_CORAL = setUpSound("hum_coral");
Expand All @@ -41,14 +39,6 @@ public class TRSoundRegistry {
public static final RegistrySupplier<SoundEvent> HUM_1996 = setUpSound("hum_1996");


// Hums

public static final RegistrySupplier<SoundEvent> HUM_CORAL = setUpSound("hum_coral");
public static final RegistrySupplier<SoundEvent> HUM_CAVE = setUpSound("hum_cave");
public static final RegistrySupplier<SoundEvent> HUM_TOYOTA = setUpSound("hum_toyota");
public static final RegistrySupplier<SoundEvent> HUM_CLASSIC = setUpSound("hum_classic");
public static final RegistrySupplier<SoundEvent> HUM_1996 = setUpSound("hum_1996");

// Screwdriver
public static final RegistrySupplier<SoundEvent> SCREWDRIVER_SHORT = setUpSound("screwdriver_short");
public static final RegistrySupplier<SoundEvent> SCREWDRIVER_CONNECT = setUpSound("screwdriver_connect");
Expand Down

0 comments on commit 5d5e3ba

Please sign in to comment.