add hover flying and creative fly
Some checks are pending
build / build (push) Waiting to run

This commit is contained in:
Soph :3 2025-10-07 13:04:51 +03:00
parent cc89a22c53
commit f3d9ec1ef6
8 changed files with 240 additions and 75 deletions

View file

@ -1,27 +1,134 @@
package konhaiii.powered_jetpacks;
import konhaiii.powered_jetpacks.hud.JetpackHUD;
import konhaiii.powered_jetpacks.item.special.JetpackItem;
import konhaiii.powered_jetpacks.models.JetpackModel;
import konhaiii.powered_jetpacks.renderers.JetpackRenderer;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRendererRegistrationCallback;
import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry;
import net.fabricmc.fabric.api.client.rendering.v1.hud.VanillaHudElements;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.InputUtil;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.tag.EntityTypeTags;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Unique;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class PoweredJetpacksClient implements ClientModInitializer {
public static KeyBinding hoverKeybinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.powered_jetpack.hover",
InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_H,
"category.powered_jetpack"
));
public static KeyBinding creativeKeybinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.powered_jetpack.creative",
InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_J,
"category.powered_jetpack"
));
public static boolean toggledHover = false;
public static boolean toggledCreative = false;
public static ItemStack getJetpack(ClientPlayerEntity player) {
ItemStack chestStack = player.getEquippedStack(EquipmentSlot.CHEST);
ItemStack backStack = ItemStack.EMPTY;
if (PoweredJetpacks.isTrinketsLoaded) {
try {
Class<?> optionalClass = Class.forName("konhaiii.powered_jetpacks.compat.TrinketsServer");
Method getBackStackMethod = optionalClass.getMethod("getBackStack", LivingEntity.class);
backStack = (ItemStack) getBackStackMethod.invoke(null, player);
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
IllegalAccessException e) {
PoweredJetpacks.LOGGER.error("ClientPlayerEntityMixin: Could not load Trinkets compat class.");
}
}
ItemStack jetpackStack = ItemStack.EMPTY;
if (isValidJetpack(chestStack)) {
jetpackStack = chestStack;
} else if (isValidJetpack(backStack)) {
jetpackStack = backStack;
}
return jetpackStack;
}
@Unique
private static boolean isValidJetpack(ItemStack stack) {
if (stack.getItem() instanceof JetpackItem jetpack) {
if (jetpack.getEnergyCost() <= 0) {
return true;
}
return jetpack.getStoredEnergy(stack) > 0;
}
return false;
}
@Override
public void onInitializeClient() {
ItemTooltipCallback.EVENT.register(new StackToolTipHandler());
ClientTickEvents.END_CLIENT_TICK.register(client -> {
while (creativeKeybinding.wasPressed()) {
if (client.player != null) {
ItemStack stack = getJetpack(client.player);
if (!stack.isEmpty() && ((JetpackItem)stack.getItem()).allowCreative) {
if (toggledHover) {
toggledHover = false;
client.player.setNoGravity(toggledHover);
}
toggledCreative = !toggledCreative;
if (!toggledCreative) {
client.player.getAbilities().allowFlying = false;
client.player.getAbilities().flying = false;
} else {
client.player.getAbilities().allowFlying = true;
client.player.getAbilities().flying = true;
client.player.sendAbilitiesUpdate();
}
}
}
}
});
ClientTickEvents.END_CLIENT_TICK.register(client -> {
while (hoverKeybinding.wasPressed()) {
if (client.player != null) {
ItemStack stack = getJetpack(client.player);
if (!stack.isEmpty() && ((JetpackItem)stack.getItem()).allowHover) {
if (toggledCreative) {
toggledCreative = false;
client.player.getAbilities().allowFlying = false;
client.player.getAbilities().flying = false;
}
toggledHover = !toggledHover;
client.player.setNoGravity(toggledHover);
}
}
}
});
LivingEntityFeatureRendererRegistrationCallback.EVENT.register(
(entityType, entityRenderer, registrationHelper, context) -> {
if (entityRenderer != null && entityType == EntityType.PLAYER) {

View file

@ -1,6 +1,7 @@
package konhaiii.powered_jetpacks.hud;
import konhaiii.powered_jetpacks.PoweredJetpacks;
import konhaiii.powered_jetpacks.PoweredJetpacksClient;
import konhaiii.powered_jetpacks.item.special.JetpackItem;
import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElement;
import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry;
@ -59,8 +60,22 @@ public class JetpackHUD implements HudElement {
TextRenderer textRenderer = client.textRenderer;
int percentage = percentage(energy, maxEnergy);
String energyText = translate("hud.powered_jetpacks.jetpack_power").concat(String.valueOf(percentage)).concat("%");
drawContext.drawTextWithShadow(textRenderer, energyText, 10, 10, 0xFFFFFFFF);
String hoverStatus = PoweredJetpacksClient.toggledHover ? "ON" : "OFF";
String creativeStatus = PoweredJetpacksClient.toggledCreative ? "ON" : "OFF";
if(!jetpack.allowCreative) {
creativeStatus = "DISABLED";
}
if(!jetpack.allowHover) {
hoverStatus = "DISABLED";
}
if(jetpack.allowHover || jetpack.allowCreative) {
String statusText = translate("hud.powered_jetpacks.status", hoverStatus, creativeStatus);
drawContext.drawTextWithShadow(textRenderer, statusText, 10, 20, 0xFFFFFFFF);
}
}
}
}

View file

@ -1,15 +1,11 @@
package konhaiii.powered_jetpacks.mixin.client;
import konhaiii.powered_jetpacks.PoweredJetpacks;
import konhaiii.powered_jetpacks.PoweredJetpacksClient;
import konhaiii.powered_jetpacks.item.special.JetpackItem;
import konhaiii.powered_jetpacks.packet.JetpackPacket;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@ -17,75 +13,103 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@Mixin(ClientPlayerEntity.class)
public abstract class ClientPlayerEntityMixin {
@Unique
private int soundCounter = 8;
@Unique
private int soundCounter = 8;
@Inject(method = "tick", at = @At("HEAD"))
private void onTick(CallbackInfo ci) {
ClientPlayerEntity player = (ClientPlayerEntity) (Object) this;
if (player.input.playerInput.jump()) {
ItemStack chestStack = player.getEquippedStack(EquipmentSlot.CHEST);
ItemStack backStack = ItemStack.EMPTY;
@Inject(method = "tick", at = @At("HEAD"))
private void onTick(CallbackInfo ci) {
ClientPlayerEntity player = (ClientPlayerEntity) (Object) this;
if (PoweredJetpacks.isTrinketsLoaded) {
try {
Class<?> optionalClass = Class.forName("konhaiii.powered_jetpacks.compat.TrinketsServer");
Method getBackStackMethod = optionalClass.getMethod("getBackStack", LivingEntity.class);
backStack = (ItemStack) getBackStackMethod.invoke(null, player);
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
IllegalAccessException e) {
PoweredJetpacks.LOGGER.error("ClientPlayerEntityMixin: Could not load Trinkets compat class.");
}
}
ItemStack jetpackStack = PoweredJetpacksClient.getJetpack(player);
ItemStack jetpackStack = null;
if (isValidJetpack(chestStack)) {
jetpackStack = chestStack;
} else if (isValidJetpack(backStack)) {
jetpackStack = backStack;
}
if (!jetpackStack.isEmpty()) {
JetpackPacket packet;
if (jetpackStack != null) {
JetpackPacket packet;
JetpackItem jetpack = (JetpackItem) jetpackStack.getItem();
if (PoweredJetpacksClient.toggledCreative && !jetpack.allowCreative) {
PoweredJetpacksClient.toggledCreative = false;
player.getAbilities().allowFlying = false;
player.getAbilities().flying = false;
}
JetpackItem jetpack = (JetpackItem) jetpackStack.getItem();
Vec3d velocity = player.getVelocity();
float horizontalBoost = jetpack.getFlightSpeed();
player.setVelocity(
velocity.x + (player.getRotationVector().x * horizontalBoost),
jetpack.addToVerticalVelocity(player.getVelocity().y),
velocity.z + (player.getRotationVector().z * horizontalBoost)
);
player.fallDistance = 0;
if (PoweredJetpacksClient.toggledHover && !jetpack.allowHover) {
PoweredJetpacksClient.toggledHover = false;
player.setNoGravity(false);
}
soundCounter++;
if (soundCounter >= 8) {
packet = new JetpackPacket(true);
soundCounter = 0;
} else {
packet = new JetpackPacket(false);
}
ClientPlayNetworking.send(packet);
} else if (soundCounter != 8) {
soundCounter = 8;
}
} else if (soundCounter != 8) {
soundCounter = 8;
}
}
@Unique
private boolean isValidJetpack(ItemStack stack) {
if (stack.getItem() instanceof JetpackItem jetpack) {
if (jetpack.getEnergyCost() <= 0) {
return true;
}
return jetpack.getStoredEnergy(stack) > 0;
}
return false;
}
Vec3d velocity = player.getVelocity();
boolean sendPacket = PoweredJetpacksClient.toggledCreative && !player.isOnGround();
if (PoweredJetpacksClient.toggledHover && jetpack.allowHover && !player.isOnGround()) {
double vertical = 0.0;
double hoverUpSpeed = 0.5;
double hoverDownSpeed = 0.4;
double horizontalSpeed = 0.35;
double inertia = 0.25;
if (player.input.playerInput.jump()) {
vertical += hoverUpSpeed;
} else if (player.input.playerInput.sneak()) {
vertical -= hoverDownSpeed;
} else {
vertical = 0.0;
}
Vec3d lookDir = player.getRotationVector().normalize();
Vec3d strafeDir = new Vec3d(-lookDir.z, 0, lookDir.x).normalize();
Vec3d move = Vec3d.ZERO;
if (player.input.playerInput.forward()) move = move.add(lookDir);
if (player.input.playerInput.backward()) move = move.subtract(lookDir);
if (player.input.playerInput.right()) move = move.add(strafeDir);
if (player.input.playerInput.left()) move = move.subtract(strafeDir);
if (move.lengthSquared() > 0) {
move = move.normalize().multiply(horizontalSpeed);
}
Vec3d targetVel = new Vec3d(move.x, vertical, move.z);
Vec3d currentVel = player.getVelocity();
Vec3d blended = currentVel.multiply(inertia).add(targetVel.multiply(1 - inertia));
player.setVelocity(blended);
sendPacket = true;
} else if (player.input.playerInput.jump()) {
float horizontalBoost = jetpack.getFlightSpeed();
player.setVelocity(velocity.x + (player.getRotationVector().x * horizontalBoost), jetpack.addToVerticalVelocity(player.getVelocity().y), velocity.z + (player.getRotationVector().z * horizontalBoost));
sendPacket = true;
}
player.fallDistance = 0;
if (sendPacket) {
soundCounter++;
if (soundCounter >= 8) {
packet = new JetpackPacket(true);
soundCounter = 0;
} else {
packet = new JetpackPacket(false);
}
ClientPlayNetworking.send(packet);
}
} else {
if (PoweredJetpacksClient.toggledCreative) {
PoweredJetpacksClient.toggledCreative = false;
player.getAbilities().allowFlying = false;
player.getAbilities().flying = false;
}
if (PoweredJetpacksClient.toggledHover) {
PoweredJetpacksClient.toggledHover = false;
player.setNoGravity(false);
}
}
if (soundCounter != 8) {
soundCounter = 8;
}
}
}