Updated wand to make behavior more consistent.
This commit is contained in:
@@ -2,17 +2,26 @@ package me.trouper.alias.server.systems;
|
|||||||
|
|
||||||
import me.trouper.alias.server.Main;
|
import me.trouper.alias.server.Main;
|
||||||
import me.trouper.alias.server.events.QuickListener;
|
import me.trouper.alias.server.events.QuickListener;
|
||||||
|
import me.trouper.alias.utils.misc.Cooldown;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
import org.bukkit.event.player.*;
|
import org.bukkit.event.player.*;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class AbstractWand implements QuickListener, Main {
|
public abstract class AbstractWand implements QuickListener, Main {
|
||||||
|
|
||||||
private final String usePermission;
|
private final String usePermission;
|
||||||
private final ItemStack wandItem;
|
private final ItemStack wandItem;
|
||||||
|
private final Cooldown<UUID> debounce = new Cooldown<>();
|
||||||
|
|
||||||
public AbstractWand(String usePermission, ItemStack wandItem) {
|
public AbstractWand(String usePermission, ItemStack wandItem) {
|
||||||
this.wandItem = wandItem.clone();
|
this.wandItem = wandItem.clone();
|
||||||
@@ -37,43 +46,96 @@ public abstract class AbstractWand implements QuickListener, Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onSwapHands(PlayerSwapHandItemsEvent e) {
|
public final void onSwapHands(PlayerSwapHandItemsEvent e) {
|
||||||
Player p = e.getPlayer();
|
Player p = e.getPlayer();
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
|
|
||||||
if (p.isSneaking()) onSwapHandSneak(p);
|
swapHand(p);
|
||||||
else onSwapHand(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
public void onAnimate(PlayerAnimationEvent e) {
|
public final void onInteract(PlayerInteractEvent e) {
|
||||||
Player p = e.getPlayer();
|
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
|
||||||
if (!e.getAnimationType().equals(PlayerAnimationType.ARM_SWING)) return;
|
|
||||||
if (e.getPlayer().getTargetEntity(5) == null) return;
|
|
||||||
e.setCancelled(true);
|
|
||||||
|
|
||||||
if (p.isSneaking()) onLeftClickSneak(p);
|
|
||||||
else onLeftClick(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onInteract(PlayerInteractEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
Player p = e.getPlayer();
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
||||||
|
|
||||||
Action action = e.getAction();
|
Action action = e.getAction();
|
||||||
|
|
||||||
if (action != Action.RIGHT_CLICK_AIR && action != Action.RIGHT_CLICK_BLOCK) return;
|
switch (action) {
|
||||||
|
case RIGHT_CLICK_AIR, RIGHT_CLICK_BLOCK -> {
|
||||||
|
e.setCancelled(true);
|
||||||
|
|
||||||
|
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
||||||
|
debounce.setCooldown(p.getUniqueId(),100);
|
||||||
|
|
||||||
|
rightClick(p);
|
||||||
|
}
|
||||||
|
case LEFT_CLICK_AIR, LEFT_CLICK_BLOCK -> {
|
||||||
|
e.setCancelled(true);
|
||||||
|
leftClick(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onEntityDamage(EntityDamageByEntityEvent e) {
|
||||||
|
if (!(e.getDamager() instanceof Player p)) return;
|
||||||
|
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
leftClick(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onEntityInteract(PlayerInteractEntityEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
|
|
||||||
if (p.isSneaking()) onRightClickSneak(p);
|
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
||||||
else onRightClick(p);
|
debounce.setCooldown(p.getUniqueId(),100);
|
||||||
|
|
||||||
|
rightClick(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onEntityInteractAt(PlayerInteractAtEntityEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
||||||
|
|
||||||
|
if (debounce.isOnCooldown(p.getUniqueId())) return;
|
||||||
|
debounce.setCooldown(p.getUniqueId(),100);
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
rightClick(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onBlockBreak(BlockBreakEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onBlockPlace(BlockPlaceEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
if (!isWand(e.getItemInHand()) || !p.hasPermission(getUsePermission())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST)
|
||||||
|
public final void onItemDrop(PlayerDropItemEvent e) {
|
||||||
|
Player p = e.getPlayer();
|
||||||
|
if (!isWand(e.getItemDrop().getItemStack()) || !p.hasPermission(getUsePermission())) return;
|
||||||
|
|
||||||
|
e.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onScroll(PlayerItemHeldEvent e) {
|
public final void onScroll(PlayerItemHeldEvent e) {
|
||||||
Player p = e.getPlayer();
|
Player p = e.getPlayer();
|
||||||
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
if (!isHoldingWand(p) || !p.hasPermission(getUsePermission())) return;
|
||||||
|
|
||||||
@@ -81,9 +143,27 @@ public abstract class AbstractWand implements QuickListener, Main {
|
|||||||
int curr = e.getNewSlot();
|
int curr = e.getNewSlot();
|
||||||
|
|
||||||
if (!p.isSneaking() || !isWand(p.getInventory().getItem(prev))) return;
|
if (!p.isSneaking() || !isWand(p.getInventory().getItem(prev))) return;
|
||||||
|
e.setCancelled(true);
|
||||||
|
|
||||||
if (curr < prev) onScrollUp(e.getPlayer());
|
if (curr == 8 && prev == 0) onScrollUp(p);
|
||||||
else if (curr > prev) onScrollDown(e.getPlayer());
|
else if (curr == 0 && prev == 8) onScrollDown(p);
|
||||||
|
else if (curr < prev) onScrollUp(p);
|
||||||
|
else if (curr > prev) onScrollDown(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void swapHand(Player p) {
|
||||||
|
if (p.isSneaking()) onSwapHandSneak(p);
|
||||||
|
else onSwapHand(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void leftClick(Player p) {
|
||||||
|
if (p.isSneaking()) onLeftClickSneak(p);
|
||||||
|
else onLeftClick(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void rightClick(Player p) {
|
||||||
|
if (p.isSneaking()) onRightClickSneak(p);
|
||||||
|
else onRightClick(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onSwapHand(Player player) {}
|
protected void onSwapHand(Player player) {}
|
||||||
@@ -92,6 +172,14 @@ public abstract class AbstractWand implements QuickListener, Main {
|
|||||||
protected void onRightClickSneak(Player player) {}
|
protected void onRightClickSneak(Player player) {}
|
||||||
protected void onLeftClick(Player player) {}
|
protected void onLeftClick(Player player) {}
|
||||||
protected void onLeftClickSneak(Player player) {}
|
protected void onLeftClickSneak(Player player) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The player must be sneaking to scroll the wand.
|
||||||
|
*/
|
||||||
protected void onScrollUp(Player player) {}
|
protected void onScrollUp(Player player) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The player must be sneaking to scroll the wand.
|
||||||
|
*/
|
||||||
protected void onScrollDown(Player player) {}
|
protected void onScrollDown(Player player) {}
|
||||||
}
|
}
|
||||||
@@ -74,26 +74,6 @@ public class Text implements Main {
|
|||||||
message(pallet,true,audience,text,args);
|
message(pallet,true,audience,text,args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendWarning(Audience audience, String warning, Object... args) {
|
|
||||||
messageAny(Pallet.WARNING, audience, warning, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendError(Audience audience, String error, Object... args) {
|
|
||||||
messageAny(Pallet.ERROR, audience, error, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendInfo(Audience audience, String info, Object... args) {
|
|
||||||
messageAny(Pallet.INFO, audience, info, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendSuccess(Audience audience, String success, Object... args) {
|
|
||||||
messageAny(Pallet.SUCCESS, audience, success, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendMessage(Audience audience, String text, Object... args) {
|
|
||||||
messageAny(Pallet.NEUTRAL, audience, text, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the component form of a message, applying pallet formatting to the text and placeholders. Placeholders are zero-indexed and curly braced. {0}, {1}, {2}...
|
* Gets the component form of a message, applying pallet formatting to the text and placeholders. Placeholders are zero-indexed and curly braced. {0}, {1}, {2}...
|
||||||
* @param pallet The colors to use for text and arguments.
|
* @param pallet The colors to use for text and arguments.
|
||||||
|
|||||||
@@ -5,9 +5,12 @@ import me.trouper.alias.server.systems.Verbose;
|
|||||||
import me.trouper.alias.server.systems.TaskManager;
|
import me.trouper.alias.server.systems.TaskManager;
|
||||||
import me.trouper.alias.server.systems.burning.BlockBurner;
|
import me.trouper.alias.server.systems.burning.BlockBurner;
|
||||||
import me.trouper.alias.server.systems.burning.BurnOptions;
|
import me.trouper.alias.server.systems.burning.BurnOptions;
|
||||||
|
import me.trouper.alias.utils.TargetingUtils;
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.InventoryHolder;
|
import org.bukkit.inventory.InventoryHolder;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@@ -23,6 +26,7 @@ public class ExplosionUtils implements Main {
|
|||||||
private double coreRadius = 3.0;
|
private double coreRadius = 3.0;
|
||||||
private double falloffRadius = 8.0;
|
private double falloffRadius = 8.0;
|
||||||
private double maxBurnRadius = 15.0;
|
private double maxBurnRadius = 15.0;
|
||||||
|
private double baseDamage = 20;
|
||||||
private double destructionDelay = 0.0; // SECONDS
|
private double destructionDelay = 0.0; // SECONDS
|
||||||
private double burnDelay = 0.5; // SECONDS
|
private double burnDelay = 0.5; // SECONDS
|
||||||
private double maxHeat = 1.0;
|
private double maxHeat = 1.0;
|
||||||
@@ -40,6 +44,9 @@ public class ExplosionUtils implements Main {
|
|||||||
public double getMaxBurnRadius() { return maxBurnRadius; }
|
public double getMaxBurnRadius() { return maxBurnRadius; }
|
||||||
public void setMaxBurnRadius(double maxBurnRadius) { this.maxBurnRadius = maxBurnRadius; }
|
public void setMaxBurnRadius(double maxBurnRadius) { this.maxBurnRadius = maxBurnRadius; }
|
||||||
|
|
||||||
|
public double getBaseDamage() { return baseDamage; }
|
||||||
|
public void setBaseDamage(double baseDamage) { this.baseDamage = baseDamage; }
|
||||||
|
|
||||||
public double getDestructionDelay() { return destructionDelay; }
|
public double getDestructionDelay() { return destructionDelay; }
|
||||||
public void setDestructionDelay(double destructionDelay) { this.destructionDelay = destructionDelay; }
|
public void setDestructionDelay(double destructionDelay) { this.destructionDelay = destructionDelay; }
|
||||||
|
|
||||||
@@ -92,22 +99,22 @@ public class ExplosionUtils implements Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void restore() {
|
public void restore() {
|
||||||
// First cleanup all tasks
|
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
// Then restore blocks
|
|
||||||
for (Map.Entry<Block, BlockState> entry : originalStates.entrySet()) {
|
for (Map.Entry<Block, BlockState> entry : originalStates.entrySet()) {
|
||||||
Block block = entry.getKey();
|
Block block = entry.getKey();
|
||||||
BlockState snapshot = entry.getValue();
|
BlockState snapshot = entry.getValue();
|
||||||
|
|
||||||
block.setBlockData(snapshot.getBlockData(), false);
|
Bukkit.getScheduler().runTask(main.getPlugin(),()->{
|
||||||
snapshot.update(true, false);
|
block.setBlockData(snapshot.getBlockData(), false);
|
||||||
|
snapshot.update(true, false);
|
||||||
|
|
||||||
ItemStack[] contents = originalInventories.get(block);
|
ItemStack[] contents = originalInventories.get(block);
|
||||||
if (contents != null && block.getState() instanceof InventoryHolder) {
|
if (contents != null && block.getState() instanceof InventoryHolder) {
|
||||||
Inventory inv = ((InventoryHolder) block.getState()).getInventory();
|
Inventory inv = ((InventoryHolder) block.getState()).getInventory();
|
||||||
inv.setContents(contents);
|
inv.setContents(contents);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,9 +134,11 @@ public class ExplosionUtils implements Main {
|
|||||||
World world = center.getWorld();
|
World world = center.getWorld();
|
||||||
if (world == null) throw new IllegalArgumentException("Center location must have a valid world");
|
if (world == null) throw new IllegalArgumentException("Center location must have a valid world");
|
||||||
|
|
||||||
Map<Block, Double> affectedBlocks = getBlocksInRadius(center, options.getMaxBurnRadius());
|
double maxBurnRadius = options.getMaxBurnRadius();
|
||||||
|
|
||||||
|
Map<Block, Double> affectedBlocks = getBlocksInRadius(center, maxBurnRadius);
|
||||||
|
Map<UUID, Double> affectedEntities = getEntitiesInRadius(center, maxBurnRadius);
|
||||||
|
|
||||||
// Create shared task manager for this explosion
|
|
||||||
TaskManager sharedTaskManager = new TaskManager();
|
TaskManager sharedTaskManager = new TaskManager();
|
||||||
BlockBurner burner = new BlockBurner(options.getBurnOptions(), sharedTaskManager);
|
BlockBurner burner = new BlockBurner(options.getBurnOptions(), sharedTaskManager);
|
||||||
ExplosionResult result = new ExplosionResult(burner);
|
ExplosionResult result = new ExplosionResult(burner);
|
||||||
@@ -147,6 +156,7 @@ public class ExplosionUtils implements Main {
|
|||||||
|
|
||||||
scheduleDestruction(blocksToDestroy, options, sharedTaskManager);
|
scheduleDestruction(blocksToDestroy, options, sharedTaskManager);
|
||||||
scheduleBurning(blocksToBurn, blocksHeatMap, burner, center, options, sharedTaskManager);
|
scheduleBurning(blocksToBurn, blocksHeatMap, burner, center, options, sharedTaskManager);
|
||||||
|
scheduleDamage(affectedEntities, options, sharedTaskManager);
|
||||||
|
|
||||||
if (options.isCreateParticles() || options.isPlaySound()) createExplosionEffects(center, options);
|
if (options.isCreateParticles() || options.isPlaySound()) createExplosionEffects(center, options);
|
||||||
|
|
||||||
@@ -180,6 +190,17 @@ public class ExplosionUtils implements Main {
|
|||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Map<UUID, Double> getEntitiesInRadius(Location center, double radius) {
|
||||||
|
List<LivingEntity> rawList = center.getNearbyLivingEntities(radius).stream().toList();
|
||||||
|
Map<UUID, Double> entities = new HashMap<>();
|
||||||
|
|
||||||
|
for (LivingEntity livingEntity : rawList) {
|
||||||
|
entities.put(livingEntity.getUniqueId(),livingEntity.getLocation().distance(center));
|
||||||
|
}
|
||||||
|
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
private static void categorizeBlocks(Map<Block, Double> affectedBlocks, ExplosionOptions options,
|
private static void categorizeBlocks(Map<Block, Double> affectedBlocks, ExplosionOptions options,
|
||||||
Set<Block> blocksToDestroy, Set<Block> blocksToBurn,
|
Set<Block> blocksToDestroy, Set<Block> blocksToBurn,
|
||||||
Map<Block, Float> blocksHeatMap) {
|
Map<Block, Float> blocksHeatMap) {
|
||||||
@@ -296,6 +317,41 @@ public class ExplosionUtils implements Main {
|
|||||||
}, burnDelayTicks);
|
}, burnDelayTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void scheduleDamage(Map<UUID, Double> affected, ExplosionOptions options, TaskManager taskManager) {
|
||||||
|
double baseDamage = options.getBaseDamage();
|
||||||
|
double igniteDistance = options.getMaxBurnRadius();
|
||||||
|
double halfDamageDistance = options.getFalloffRadius();
|
||||||
|
double fullDamageDistance = options.getCoreRadius();
|
||||||
|
|
||||||
|
for (Map.Entry<UUID, Double> entityDistance : affected.entrySet()) {
|
||||||
|
LivingEntity liv = (LivingEntity) Bukkit.getEntity(entityDistance.getKey());
|
||||||
|
if (liv == null) continue;
|
||||||
|
|
||||||
|
double distance = entityDistance.getValue();
|
||||||
|
|
||||||
|
if (distance >= halfDamageDistance && distance <= igniteDistance) {
|
||||||
|
taskManager.scheduleTask(()->{
|
||||||
|
liv.setFireTicks(5 * 20);
|
||||||
|
},(long) distance / 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (distance >= fullDamageDistance && distance <= halfDamageDistance) {
|
||||||
|
taskManager.scheduleTask(()->{
|
||||||
|
liv.setFireTicks(10 * 20);
|
||||||
|
liv.damage(baseDamage / 2);
|
||||||
|
},(long) distance / 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (distance <= fullDamageDistance) {
|
||||||
|
taskManager.scheduleTask(()->{
|
||||||
|
liv.setFireTicks(15 * 20);
|
||||||
|
liv.damage(baseDamage);
|
||||||
|
},(long) distance / 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void createExplosionEffects(Location center, ExplosionOptions options) {
|
private static void createExplosionEffects(Location center, ExplosionOptions options) {
|
||||||
World world = center.getWorld();
|
World world = center.getWorld();
|
||||||
if (world == null) return;
|
if (world == null) return;
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package me.trouper.alias.server.systems.world;
|
||||||
|
|
||||||
|
public class Snapshot {
|
||||||
|
|
||||||
|
}
|
||||||
20
src/main/java/me/trouper/alias/utils/VectorUtils.java
Normal file
20
src/main/java/me/trouper/alias/utils/VectorUtils.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package me.trouper.alias.utils;
|
||||||
|
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class VectorUtils {
|
||||||
|
|
||||||
|
public static float[] toAngles(Vector vector) {
|
||||||
|
double x = vector.getX();
|
||||||
|
double y = vector.getY();
|
||||||
|
double z = vector.getZ();
|
||||||
|
|
||||||
|
float yaw = (float) Math.toDegrees(Math.atan2(-x, z));
|
||||||
|
|
||||||
|
double xzLength = Math.sqrt(x * x + z * z);
|
||||||
|
|
||||||
|
float pitch = (float) Math.toDegrees(Math.atan2(-y, xzLength));
|
||||||
|
|
||||||
|
return new float[] { yaw, pitch };
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/main/java/me/trouper/alias/utils/misc/TimeUtils.java
Normal file
20
src/main/java/me/trouper/alias/utils/misc/TimeUtils.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package me.trouper.alias.utils.misc;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
public class TimeUtils {
|
||||||
|
|
||||||
|
public static String formatTime(long millis) {
|
||||||
|
Instant instant = Instant.ofEpochMilli(millis);
|
||||||
|
return DateTimeFormatter.RFC_1123_DATE_TIME.withZone(ZoneId.of("UTC")).format(instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long deserializeTime(String rfcString) {
|
||||||
|
LocalDateTime dateTime = LocalDateTime.parse(rfcString, DateTimeFormatter.RFC_1123_DATE_TIME);
|
||||||
|
return dateTime.atZone(ZoneId.of("UTC")).toInstant().toEpochMilli();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user