- moved flight logic to FlightExecutor.java

- implemented 4040 flying

The mod is almost finished now, but I still need to test it and maybe iron some bugs out.
master
Frieder Hannenheim 2020-10-07 20:41:43 +02:00
parent f1d9fe9c6e
commit 63d17ac1aa
8 changed files with 175 additions and 89 deletions

View File

@ -2,15 +2,12 @@ package fhannenheim.autopilot;
import fhannenheim.autopilot.chat.ChatCommandHandler;
import fhannenheim.autopilot.util.Config;
import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLPaths;
import org.apache.logging.log4j.LogManager;
@ -38,9 +35,10 @@ public class Autopilot {
}
private void doClientStuff(final FMLClientSetupEvent event) {
FlightHandler handler = new FlightHandler();
MinecraftForge.EVENT_BUS.register(handler);
handler.onClientSetup();
FlightHandler flightHandler = new FlightHandler();
MinecraftForge.EVENT_BUS.register(flightHandler);
flightHandler.onClientSetup();
KeybindHandler.onClientSetup();
}
}

View File

@ -3,64 +3,56 @@ package fhannenheim.autopilot;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.RootCommandNode;
import com.sun.javafx.geom.Vec2d;
import fhannenheim.autopilot.util.Config;
import fhannenheim.autopilot.flight.FlightExecutor;
import fhannenheim.autopilot.util.FlightType;
import fhannenheim.autopilot.util.InventoryUtils;
import fhannenheim.autopilot.util.OnArrive;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.DirtMessageScreen;
import net.minecraft.client.gui.screen.MainMenuScreen;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.command.ISuggestionProvider;
import net.minecraft.command.arguments.EntityAnchorArgument;
import net.minecraft.command.arguments.Vec2Argument;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.play.client.CEntityActionPacket;
import net.minecraft.network.play.client.CPlayerTryUseItemPacket;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import org.lwjgl.glfw.GLFW;
import java.text.DecimalFormat;
public class FlightHandler {
public static KeyBinding flyForward;
public static FlightHandler instance;
public FlightExecutor flightExecutor;
public boolean isAutoFlying;
public Vec3d destination;
public FlightType type;
private int ticksSinceRocket;
private boolean shallDisconnect;
public FlightType flightType;
public boolean shallDisconnect;
private double totalDistance;
public void onClientSetup() {
flyForward = new KeyBinding("keybind.autopilot.flyforward",
GLFW.GLFW_KEY_V, "category.autopilot");
ClientRegistry.registerKeyBinding(flyForward);
instance = this;
flightExecutor = new FlightExecutor(this);
}
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent event) {
PlayerEntity playerEntity = Minecraft.getInstance().player;
if (playerEntity != null && flyForward.isPressed()) {
boolean rockets = KeybindHandler.flyForwardROCKETS.isPressed();
boolean angle4040 = KeybindHandler.flyForward4040.isPressed();
if (playerEntity != null && (rockets || angle4040)) {
destination = null;
if (!isAutoFlying) {
playerEntity.rotationPitch = -3;
if (!isAutoFlying && !playerEntity.onGround) {
if (!playerEntity.isElytraFlying()) {
playerEntity.startFallFlying();
}
type = FlightType.ROCKETS;
if (rockets) flightType = FlightType.ROCKETS;
else flightType = FlightType.ANGLE4040;
isAutoFlying = true;
} else {
isAutoFlying = false;
@ -68,29 +60,22 @@ public class FlightHandler {
}
}
public void flyTo(Vec3d _destination, FlightType flightType) {
destination = _destination;
type = flightType;
public void flyTo(Vec3d pos, FlightType type) {
destination = pos;
this.flightType = type;
isAutoFlying = true;
if (Minecraft.getInstance().player != null) {
totalDistance = destination.distanceTo(Minecraft.getInstance().player.getPositionVec());
}
}
@SubscribeEvent
// this is for the commandDispatcher injection, I can't parameterize it and IDEA won't shut up about it.
@SuppressWarnings({"unchecked", "rawtypes"})
@SubscribeEvent
public void tick(TickEvent.ClientTickEvent event) {
if (event.side != LogicalSide.CLIENT || event.phase != TickEvent.Phase.END)
return;
ticksSinceRocket++;
PlayerEntity playerEntity = Minecraft.getInstance().player;
if (playerEntity == null || !playerEntity.isAlive()) {
isAutoFlying = false;
destination = null;
return;
}
if (Minecraft.getInstance().getConnection() != null) {
CommandDispatcher<CommandSource> dispatcher = new CommandDispatcher<CommandSource>((RootCommandNode) Minecraft.getInstance().getConnection().commandDispatcher.getRoot());
dispatcher.register(Commands.literal("flyto")
@ -101,7 +86,18 @@ public class FlightHandler {
);
Minecraft.getInstance().getConnection().commandDispatcher = new CommandDispatcher<ISuggestionProvider>((RootCommandNode) dispatcher.getRoot());
}
PlayerEntity playerEntity = Minecraft.getInstance().player;
if (playerEntity == null || !playerEntity.isAlive()) {
isAutoFlying = false;
destination = null;
return;
}
if (playerEntity.onGround) {
playerEntity.stopFallFlying();
isAutoFlying = false;
destination = null;
return;
}
if (isAutoFlying) {
if (!playerEntity.isElytraFlying() && !playerEntity.onGround) {
@ -112,37 +108,15 @@ public class FlightHandler {
playerEntity.startFallFlying();
Minecraft.getInstance().getConnection().sendPacket(new CEntityActionPacket(playerEntity, CEntityActionPacket.Action.START_FALL_FLYING));
}
if (destination != null) {
playerEntity.lookAt(EntityAnchorArgument.Type.EYES, destination);
}
playerEntity.rotationPitch = -3;
PlayerInventory inventory = playerEntity.inventory;
// Place new rockets in hand if needed
InventoryUtils.refillRockets(playerEntity);
if (destination == null || Vec2d.distance(destination.x, destination.z, playerEntity.getPosX(), playerEntity.getPosZ()) > 3) {
// If the player is lower than the flying altitude and is flying too slow, use a rocket to boost speed
if (Math.sqrt(Math.pow(Math.abs(playerEntity.getMotion().x), 2) + Math.pow(Math.abs(playerEntity.getMotion().z), 2)) < 1.5f
&& playerEntity.getPosition().getY() < Config.flight_level.get()
&& ticksSinceRocket > 3) {
Minecraft.getInstance().getConnection().sendPacket(new CPlayerTryUseItemPacket(Hand.MAIN_HAND));
ticksSinceRocket = 0;
}
} else if (destination != null) {
if (Config.on_arrive.get() == OnArrive.Disconnect) {
shallDisconnect = true;
playerEntity.rotationPitch = -90;
Minecraft.getInstance().getConnection().sendPacket(new CPlayerTryUseItemPacket(Hand.MAIN_HAND));
ticksSinceRocket = 0;
} else if (Config.on_arrive.get() == OnArrive.TryToLand) {
playerEntity.playSound(SoundEvents.BLOCK_BELL_USE, 4, 1);
}
}
if (flightType == FlightType.ROCKETS)
flightExecutor.rocketFlight(playerEntity);
if (flightType == FlightType.ANGLE4040)
flightExecutor.fourtyfourtyFlight(playerEntity);
}
}

View File

@ -0,0 +1,18 @@
package fhannenheim.autopilot;
import net.minecraft.client.settings.KeyBinding;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import org.lwjgl.glfw.GLFW;
public class KeybindHandler {
public static KeyBinding flyForwardROCKETS;
public static KeyBinding flyForward4040;
public static void onClientSetup() {
flyForwardROCKETS = new KeyBinding("keybind.autopilot.flyforwardrockets", GLFW.GLFW_KEY_V, "category.autopilot");
flyForward4040 = new KeyBinding("keybind.autopilot.flyforward4040", GLFW.GLFW_KEY_B, "category.autopilot");
ClientRegistry.registerKeyBinding(flyForwardROCKETS);
ClientRegistry.registerKeyBinding(flyForward4040);
}
}

View File

@ -1,30 +1,19 @@
package fhannenheim.autopilot.chat;
import com.mojang.brigadier.CommandDispatcher;
import fhannenheim.autopilot.Autopilot;
import fhannenheim.autopilot.FlightHandler;
import fhannenheim.autopilot.util.FlightType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.command.arguments.Vec3Argument;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.apache.http.auth.AUTH;
import org.lwjgl.glfw.GLFW;
public class ChatCommandHandler {
@SubscribeEvent
public void onChatInput(ClientChatEvent event){
String message = event.getMessage();
Autopilot.LOGGER.warn(message);
if(message.startsWith("/flyto "))
{
String[] commands = message.split(" ");
@ -33,7 +22,7 @@ public class ChatCommandHandler {
event.setCanceled(true);
return;
}
Vec3d pos = Vec3d.ZERO;
Vec3d pos;
FlightType flightType = FlightType.ROCKETS;
try {
pos = new Vec3d(Integer.parseInt(commands[1]),0,Integer.parseInt(commands[2]));

View File

@ -0,0 +1,109 @@
package fhannenheim.autopilot.flight;
import com.sun.javafx.geom.Vec2d;
import fhannenheim.autopilot.Autopilot;
import fhannenheim.autopilot.FlightHandler;
import fhannenheim.autopilot.util.Config;
import fhannenheim.autopilot.util.InventoryUtils;
import fhannenheim.autopilot.util.OnArrive;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.play.client.CPlayerTryUseItemPacket;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundEvents;
public class FlightExecutor {
public FlightHandler flightHandler;
public int ticksSinceRocket;
private FlightPhase flightPhase;
public FlightExecutor(FlightHandler flightHandler) {
this.flightHandler = flightHandler;
}
public void rocketFlight(PlayerEntity playerEntity) {
ticksSinceRocket++;
playerEntity.rotationPitch = -3;
// Place new rockets in hand if needed
InventoryUtils.refillRockets(playerEntity);
if (flightHandler.destination == null || Vec2d.distance(flightHandler.destination.x, flightHandler.destination.z, playerEntity.getPosX(), playerEntity.getPosZ()) > 3) {
// If the player is lower than the flying altitude and is flying too slow, use a rocket to boost speed
if (Math.sqrt(Math.pow(playerEntity.getMotion().x, 2) + Math.pow(playerEntity.getMotion().z, 2)) < 1.5f
&& playerEntity.getPosition().getY() < Config.flight_level.get()
&& ticksSinceRocket > 3) {
useRocket();
ticksSinceRocket = 0;
}
} else if (flightHandler.destination != null) {
if (Config.on_arrive.get() == OnArrive.Disconnect) {
flightHandler.shallDisconnect = true;
playerEntity.rotationPitch = -90;
useRocket();
ticksSinceRocket = 0;
} else if (Config.on_arrive.get() == OnArrive.TryToLand) {
playerEntity.playSound(SoundEvents.BLOCK_BELL_USE, 4, 1);
}
}
}
// values from https://www.reddit.com/r/Minecraft/comments/5ic9la/using_a_genetic_algorithm_to_power_infinite/
public void fourtyfourtyFlight(PlayerEntity playerEntity) {
// Place new rockets in hand if needed
InventoryUtils.refillRockets(playerEntity);
// apparently switch statements can't handle null-objects
flightPhase = flightPhase == null ? FlightPhase.DESCEND : flightPhase;
switch (flightPhase) {
case ASCEND:
playerEntity.rotationPitch = -49.44969f;
break;
case DESCEND:
playerEntity.rotationPitch = 37.7458839f;
break;
default:
flightPhase = FlightPhase.DESCEND;
break;
}
double velocity = getVelocity(playerEntity);
if (flightPhase == FlightPhase.DESCEND && velocity > 2.08719635f)
flightPhase = FlightPhase.ASCEND;
else if (flightPhase == FlightPhase.ASCEND && velocity < 0.224041611f)
flightPhase = FlightPhase.DESCEND;
if (
flightPhase == FlightPhase.ASCEND &&
playerEntity.getPosY() + 50 < Config.flight_level.get() &&
velocity < 0.75f
) {
useRocket();
ticksSinceRocket = 0;
}
}
private double getVelocity(PlayerEntity playerEntity) {
return Math.sqrt(
Math.pow(playerEntity.getMotion().x, 2) +
Math.pow(playerEntity.getMotion().y, 2) +
Math.pow(playerEntity.getMotion().z, 2)
);
}
@SuppressWarnings("ConstantConditions")
private void useRocket() {
try {
Minecraft.getInstance().getConnection().sendPacket(new CPlayerTryUseItemPacket(Hand.MAIN_HAND));
} catch (NullPointerException e) {
Autopilot.LOGGER.warn("Couldn't fire rocket");
}
}
private enum FlightPhase {
ASCEND,
DESCEND,
}
}

View File

@ -2,7 +2,6 @@ package fhannenheim.autopilot.util;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.electronwill.nightconfig.core.io.WritingMode;
import fhannenheim.autopilot.Autopilot;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.common.Mod;
@ -25,15 +24,16 @@ public class Config {
public static void init(ForgeConfigSpec.Builder config){
config.comment("Autopilot config");
flight_level = config
.comment("altitude the autopilot flies at. It will slowly rise to the specified y level and then stay there.")
.defineInRange("autopilot.flight_level",300,1,1000000);
.comment("Altitude the autopilot flies at. It will slowly rise to the specified y level and then stay there.\n" +
"The default is 400 so the Autopilot won't run into blocks")
.defineInRange("autopilot.flight_level", 400, 1, 1000000);
default_flight_type = config
.comment("the default flight type that will be used if you don't specify anything in the flyto command.")
.defineEnum("autopilot.default_flight_type",FlightType.ROCKETS);
.comment("The default flight type that will be used if you don't specify anything in the flyto command.")
.defineEnum("autopilot.default_flight_type", FlightType.ROCKETS);
on_arrive = config
.comment("What to do if the autopilot arrives at the destination." +
"\nIt can either disconnect, or try to land and then disconnect.")
.defineEnum("autopilot.on_arrive",OnArrive.Disconnect);
.defineEnum("autopilot.on_arrive", OnArrive.Disconnect);
}

View File

@ -1,7 +1,6 @@
package fhannenheim.autopilot.util;
import com.google.common.collect.ImmutableSet;
import fhannenheim.autopilot.Autopilot;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.PlayerController;
import net.minecraft.entity.player.PlayerEntity;
@ -36,7 +35,6 @@ public class InventoryUtils {
public static void replaceElytra(PlayerEntity player) {
PlayerInventory inventory = player.inventory;
ItemStack elytra = player.getItemStackFromSlot(EquipmentSlotType.CHEST);
Autopilot.LOGGER.info(inventory.getSlotFor(elytra));
if (elytra.getDamage() == elytra.getMaxDamage() - 1) {
if (inventory.hasAny(ImmutableSet.of(Items.ELYTRA))) {
int slot = -1;
@ -47,7 +45,6 @@ public class InventoryUtils {
}
}
if (slot != -1) {
Autopilot.LOGGER.info("le why?");
PlayerContainer container = player.container;
click(container, toServerSlotId(slot));
click(container, 6);

View File

@ -1,5 +1,6 @@
{
"keybind.autopilot.flyforward":"Start flying forward",
"category.autopilot":"Auto Elytra",
"keybind.autopilot.flyforwardrockets": "Fly Forward Using Rockets",
"keybind.autopilot.flyforward4040": "Fly Forward Using The 4040 Method",
"category.autopilot": "Auto Elytra",
"autopilot.disconnect": "You where disconnected because the autopilot arrived at the destination."
}