Downstream changes (#100)

Additions:
* Clickable Polls
* Halloween Gizmos

General Changes:
* Bungee players reduced
* Broadcast perms are now false by default
* Zombie hitboxes removed

Fixes:
* Minecarts can no longer be moved in lobbies
* 1 day holidays now work properly
* Staff can see team chat
* Headless horseman works
* Lobby portals now spam clients with connection messages
* Mutation token GUIs no longer show when mutation polls are disabled
* Double jump works again
This commit is contained in:
Austin Mayes 2018-11-20 17:59:52 -06:00 committed by GitHub
parent 530885fd66
commit f3f74b50e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 585 additions and 134 deletions

View File

@ -210,7 +210,10 @@ public class GameFormatter {
}
public void sendList(Audience audience, Collection<Game> games) {
if(games.isEmpty()) return;
if(games.isEmpty()) {
audience.sendMessage(new WarningComponent("game.none"));
return;
}
audience.sendMessage(
new Component(

View File

@ -31,7 +31,7 @@ import static tc.oc.commons.core.stream.Collectors.toImmutableSet;
@Singleton
public class PingListener implements Listener, PluginFacet {
private static final int MAX_PLAYERS = 3000;
private static final int MAX_PLAYERS = 300;
private final Logger logger;
private final Random random = new Random();

View File

@ -101,6 +101,7 @@ game.waitingForPlayers = Waiting for {0} more players to join {1}...
game.left = Left {0}
game.unknown = Unknown game '{0}'
game.offline = Sorry, {0} is offline right now
game.none = There are currently no playable games
game.empty = There are no {0} matches happening right now
game.choose = Click on a game below, or type {0} or {1}
game.numOnline = {0} players

View File

@ -3,3 +3,7 @@ gizmo.gun.empty = No Droplets available to shoot
raindrops.purchase.fail = You do not have enough Droplets to purchase this
purchase.purchase.fail = Purchase failed
version.too.old.gizmo = This gizmo requires at least Minecraft 1.9
gizmo.use.cooldown = You must wait to use this gizmo again

View File

@ -57,4 +57,4 @@ trial.joinFull = join full servers
trial.chooseTeam = choose their team
# {0} = shop URL
trial.upgrade = Visit {0} to extend your membership.
trial.upgrade = Visit {0} to extend your membership.

View File

@ -1,7 +1,6 @@
package tc.oc.lobby.bukkit;
import javax.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import org.bukkit.permissions.Permission;

View File

@ -3,7 +3,6 @@ package tc.oc.lobby.bukkit;
import java.util.List;
import java.util.logging.Level;
import javax.inject.Inject;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.configuration.Configuration;

View File

@ -7,6 +7,7 @@ import tc.oc.commons.core.inject.HybridManifest;
import tc.oc.commons.core.plugin.PluginFacetBinder;
import tc.oc.lobby.bukkit.gizmos.GizmoUtils;
import tc.oc.lobby.bukkit.gizmos.gun.GunGizmo;
import tc.oc.lobby.bukkit.gizmos.halloween.ghost.GhostGizmo;
import tc.oc.lobby.bukkit.listeners.PlayerListener;
import tc.oc.lobby.bukkit.listeners.PortalsListener;
import tc.oc.lobby.bukkit.listeners.RaindropsListener;
@ -24,6 +25,7 @@ public class LobbyManifest extends HybridManifest {
requestStaticInjection(GizmoUtils.class);
requestStaticInjection(GunGizmo.class);
requestStaticInjection(GhostGizmo.class);
}
@Provides World world(Server server) {

View File

@ -1,16 +1,12 @@
package tc.oc.lobby.bukkit;
import me.anxuiz.settings.*;
import me.anxuiz.settings.bukkit.PlayerSettingCallback;
import me.anxuiz.settings.Setting;
import me.anxuiz.settings.SettingBuilder;
import me.anxuiz.settings.SettingCallbackManager;
import me.anxuiz.settings.SettingRegistry;
import me.anxuiz.settings.TypeParseException;
import me.anxuiz.settings.bukkit.PlayerSettings;
import me.anxuiz.settings.types.EnumType;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import tc.oc.commons.bukkit.hologram.Hologram;
import tc.oc.commons.bukkit.hologram.content.HologramAnimation;
import tc.oc.commons.bukkit.util.ItemCreator;
import javax.annotation.Nonnull;
public class Settings {

View File

@ -1,5 +1,7 @@
package tc.oc.lobby.bukkit;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
@ -16,9 +18,6 @@ import java.util.logging.Logger;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import javax.inject.Inject;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;

View File

@ -1,8 +1,13 @@
package tc.oc.lobby.bukkit;
import java.util.List;
import net.minecraft.server.*;
import net.minecraft.server.EntityPlayer;
import net.minecraft.server.Packet;
import net.minecraft.server.PacketPlayOutScoreboardDisplayObjective;
import net.minecraft.server.PacketPlayOutScoreboardScore;
import net.minecraft.server.ScoreboardObjective;
import net.minecraft.server.ScoreboardScore;
import net.minecraft.server.ScoreboardServer;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Material;
@ -57,6 +62,7 @@ public class Utils {
player.setGravity(true);
player.setPotionParticles(false);
player.hideTitle();
player.setCollidesWithEntities(false);
player.getWorld().spawnParticle(Particle.CLOUD, player.getLocation(), 15, 0.5, 0.5, 0.5, 0);
}

View File

@ -1,8 +1,7 @@
package tc.oc.lobby.bukkit.gizmos;
import java.util.List;
import com.google.common.collect.Lists;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@ -10,7 +9,7 @@ import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import tc.oc.lobby.bukkit.LobbyTranslations;
import tc.oc.lobby.bukkit.gizmos.halloween.HeadlessHorsemanGizmo;
import tc.oc.lobby.bukkit.gizmos.halloween.HalloweenGizmo;
import tc.oc.lobby.bukkit.listeners.RaindropsListener;
public abstract class Gizmo implements Listener {
@ -29,7 +28,7 @@ public abstract class Gizmo implements Listener {
this.initialize();
}
protected abstract void initialize();
public String getName(Player viewer) {
@ -61,7 +60,7 @@ public abstract class Gizmo implements Listener {
}
public String getCostText(Player player) {
if (this.getClass().isInstance(HeadlessHorsemanGizmo.class)) {
if (this instanceof HalloweenGizmo) {
return ChatColor.YELLOW + LobbyTranslations.get().t("gizmo.specialEvent", player);
} else if(this.getClass().isInstance(Gizmos.purchasingMap.get(player))) {
return ChatColor.GOLD + LobbyTranslations.get().t("gizmo.purchasing", player);
@ -77,7 +76,7 @@ public abstract class Gizmo implements Listener {
}
public boolean ownsGizmo(Player player) {
if(cost <= 0) {
if(cost <= 0 && (!(this instanceof HalloweenGizmo))) {
return true;
} else {
return player.hasPermission(this.getPermissionNode());

View File

@ -1,8 +1,7 @@
package tc.oc.lobby.bukkit.gizmos;
import javax.inject.Inject;
import com.google.common.collect.Lists;
import javax.inject.Inject;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@ -12,17 +11,17 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import tc.oc.api.bukkit.users.Users;
import tc.oc.api.docs.PlayerId;
import tc.oc.lobby.bukkit.Lobby;
import tc.oc.minecraft.scheduler.SyncExecutor;
import tc.oc.api.users.PurchaseGizmoRequest;
import tc.oc.api.users.UserService;
import tc.oc.commons.bukkit.raindrops.PlayerRecieveRaindropsEvent;
import tc.oc.commons.core.chat.Component;
import tc.oc.commons.core.commands.CommandFutureCallback;
import tc.oc.commons.core.formatting.StringUtils;
import tc.oc.lobby.bukkit.Lobby;
import tc.oc.lobby.bukkit.LobbyTranslations;
import tc.oc.lobby.bukkit.Utils;
import tc.oc.lobby.bukkit.listeners.RaindropsListener;
import tc.oc.commons.bukkit.raindrops.PlayerRecieveRaindropsEvent;
import tc.oc.minecraft.scheduler.SyncExecutor;
public class GizmoUtils {

View File

@ -1,10 +1,9 @@
package tc.oc.lobby.bukkit.gizmos;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@ -20,7 +19,8 @@ import tc.oc.lobby.bukkit.LobbyTranslations;
import tc.oc.lobby.bukkit.gizmos.chicken.ChickenGizmo;
import tc.oc.lobby.bukkit.gizmos.empty.EmptyGizmo;
import tc.oc.lobby.bukkit.gizmos.gun.GunGizmo;
import tc.oc.lobby.bukkit.gizmos.halloween.HeadlessHorsemanGizmo;
import tc.oc.lobby.bukkit.gizmos.halloween.ghost.GhostGizmo;
import tc.oc.lobby.bukkit.gizmos.halloween.horse.HeadlessHorsemanGizmo;
import tc.oc.lobby.bukkit.gizmos.launcher.LauncherGizmo;
import tc.oc.lobby.bukkit.gizmos.popper.PopperGizmo;
import tc.oc.lobby.bukkit.gizmos.rocket.RocketGizmo;
@ -32,10 +32,10 @@ public class Gizmos implements Listener {
public static GunGizmo gunGizmo = new GunGizmo("Raindrop Gun", ChatColor.AQUA.toString(), "Gift raindrops with a punch :D", Material.IRON_HOE, 7500);
public static ChickenGizmo chickenGizmo = new ChickenGizmo("Chickenifier5000", ChatColor.YELLOW.toString(), "bok B'GAWK", Material.EGG, 10000);
public static LauncherGizmo launcherGizmo = new LauncherGizmo("Murica", ChatColor.RED.toString(), "Show your pride!", Material.FEATHER, 17760);
//TODO: Replace cost and handle permissions
public static HeadlessHorsemanGizmo headlessHorsemanGizmo = new HeadlessHorsemanGizmo("The Headless Horseman", ChatColor.RED.toString(), "You have been taken over by the darkness...", Material.NETHER_STAR, 999999);
public static HeadlessHorsemanGizmo headlessHorsemanGizmo = new HeadlessHorsemanGizmo("The Headless Horseman", ChatColor.RED.toString(), "You have been taken over by the darkness...", Material.NETHER_STAR);
public static GhostGizmo ghostGizmo = new GhostGizmo("Ghosts", ChatColor.RED.toString(), "Surround yourself in ghosts!", Material.BONE);
public static final List<Gizmo> gizmos = Lists.newArrayList(emptyGizmo, popperGizmo, rocketGizmo, gunGizmo, chickenGizmo, launcherGizmo, headlessHorsemanGizmo);
public static final List<Gizmo> gizmos = Lists.newArrayList(emptyGizmo, popperGizmo, rocketGizmo, gunGizmo, chickenGizmo, launcherGizmo, headlessHorsemanGizmo, ghostGizmo);
public static Map<Player, Gizmo> gizmoMap = Maps.newHashMap();
public static Map<Player, Gizmo> purchasingMap = Maps.newHashMap();

View File

@ -1,12 +1,11 @@
package tc.oc.lobby.bukkit.gizmos.chicken;
import com.google.common.collect.Maps;
import com.google.inject.Injector;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Maps;
import com.google.inject.Injector;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -22,6 +21,7 @@ import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import tc.oc.api.bukkit.users.Users;
import tc.oc.commons.bukkit.nick.IdentityProvider;
import tc.oc.commons.bukkit.raindrops.RaindropUtil;
import tc.oc.commons.bukkit.util.NMSHacks;
import tc.oc.commons.core.chat.Component;
import tc.oc.lobby.bukkit.Lobby;
@ -29,7 +29,6 @@ import tc.oc.lobby.bukkit.LobbyTranslations;
import tc.oc.lobby.bukkit.gizmos.Gizmo;
import tc.oc.lobby.bukkit.gizmos.GizmoConfig;
import tc.oc.lobby.bukkit.gizmos.Gizmos;
import tc.oc.commons.bukkit.raindrops.RaindropUtil;
public class ChickenGizmo extends Gizmo implements Listener {

View File

@ -1,13 +1,12 @@
package tc.oc.lobby.bukkit.gizmos.gun;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.inject.Inject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;

View File

@ -0,0 +1,26 @@
package tc.oc.lobby.bukkit.gizmos.halloween;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import tc.oc.lobby.bukkit.gizmos.Gizmo;
import tc.oc.lobby.bukkit.gizmos.Gizmos;
public abstract class HalloweenGizmo extends Gizmo {
public HalloweenGizmo(String name, String prefix, String description, Material icon) {
super(name, prefix, description, icon, 0);
}
@Override
public boolean canPurchase(Player player) {
// HACK: Players can only have one hallow gizmo
return (player.hasPermission("lobby.gizmo.buy.hallow") && !ownsAny(player)) || player.isOp();
}
private boolean ownsAny(Player player) {
for (Gizmo gizmo : Gizmos.gizmos) {
if (gizmo instanceof HalloweenGizmo && gizmo.ownsGizmo(player)) return true;
}
return false;
}
}

View File

@ -0,0 +1,49 @@
package tc.oc.lobby.bukkit.gizmos.halloween.ghost;
import java.time.Duration;
import java.time.Instant;
import javax.inject.Inject;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import tc.oc.commons.bukkit.chat.Audiences;
import tc.oc.commons.bukkit.util.OnlinePlayerMapAdapter;
import tc.oc.lobby.bukkit.Lobby;
import tc.oc.lobby.bukkit.gizmos.Gizmos;
import tc.oc.lobby.bukkit.gizmos.halloween.HalloweenGizmo;
public class GhostGizmo extends HalloweenGizmo implements Listener {
private final OnlinePlayerMapAdapter<Instant> coolDowns = new OnlinePlayerMapAdapter<>(Lobby.get());
private static final Duration COOLDOWN = Duration.ofMinutes(1);
@Inject private static Audiences audiences;
public GhostGizmo(String name, String prefix, String description, Material icon) {
super(name, prefix, description, icon);
this.coolDowns.enable();
}
@Override
protected void initialize() {
Bukkit.getPluginManager().registerEvents(this, Lobby.get());
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
if (!(Gizmos.gizmoMap.get(player) instanceof GhostGizmo)) return;
if (player.getItemInHand().getType() != this.getIcon()) return;
if (coolDowns.get(player) == null || coolDowns.get(player).isBefore(Instant.now().minus(COOLDOWN))) {
coolDowns.put(player, Instant.now());
new GhostTask(player).runTask(0, 1);
} else {
audiences.get(player).sendWarning(new TranslatableComponent("gizmo.use.cooldown"), true);
}
}
}

View File

@ -0,0 +1,115 @@
package tc.oc.lobby.bukkit.gizmos.halloween.ghost;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Skin;
import org.bukkit.Sound;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.EulerAngle;
import org.bukkit.util.Vector;
import tc.oc.commons.bukkit.item.ItemBuilder;
import tc.oc.commons.bukkit.scheduler.RepeatingRunnable;
import tc.oc.commons.bukkit.util.Vectors;
import tc.oc.lobby.bukkit.Lobby;
public class GhostTask extends RepeatingRunnable {
private static final Skin GHOST = new Skin("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlc"
+ "y5taW5lY3JhZnQubmV0L3RleHR1cmUvZWY3YTRmOTVlNWZlOTliNDViZTYxYmIzMzg4MmMxMmE5M2IyMmQyOTdmZDE3NjVhYjIxZTc3"
+ "NDhkYzZiOGNmMyJ9fX0=", null);
private static final ItemStack HEAD = new ItemBuilder().material(Material.SKULL_ITEM).durability(3).skin(null, UUID.randomUUID(), GHOST).get();
private static final ItemStack CHEST = new ItemBuilder().material(Material.LEATHER_CHESTPLATE).get();
private static final int TOTAL_TICKS = 20 * 20;
private static final int NUM_GHOSTS = 3;
private final Player player;
private final List<ArmorStand> ghosts;
static {
LeatherArmorMeta meta = (LeatherArmorMeta) CHEST.getItemMeta();
meta.setColor(Color.BLACK);
CHEST.setItemMeta(meta);
}
public GhostTask(Player player) {
super(TOTAL_TICKS);
this.player = player;
this.ghosts = new ArrayList<>();
for (int i = 0; i < NUM_GHOSTS; i++) {
// proportion as to how far the ghost should be in the circle
double prop = i / (double) NUM_GHOSTS;
Vector v = new Vector(3, .5, 0);
Vectors.rotateAroundAxisY(v, prop * 2 * Math.PI);
Location spawnLoc = player.getLocation().add(v);
spawnLoc.setDirection(player.getEyeLocation().subtract(spawnLoc.clone().add(0, player.getEyeHeight(), 0)).toVector());
ghosts.add(createGhost(spawnLoc));
}
}
@Override
protected void repeat() {
// end condition
if (getIteration() == TOTAL_TICKS - 1) {
player.getWorld().playSound(player.getLocation(), Sound.BLOCK_SNOW_BREAK, .5f, .75f);
for (ArmorStand ghost : ghosts) {
ghost.remove();
player.getWorld().spawnParticle(Particle.EXPLOSION_HUGE, ghost.getLocation().add(0, 1, 0), 1, 0, 0, 0, .5);
}
}
// otherwise...
for (int i = 0; i < NUM_GHOSTS; i++) {
ArmorStand ghost = ghosts.get(i);
// proportion as to how far the ghost should be in the circle
double prop = i / (double) NUM_GHOSTS;
// proportion as to how far in the animation we are
double offset = getIteration() / (double) TOTAL_TICKS;
Vector v = new Vector(3, .5, 0);
Vectors.rotateAroundAxisY(v, prop * 2 * Math.PI + offset * 10);
// put ghost in proper location
Location nextLoc = player.getLocation().add(v);
nextLoc.setDirection(player.getEyeLocation().subtract(nextLoc.clone().add(0, player.getEyeHeight(), 0)).toVector());
ghost.teleport(nextLoc);
// now lets spawn particles
player.getWorld().spawnParticle(Particle.SMOKE_LARGE, ghost.getLocation().add(0, 1, 0), 3, 1, .3, 0, .1);
if (getIteration() % 4 == 0) {
player.getWorld().spawnParticle(Particle.FLAME, ghost.getLocation().add(0, 1, 0), 1, 0, .5, 0, .2);
}
}
}
@Override
protected Plugin plugin() {
return Lobby.get();
}
private ArmorStand createGhost(Location l) {
ArmorStand stand = l.getWorld().spawn(l, ArmorStand.class);
stand.setVisible(false);
stand.setBasePlate(false);
stand.setHelmet(HEAD);
stand.setChestplate(CHEST);
stand.setMarker(false);
stand.setGravity(false);
stand.setHeadPose(new EulerAngle(.4, 0, 0));
return stand;
}
}

View File

@ -1,13 +1,12 @@
package tc.oc.lobby.bukkit.gizmos.halloween;
package tc.oc.lobby.bukkit.gizmos.halloween.horse;
import com.google.common.collect.ImmutableList;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.AbstractHorse;
import org.bukkit.entity.Horse;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.HorseInventory;
import org.bukkit.inventory.ItemStack;
import tc.oc.commons.core.util.Optionals;
@ -27,20 +26,26 @@ public class HeadlessHorse {
protected AbstractHorse spawn(Location location, Class<AbstractHorse> horse) {
AbstractHorse entity = viewer.getWorld().spawn(location, horse);
this.horse = entity;
Optionals.cast(horse, Horse.class).ifPresent(living -> {
Optionals.cast(entity, Horse.class).ifPresent(living -> {
living.setRemoveWhenFarAway(true);
living.setCollidable(false);
living.setCanPickupItems(false);
living.setInvulnerable(true);
living.setAdult();
EntityEquipment entityEquipment = living.getEquipment();
entityEquipment.setHelmetDropChance(0);
entityEquipment.setChestplateDropChance(0);
entityEquipment.setLeggingsDropChance(0);
entityEquipment.setBootsDropChance(0);
entity.setTamed(true);
living.getInventory().setSaddle(new ItemStack(Material.SADDLE));
living.setPassengers(ImmutableList.of(viewer));
living.setDomestication(1);
living.setMaxDomestication(1);
living.setTamed(true);
living.setOwner(viewer);
living.setPassenger(viewer);
HorseInventory inventory = living.getInventory();
inventory.setSaddle(new ItemStack(Material.SADDLE));
});
return entity;
}

View File

@ -1,4 +1,4 @@
package tc.oc.lobby.bukkit.gizmos.halloween;
package tc.oc.lobby.bukkit.gizmos.halloween.horse;
import com.google.common.collect.ImmutableMap;
import org.bukkit.Color;

View File

@ -1,4 +1,4 @@
package tc.oc.lobby.bukkit.gizmos.halloween;
package tc.oc.lobby.bukkit.gizmos.halloween.horse;
import java.util.Map;
import java.util.WeakHashMap;
@ -6,21 +6,26 @@ import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.PoseFlag;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;
import tc.oc.commons.bukkit.chat.WarningComponent;
import tc.oc.lobby.bukkit.Lobby;
import tc.oc.lobby.bukkit.gizmos.Gizmo;
import tc.oc.lobby.bukkit.gizmos.Gizmos;
import tc.oc.lobby.bukkit.gizmos.halloween.HalloweenGizmo;
import tc.oc.minecraft.protocol.MinecraftVersion;
public class HeadlessHorsemanGizmo extends Gizmo implements Listener {
public class HeadlessHorsemanGizmo extends HalloweenGizmo implements Listener {
private Map<Player, HeadlessHorseman> mutated;
private Map<Player, HeadlessHorse> horseByPlayer;
public HeadlessHorsemanGizmo(String name, String prefix, String description, Material icon, int cost) {
super(name, prefix, description, icon, cost);
public HeadlessHorsemanGizmo(String name, String prefix, String description, Material icon) {
super(name, prefix, description, icon);
this.mutated = new WeakHashMap<>();
this.horseByPlayer = new WeakHashMap<>();
}
@ -37,10 +42,14 @@ public class HeadlessHorsemanGizmo extends Gizmo implements Listener {
final Player player = e.getPlayer();
if(mutated.get(player) == null) {
HeadlessHorseman horseman = new HeadlessHorseman(player);
mutated.put(player, horseman);
horseByPlayer.put(player, horseman.getHeadlessHorse());
createEffect(player);
if (MinecraftVersion.atLeast(MinecraftVersion.MINECRAFT_1_9, player.getProtocolVersion())) {
HeadlessHorseman horseman = new HeadlessHorseman(player);
mutated.put(player, horseman);
horseByPlayer.put(player, horseman.getHeadlessHorse());
createEffect(player);
} else {
player.sendMessage(new WarningComponent("version.too.old.gizmo"));
}
} else {
mutated.get(player).restore();
mutated.remove(player);
@ -48,6 +57,25 @@ public class HeadlessHorsemanGizmo extends Gizmo implements Listener {
}
}
@EventHandler
public void onDismount(PlayerMoveEvent event) {
if (event.getEntityTo().poseFlags().contains(PoseFlag.RIDING)) return;
if (!mutated.containsKey(event.getPlayer())) return;
mutated.get(event.getPlayer()).restore();
mutated.remove(event.getPlayer());
horseByPlayer.remove(event.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
if (!mutated.containsKey(event.getPlayer())) return;
mutated.get(event.getPlayer()).restore();
mutated.remove(event.getPlayer());
horseByPlayer.remove(event.getPlayer());
}
private void createEffect(Player viewer) {
new BukkitRunnable() {
@Override

View File

@ -1,6 +1,10 @@
package tc.oc.lobby.bukkit.gizmos.launcher;
import org.bukkit.*;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;

View File

@ -1,7 +1,7 @@
package tc.oc.lobby.bukkit.gizmos.popper;
import com.google.common.collect.Maps;
import java.util.Map;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -11,17 +11,15 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import com.google.common.collect.Maps;
import org.bukkit.event.player.PlayerQuitEvent;
import tc.oc.api.bukkit.users.Users;
import tc.oc.commons.bukkit.raindrops.RaindropUtil;
import tc.oc.commons.core.chat.Component;
import tc.oc.lobby.bukkit.Lobby;
import tc.oc.lobby.bukkit.LobbyTranslations;
import tc.oc.lobby.bukkit.gizmos.Gizmo;
import tc.oc.lobby.bukkit.gizmos.GizmoConfig;
import tc.oc.lobby.bukkit.gizmos.Gizmos;
import tc.oc.commons.bukkit.raindrops.RaindropUtil;
public class PopperGizmo extends Gizmo implements Listener {
public Map<Player, Integer> poppedCount = Maps.newHashMap();

View File

@ -1,13 +1,11 @@
package tc.oc.lobby.bukkit.gizmos.rocket;
import com.google.common.collect.Lists;
import java.util.List;
import org.bukkit.entity.Firework;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import com.google.common.collect.Lists;
public class Rocket {
public Rocket(Player observer, Player victim, List<Firework> fireworks) {
this.observer = observer;

View File

@ -2,6 +2,8 @@ package tc.oc.lobby.bukkit.gizmos.rocket;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -14,16 +16,13 @@ import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.util.Vector;
import tc.oc.api.bukkit.users.Users;
import tc.oc.commons.bukkit.raindrops.RaindropUtil;
import tc.oc.commons.core.chat.Component;
import tc.oc.lobby.bukkit.Lobby;
import tc.oc.lobby.bukkit.LobbyTranslations;
import tc.oc.lobby.bukkit.gizmos.Gizmo;
import tc.oc.lobby.bukkit.gizmos.GizmoConfig;
import tc.oc.lobby.bukkit.gizmos.Gizmos;
import tc.oc.commons.bukkit.raindrops.RaindropUtil;
import java.util.List;
import java.util.Map;
public class RocketGizmo extends Gizmo implements Listener {
public final List<Rocket> rockets = Lists.newArrayList();

View File

@ -1,10 +1,9 @@
package tc.oc.lobby.bukkit.gizmos.rocket;
import java.util.Iterator;
import org.bukkit.util.Vector;
import tc.oc.lobby.bukkit.gizmos.Gizmos;
import java.util.Iterator;
public class RocketTask implements Runnable{
@Override
public void run() {

View File

@ -1,11 +1,15 @@
package tc.oc.lobby.bukkit.gizmos.rocket;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Random;
import net.minecraft.server.Packet;
import net.minecraft.server.PacketPlayOutEntity;
import org.bukkit.*;
import org.bukkit.Color;
import org.bukkit.Effect;
import org.bukkit.FireworkEffect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Firework;
@ -13,8 +17,6 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.util.Vector;
import com.google.common.collect.Lists;
import tc.oc.lobby.bukkit.gizmos.GizmoConfig;
public class RocketUtils {

View File

@ -1,11 +1,19 @@
package tc.oc.lobby.bukkit.listeners;
import static net.md_5.bungee.api.ChatColor.AQUA;
import static net.md_5.bungee.api.ChatColor.DARK_AQUA;
import static net.md_5.bungee.api.ChatColor.DARK_PURPLE;
import static net.md_5.bungee.api.ChatColor.GOLD;
import static net.md_5.bungee.api.ChatColor.GREEN;
import static net.md_5.bungee.api.ChatColor.LIGHT_PURPLE;
import com.google.common.eventbus.Subscribe;
import java.time.Duration;
import java.time.Instant;
import java.util.Random;
import java.util.logging.Level;
import javax.annotation.Nullable;
import javax.inject.Inject;
import com.google.common.eventbus.Subscribe;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.Location;
@ -24,11 +32,9 @@ import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.geometry.Cuboid;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import java.time.Duration;
import java.time.Instant;
import tc.oc.api.bukkit.users.OnlinePlayers;
import tc.oc.api.docs.User;
import tc.oc.api.docs.virtual.ServerDoc;
@ -38,6 +44,7 @@ import tc.oc.commons.bukkit.bossbar.BossBarFactory;
import tc.oc.commons.bukkit.chat.Audiences;
import tc.oc.commons.bukkit.chat.ComponentRenderContext;
import tc.oc.commons.bukkit.chat.HeaderComponent;
import tc.oc.commons.bukkit.chat.Links;
import tc.oc.commons.bukkit.event.ObserverKitApplyEvent;
import tc.oc.commons.bukkit.event.UserLoginEvent;
import tc.oc.commons.core.chat.Audience;
@ -49,9 +56,6 @@ import tc.oc.commons.core.restart.RequestRestartEvent;
import tc.oc.commons.core.util.TimeUtils;
import tc.oc.lobby.bukkit.LobbyConfig;
import tc.oc.lobby.bukkit.Utils;
import tc.oc.commons.bukkit.chat.Links;
import static net.md_5.bungee.api.ChatColor.*;
public class PlayerListener implements PluginFacet, Listener {
class SignUpdate implements ServerDoc.StatusUpdate {

View File

@ -1,26 +1,32 @@
package tc.oc.lobby.bukkit.listeners;
import com.google.common.collect.Sets;
import com.google.inject.Inject;
import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import tc.oc.commons.bukkit.teleport.Navigator;
import tc.oc.commons.core.plugin.PluginFacet;
import tc.oc.commons.core.scheduler.Scheduler;
import tc.oc.lobby.bukkit.portals.Portal;
import tc.oc.lobby.bukkit.portals.PortalsConfig;
import java.util.HashSet;
import java.util.Set;
public class PortalsListener implements PluginFacet, Listener {
private final Set<Portal> portals = new HashSet();
private final Set<UUID> connecting = Sets.newConcurrentHashSet();
private PortalsConfig config;
private Scheduler scheduler;
@Inject
PortalsListener(PortalsConfig config) {
PortalsListener(PortalsConfig config, Scheduler scheduler) {
this.config = config;
this.scheduler = scheduler;
}
public void enable() {
@ -34,8 +40,11 @@ public class PortalsListener implements PluginFacet, Listener {
for (Portal portal : portals) {
if (portal.getCuboid().contains(event.getPlayer().getLocation().position())) {
Navigator.Connector connector = portal.getConnector();
if(connector.isConnectable()) {
UUID uuid = event.getPlayer().getUniqueId();
if(connector.isConnectable() && !connecting.contains(uuid)) {
connector.teleport(event.getPlayer());
connecting.add(uuid);
scheduler.createDelayedTask(Duration.ofSeconds(5), () -> connecting.remove(uuid));
break;
}
}

View File

@ -1,10 +1,9 @@
package tc.oc.lobby.bukkit.listeners;
import com.google.common.collect.Maps;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import com.google.common.collect.Maps;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;

View File

@ -1,18 +1,17 @@
package tc.oc.lobby.bukkit.portals;
import org.bukkit.geometry.Cuboid;
import tc.oc.commons.bukkit.config.ExternalConfiguration;
import tc.oc.commons.bukkit.configuration.ConfigUtils;
import tc.oc.commons.bukkit.teleport.Navigator;
import tc.oc.commons.core.logging.Loggers;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.bukkit.geometry.Cuboid;
import tc.oc.commons.bukkit.config.ExternalConfiguration;
import tc.oc.commons.bukkit.configuration.ConfigUtils;
import tc.oc.commons.bukkit.teleport.Navigator;
import tc.oc.commons.core.logging.Loggers;
@Singleton
public class PortalsConfig extends ExternalConfiguration {

View File

@ -15,6 +15,8 @@ import tc.oc.commons.bukkit.tokens.TokenUtil;
import tc.oc.commons.core.commands.Commands;
import tc.oc.commons.core.formatting.StringUtils;
import tc.oc.commons.core.restart.RestartManager;
import tc.oc.parse.ParseException;
import tc.oc.parse.primitive.BooleanParser;
import tc.oc.pgm.Config;
import tc.oc.pgm.PGM;
import tc.oc.pgm.map.PGMMap;
@ -37,8 +39,13 @@ import static tc.oc.commons.bukkit.commands.CommandUtils.newCommandException;
public class PollCommands implements Commands {
private static final String VOTE_FOR = ChatColor.GREEN + "in favor of";
private static final String VOTE_AGAINST = ChatColor.RED + "against";
@Inject
private static RestartManager restartManager;
@Inject
private static BooleanParser booleanParser;
@Command(
aliases = {"poll"},
@ -62,15 +69,14 @@ public class PollCommands implements Commands {
Player voter = tc.oc.commons.bukkit.commands.CommandUtils.senderToPlayer(sender);
Poll currentPoll = PGM.getPollManager().getPoll();
if(currentPoll != null) {
if(args.getString(0).equalsIgnoreCase("yes")) {
currentPoll.voteFor(voter.getName());
sender.sendMessage(ChatColor.GREEN + "You have voted for the current poll.");
} else if (args.getString(0).equalsIgnoreCase("no")) {
currentPoll.voteAgainst(voter.getName());
sender.sendMessage(ChatColor.RED + "You have voted against the current poll.");
} else {
throw new CommandException("Accepted values: yes|no");
boolean vote;
try {
vote = booleanParser.parse(args.getString(0));
} catch (ParseException e) {
throw new CommandException("Please vote yes or no!");
}
currentPoll.vote(vote, voter.getName());
sender.sendMessage(ChatColor.AQUA + "You voted " + (vote ? VOTE_FOR : VOTE_AGAINST) + ChatColor.AQUA + " the current poll.");
} else {
throw new CommandException("There is currently no poll running.");
}
@ -226,7 +232,6 @@ public class PollCommands implements Commands {
}
pollManager.startPoll(poll);
Bukkit.getServer().broadcastMessage(Poll.boldAqua + poll.getInitiator() + Poll.normalize + " has started a poll " + poll.getDescriptionMessage());
Bukkit.broadcastMessage(Poll.tutorialMessage());
}
}
}

View File

@ -78,7 +78,7 @@ public class HitboxPlayerFacet implements MatchPlayerFacet {
final Location location = player.getLocation();
final double radius = width / 2;
return Cuboid.between(location.position().minus(radius, 0, radius),
location.position().plus(radius, PLAYER_HEIGHT, radius));
location.position().plus(radius, PLAYER_HEIGHT, radius));
} else {
return player.getBoundingBox();
}
@ -151,9 +151,9 @@ public class HitboxPlayerFacet implements MatchPlayerFacet {
private boolean isAttacker(Player attacker) {
final MatchPlayer mp = match.getPlayer(attacker);
return mp != null &&
mp.canInteract() &&
(mapInfo.friendlyFire ||
!mp.getParty().equals(matchPlayer.getParty()));
mp.canInteract() &&
(mapInfo.friendlyFire ||
!mp.getParty().equals(matchPlayer.getParty()));
}
private void updateFakeLocations(Location c) {

View File

@ -113,7 +113,9 @@ public class DoubleJumpMatchModule extends MatchModule implements Listener {
impulse.setY(0.75 + Math.abs(impulse.getY()) * 0.5);
impulse.multiply(jumper.kit.power / 3f);
event.getPlayer().applyImpulse(impulse, true);
// HACK: Shiny broke the impulse API
// event.getPlayer().applyImpulse(impulse, true);
event.getPlayer().setVelocity(player.getVelocity().plus(impulse));
player.getWorld().playSound(player.getLocation(), Sound.ENTITY_ZOMBIE_INFECT, 0.5f, 1.8f);
}

View File

@ -1,11 +1,16 @@
package tc.oc.pgm.polls;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import tc.oc.commons.core.chat.Components;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.ChatColor;
import org.bukkit.Server;
public abstract class Poll implements Runnable {
protected final Map<String, Boolean> votes = new HashMap<String, Boolean>();
protected final long startTime = System.currentTimeMillis();
@ -22,7 +27,7 @@ public abstract class Poll implements Runnable {
this.pollManager = pollManager;
this.server = server;
this.initiator = initiator;
this.voteFor(initiator);
this.vote(true, initiator);
timeLeftSeconds = 60;
}
@ -83,20 +88,30 @@ public abstract class Poll implements Runnable {
return normalize + "Yes: " + boldAqua + this.getVotesFor() + " " + normalize + "No: " + boldAqua + this.getVotesAgainst();
}
public static String tutorialMessage() {
return normalize + "Use " + boldAqua + "/vote [yes|no]" + normalize + " to vote";
public static BaseComponent tutorialMessage() {
BaseComponent yes = Components.clickEvent(new TextComponent("YES"), ClickEvent.Action.RUN_COMMAND, "/vote yes");
yes = Components.hoverEvent(yes, HoverEvent.Action.SHOW_TEXT, new TextComponent("Vote in favor of the poll."));
yes.setColor(net.md_5.bungee.api.ChatColor.GREEN);
BaseComponent no = Components.clickEvent(new TextComponent("NO"), ClickEvent.Action.RUN_COMMAND, "/vote no");
no = Components.hoverEvent(no, HoverEvent.Action.SHOW_TEXT, new TextComponent("Vote against the poll."));
no.setColor(net.md_5.bungee.api.ChatColor.RED);
return new TextComponent(
Components.color(new TextComponent("Click "), net.md_5.bungee.api.ChatColor.DARK_AQUA),
yes,
Components.color(new TextComponent(" or "), net.md_5.bungee.api.ChatColor.DARK_AQUA),
no,
Components.color(new TextComponent(" to vote!"), net.md_5.bungee.api.ChatColor.DARK_AQUA)
);
}
public boolean hasVoted(String playerName) {
return this.votes.containsKey(playerName);
}
public void voteFor(String playerName) {
this.votes.put(playerName, true);
}
public void voteAgainst(String playerName) {
this.votes.put(playerName, false);
public void vote(boolean yes, String playerName) {
this.votes.put(playerName, yes);
}
@Override
@ -106,6 +121,7 @@ public abstract class Poll implements Runnable {
this.pollManager.endPoll(PollEndReason.Completed);
} else if(timeLeftSeconds % 15 == 0 || (timeLeftSeconds < 15 && timeLeftSeconds % 5 == 0)) {
this.server.broadcastMessage(this.getStatusMessage());
this.server.broadcast(tutorialMessage());
}
this.decrementTimeLeft();
}

View File

@ -1,6 +1,7 @@
package tc.oc.pgm.tokens.gui;
import org.bukkit.ChatColor;
import tc.oc.commons.bukkit.chat.WarningComponent;
import tc.oc.commons.bukkit.gui.buttons.Button;
import tc.oc.commons.bukkit.gui.interfaces.ChestInterface;
import tc.oc.commons.bukkit.tokens.TokenUtil;
@ -8,6 +9,7 @@ import tc.oc.commons.bukkit.util.Constants;
import tc.oc.commons.bukkit.util.ItemCreator;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import tc.oc.pgm.Config;
import tc.oc.pgm.menu.gui.MainMenuInterface;
import java.util.ArrayList;
@ -51,7 +53,11 @@ public class MainTokenMenu extends ChestInterface {
, 15) {
@Override
public void function(Player player) {
player.openInventory(new MutationTokenInterface(player).getInventory());
if (Config.Poll.enabled()) {
player.openInventory(new MutationTokenInterface(player).getInventory());
} else {
player.sendMessage(new WarningComponent("poll.disabled"));
}
}
});

View File

@ -0,0 +1,94 @@
package tc.oc.commons.bukkit.scheduler;
import java.util.function.Predicate;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
public abstract class RepeatingRunnable implements Runnable {
private final Predicate<Integer> condition;
private int taskId = -1;
private int iteration = 0;
public RepeatingRunnable() {
this(dummy -> true);
}
public RepeatingRunnable(Predicate<Integer> condition) {
this.condition = condition;
}
public RepeatingRunnable(final int repeat) {
this(iteration -> iteration < repeat);
}
public final void run() {
try {
if (condition.test(iteration)) {
repeat();
} else {
cancel();
}
} catch (Exception e) {
e.printStackTrace();
}
iteration++;
}
protected abstract void repeat();
protected abstract Plugin plugin();
public synchronized void cancel() throws IllegalStateException {
Bukkit.getScheduler().cancelTask(this.getTaskId());
}
public synchronized int getTaskId() throws IllegalStateException {
int id = this.taskId;
if (id == -1) {
throw new IllegalStateException("Not scheduled yet");
} else {
return id;
}
}
public synchronized BukkitTask runTask(long delay, long period) throws IllegalArgumentException,
IllegalStateException {
this.checkState();
return this.setupId(Bukkit.getScheduler().runTaskTimer(plugin(), this, delay, period));
}
private void checkState() {
if (this.taskId != -1) {
throw new IllegalStateException("Already scheduled as " + this.taskId);
}
}
private BukkitTask setupId(BukkitTask task) {
this.taskId = task.getTaskId();
return task;
}
public synchronized BukkitTask runTaskAsync(long delay, long period) throws IllegalArgumentException,
IllegalStateException {
this.checkState();
return this.setupId(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin(), this, delay,
period));
}
public int getIteration() {
return iteration;
}
@Override
public int hashCode() {
return getTaskId();
}
@Override
public String toString() {
return Integer.toString(getTaskId());
}
}

View File

@ -45,4 +45,89 @@ public class Vectors {
Numbers.parse(components[1], Double.class, true),
Numbers.parse(components[2], Double.class, true));
}
public static final Vector rotateAroundAxisX(Vector v, double rad) {
double y, z, cos, sin;
cos = Math.cos(rad);
sin = Math.sin(rad);
y = v.getY() * cos - v.getZ() * sin;
z = v.getY() * sin + v.getZ() * cos;
return v.setY(y).setZ(z);
}
public static final Vector rotateAroundAxisY(Vector v, double rad) {
double x, z, cos, sin;
cos = Math.cos(rad);
sin = Math.sin(rad);
x = v.getX() * cos + v.getZ() * sin;
z = v.getX() * -sin + v.getZ() * cos;
return v.setX(x).setZ(z);
}
public static final Vector rotateAroundAxisZ(Vector v, double rad) {
double x, y, cos, sin;
cos = Math.cos(rad);
sin = Math.sin(rad);
x = v.getX() * cos - v.getY() * sin;
y = v.getX() * sin + v.getY() * cos;
return v.setX(x).setY(y);
}
public static final Vector rotateVector(Vector v, double radX, double radY, double radZ) {
rotateAroundAxisX(v, radX);
rotateAroundAxisY(v, radY);
rotateAroundAxisZ(v, radZ);
return v;
}
/**
* Rotate a vector about a location using that location's direction
*
* @param v
* @param location
* @return
*/
public static final Vector rotateVector(Vector v, Location location) {
double yaw = Math.toRadians(-1 * (location.getYaw() + 90));
double pitch = Math.toRadians(-location.getPitch());
return rotateVector(v, pitch, yaw);
}
/**
* This handles non-unit vectors, with yaw and pitch instead of X,Y,Z angles.
*
* Thanks to SexyToad!
*
* @param v
* @param pitchRadians
* @param yawRadians
* @return
*/
public static final Vector rotateVector(Vector v, double pitchRadians, double yawRadians) {
double cosYaw = Math.cos(yawRadians);
double cosPitch = Math.cos(pitchRadians);
double sinYaw = Math.sin(yawRadians);
double sinPitch = Math.sin(pitchRadians);
double initialX, initialY, initialZ;
double x, y, z;
// Z_Axis rotation (Pitch)
initialX = v.getX();
initialY = v.getY();
x = initialX * cosPitch - initialY * sinPitch;
y = initialX * sinPitch + initialY * cosPitch;
// Y_Axis rotation (Yaw)
initialZ = v.getZ();
initialX = x;
z = initialZ * cosYaw - initialX * sinYaw;
x = initialZ * sinYaw + initialX * cosYaw;
return v.setX(x).setY(y).setZ(z);
}
public static final double angleToXAxis(Vector vector) {
return Math.atan2(vector.getX(), vector.getY());
}
}

View File

@ -7,6 +7,8 @@ import java.util.Set;
import com.google.common.collect.Sets;
import tc.oc.commons.core.stream.Collectors;
import javax.annotation.Nullable;
public interface Holidays {
ZoneOffset ZONE = ZoneOffset.UTC;
@ -15,13 +17,13 @@ public interface Holidays {
public final String key;
public final MonthDay start;
public final MonthDay end;
@Nullable public final MonthDay end;
Holiday(String key, MonthDay date) {
this(key, date, date);
this(key, date, null);
}
Holiday(String key, MonthDay start, MonthDay end) {
Holiday(String key, MonthDay start, @Nullable MonthDay end) {
this.key = key;
this.start = start;
this.end = end;
@ -29,8 +31,10 @@ public interface Holidays {
public boolean isNow() {
final MonthDay now = MonthDay.now(ZONE);
return !(start.isBefore(end) ? now.isBefore(start) || now.isAfter(end)
: now.isBefore(start) && now.isAfter(end));
if (end != null) {
return !(now.isBefore(start) || now.isAfter(end));
} else
return start.equals(now);
}
}