9
0
mirror of https://github.com/HibiscusMC/HMCCosmetics.git synced 2025-12-31 12:56:39 +00:00

BALLOONS??

This commit is contained in:
MasterOfTheFish
2022-02-26 00:23:33 -05:00
parent ba7327dd54
commit 23bcd56eac
72 changed files with 688 additions and 142 deletions

View File

@@ -11,7 +11,7 @@ import io.github.fisher2911.hmccosmetics.database.DatabaseFactory;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.item.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook;
import io.github.fisher2911.hmccosmetics.listener.ClickListener;
import io.github.fisher2911.hmccosmetics.listener.CosmeticFixListener;

View File

@@ -60,7 +60,7 @@ public class HMCCosmeticsAPI {
if (armorItem == null) {
return null;
}
return new CosmeticItem(new ArmorItem(armorItem));
return new CosmeticItem(armorItem.copy());
}
/**

View File

@@ -6,7 +6,7 @@ import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticsMenu;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.item.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.message.Message;
import io.github.fisher2911.hmccosmetics.message.MessageHandler;
import io.github.fisher2911.hmccosmetics.message.Messages;

View File

@@ -1,8 +1,11 @@
package io.github.fisher2911.hmccosmetics.config;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.util.Vector;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
@ConfigSerializable
@@ -14,6 +17,7 @@ public class CosmeticSettings {
private static final transient String REQUIRE_EMPTY_CHEST_PLATE_PATH = "require-empty-chest-plate";
private static final transient String REQUIRE_EMPTY_PANTS_PATH = "require-empty-pants";
private static final transient String REQUIRE_EMPTY_BOOTS_PATH = "require-empty-boots";
private static final transient String BALLOON_OFFSET = "balloon-offset";
private static final transient String LOOK_DOWN_PITCH_PATH = "look-down-backpack-remove";
private static final String VIEW_DISTANCE_PATH = "view-distance";
@@ -25,6 +29,7 @@ public class CosmeticSettings {
private boolean requireEmptyBoots;
private int lookDownPitch;
private int viewDistance;
private Vector balloonOffset;
public void load(final FileConfiguration config) {
this.requireEmptyHelmet = config.getBoolean(COSMETIC_SETTINGS_PATH + "." + REQUIRE_EMPTY_HELMET_PATH);
@@ -35,6 +40,16 @@ public class CosmeticSettings {
this.lookDownPitch = config.getInt(COSMETIC_SETTINGS_PATH + "." + LOOK_DOWN_PITCH_PATH);
this.viewDistance = config.getInt(COSMETIC_SETTINGS_PATH + "." + VIEW_DISTANCE_PATH);
final var balloonSection = config.getConfigurationSection(COSMETIC_SETTINGS_PATH + "." + BALLOON_OFFSET);
if (balloonSection != null) {
this.balloonOffset = loadVector(balloonSection);
}
}
private Vector loadVector(final ConfigurationSection section) {
return new Vector(section.getDouble("x"), section.getDouble("y"), section.getDouble("z"));
}
public boolean isRequireEmptyHelmet() {
@@ -77,6 +92,10 @@ public class CosmeticSettings {
this.requireEmptyBoots = requireEmptyBoots;
}
public Vector getBalloonOffset() {
return balloonOffset;
}
public int getLookDownPitch() {
return lookDownPitch;
}

View File

@@ -4,6 +4,7 @@ import dev.triumphteam.gui.components.GuiAction;
import dev.triumphteam.gui.guis.GuiItem;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.BalloonItem;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.util.Keys;
import io.github.fisher2911.hmccosmetics.util.StringUtils;
@@ -58,6 +59,7 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
private static final String ACTION = "action";
private static final String ID = "id";
private static final String DYEABLE = "dyeable";
private static final String BALLOON_MODEL_ID = "balloon";
static {
plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
@@ -100,6 +102,7 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
final ConfigurationNode actionNode = source.node(ACTION);
final ConfigurationNode idNode = source.node(ID);
final ConfigurationNode dyeableNode = source.node(DYEABLE);
final ConfigurationNode balloonModelIdNode = source.node(BALLOON_MODEL_ID);
final String materialString = Utils.replaceIfNull(materialNode.getString(), "");
final int amount = amountNode.getInt();
@@ -227,6 +230,20 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
final String permission = permissionNode.getString();
if (cosmeticType == ArmorItem.Type.BALLOON) {
return new BalloonItem(
itemStack,
actions,
Utils.replaceIfNull(idNode.getString(), ""),
lockedLore,
permission,
cosmeticType,
dyeable,
-1,
balloonModelIdNode.getString()
);
}
return new ArmorItem(
itemStack,
actions,
@@ -238,6 +255,8 @@ public class ItemSerializer implements TypeSerializer<GuiItem> {
-1
);
} catch (final IllegalArgumentException exception) {
final GuiItem guiItem = dev.triumphteam.gui.builder.item.ItemBuilder.from(itemStack).asGuiItem();
guiItem.setAction(event -> {

View File

@@ -10,13 +10,13 @@ import io.github.fisher2911.hmccosmetics.database.dao.ArmorItemDAO;
import io.github.fisher2911.hmccosmetics.database.dao.CitizenDAO;
import io.github.fisher2911.hmccosmetics.database.dao.UserDAO;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.item.CitizensHook;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import io.github.fisher2911.hmccosmetics.user.BaseUser;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.NPCUser;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import java.sql.SQLException;
import java.util.List;
@@ -24,35 +24,15 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import io.github.fisher2911.hmccosmetics.user.UserFactory;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
public class Database {
protected final HMCCosmetics plugin;
final Dao<UserDAO, UUID> userDao;
final Dao<CitizenDAO, Integer> citizenDao;
final Dao<ArmorItemDAO, String> armorItemDao;
private final Dao<UserDAO, UUID> userDao;
private final Dao<CitizenDAO, Integer> citizenDao;
private final Dao<ArmorItemDAO, String> armorItemDao;
private final ConnectionSource dataSource;
private final DatabaseType databaseType;
AtomicInteger FAKE_ENTITY_ID = new AtomicInteger(Integer.MAX_VALUE);
String TABLE_NAME = "user";
String PLAYER_UUID_COLUMN = "uuid";
String BACKPACK_COLUMN = "backpack";
String HAT_COLUMN = "hat";
String DYE_COLOR_COLUMN = "dye";
String CREATE_TABLE_STATEMENT =
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
PLAYER_UUID_COLUMN + " CHAR(36), " +
BACKPACK_COLUMN + " CHAR(50), " +
HAT_COLUMN + " CHAR(50), " +
DYE_COLOR_COLUMN + " INT, " +
"UNIQUE (" +
PLAYER_UUID_COLUMN +
"))";
public Database(
final HMCCosmetics plugin,
@@ -64,7 +44,6 @@ public class Database {
this.citizenDao = DaoManager.createDao(this.dataSource, CitizenDAO.class);
this.armorItemDao = DaoManager.createDao(this.dataSource, ArmorItemDAO.class);
this.databaseType = databaseType;
}
public void load() {

View File

@@ -3,7 +3,7 @@ package io.github.fisher2911.hmccosmetics.database;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.User;
import java.io.File;
@@ -12,9 +12,6 @@ import java.nio.file.Path;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -24,8 +21,6 @@ import java.util.function.Consumer;
import org.bukkit.configuration.file.YamlConfiguration;
import javax.swing.text.DateFormatter;
public class DatabaseConverter {
private static final int CURRENT_VERSION = 2;

View File

@@ -46,7 +46,7 @@ public class ArmorItemDAO {
if (armorItem == null) {
return null;
}
final ArmorItem copy = new ArmorItem(armorItem);
final ArmorItem copy = armorItem.copy();
copy.setDye(this.rgbDye);
return copy;
}

View File

@@ -5,11 +5,8 @@ import com.j256.ormlite.table.DatabaseTable;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import io.github.fisher2911.hmccosmetics.user.BaseUser;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.NPCUser;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.jetbrains.annotations.Nullable;
import java.util.List;

View File

@@ -5,9 +5,7 @@ import com.j256.ormlite.table.DatabaseTable;
import io.github.fisher2911.hmccosmetics.cosmetic.CosmeticManager;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import io.github.fisher2911.hmccosmetics.user.BaseUser;
import io.github.fisher2911.hmccosmetics.user.NPCUser;
import io.github.fisher2911.hmccosmetics.user.EntityIds;
import io.github.fisher2911.hmccosmetics.user.User;
import io.github.fisher2911.hmccosmetics.user.Wardrobe;
import org.jetbrains.annotations.Nullable;

View File

@@ -171,7 +171,7 @@ public class ArmorItem extends GuiItem {
this.dye = dye;
}
public ArmorItem(final ArmorItem armorItem) {
protected ArmorItem(final ArmorItem armorItem) {
super(armorItem.getItemStack(), null);
this.id = armorItem.getId();
this.lockedLore = new ArrayList<>();
@@ -188,6 +188,17 @@ public class ArmorItem extends GuiItem {
}
public static ArmorItem empty(final Type type, final String id) {
if (type == Type.BALLOON) {
return new BalloonItem(
new ItemStack(Material.AIR),
id,
new ArrayList<>(),
"",
type,
-1,
""
);
}
return new ArmorItem(
new ItemStack(Material.AIR),
id,
@@ -268,6 +279,9 @@ public class ArmorItem extends GuiItem {
}
public ArmorItem copy() {
if (this instanceof final BalloonItem item) {
return new BalloonItem(item);
}
return new ArmorItem(this);
}
@@ -281,6 +295,7 @@ public class ArmorItem extends GuiItem {
HAT(EquipmentSlot.HEAD),
BACKPACK(null),
BALLOON(null),
OFF_HAND(EquipmentSlot.OFF_HAND),
CHEST_PLATE(EquipmentSlot.CHEST),
PANTS(EquipmentSlot.LEGS),

View File

@@ -0,0 +1,82 @@
package io.github.fisher2911.hmccosmetics.gui;
import dev.triumphteam.gui.components.GuiAction;
import io.github.fisher2911.hmccosmetics.config.CosmeticGuiAction;
import org.apache.logging.log4j.util.Strings;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class BalloonItem extends ArmorItem {
private final String modelId;
public BalloonItem(final BalloonItem item) {
this(
item.getItemStack(),
item.getActions(),
item.getId(),
item.getLockedLore(),
item.getPermission(),
item.getType(),
item.getDye(),
item.getModelId()
);
}
public BalloonItem(final @NotNull ItemStack itemStack, final List<CosmeticGuiAction> actions, final String id, final List<String> lockedLore, final String permission, final Type type, final int dye, final String modelId) {
super(itemStack, actions, id, lockedLore, permission, type, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull ItemStack itemStack, final String id, final List<String> lockedLore, final String permission, final Type type, final int dye, final String modelId) {
super(itemStack, id, lockedLore, permission, type, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull Material material, final String id, final List<String> lockedLore, final String permission, final Type type, final int dye, final String modelId) {
super(material, id, lockedLore, permission, type, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull Material material, final List<CosmeticGuiAction> actions, final String id, final List<String> lockedLore, final String permission, final Type type, final int dye, final String modelId) {
super(material, actions, id, lockedLore, permission, type, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull ItemStack itemStack, final List<CosmeticGuiAction> actions, final String id, final List<String> lockedLore, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
super(itemStack, actions, id, lockedLore, permission, type, dyeable, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull ItemStack itemStack, final String id, final List<String> lockedLore, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
super(itemStack, id, lockedLore, permission, type, dyeable, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull Material material, final String id, final List<String> lockedLore, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
super(material, id, lockedLore, permission, type, dyeable, dye);
this.modelId = modelId;
}
public BalloonItem(final @NotNull Material material, final @Nullable GuiAction<InventoryClickEvent> action, final String id, final List<String> lockedLore, final String permission, final Type type, final boolean dyeable, final int dye, final String modelId) {
super(material, action, id, lockedLore, permission, type, dyeable, dye);
this.modelId = modelId;
}
public BalloonItem(final ArmorItem armorItem, final String modelId) {
super(armorItem);
this.modelId = modelId;
}
public String getModelId() {
if (this.modelId == null) {
return Strings.EMPTY;
}
return this.modelId;
}
}

View File

@@ -182,7 +182,7 @@ public class CosmeticsMenu {
for (final GuiItem guiItem : gui.guiItemMap.values()) {
if (guiItem instanceof final ArmorItem item) {
final ArmorItem copy = new ArmorItem(item);
final ArmorItem copy = item.copy();
copy.setAction(null);
this.cosmeticManager.addArmorItem(copy);
final String perm = copy.getPermission();

View File

@@ -1,4 +1,4 @@
package io.github.fisher2911.hmccosmetics.hook.item;
package io.github.fisher2911.hmccosmetics.hook;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.concurrent.Threads;

View File

@@ -1,7 +1,6 @@
package io.github.fisher2911.hmccosmetics.hook;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.hook.item.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.item.ItemHook;
import io.github.fisher2911.hmccosmetics.hook.item.ItemHooks;
import io.github.fisher2911.hmccosmetics.hook.item.ItemsAdderHook;
@@ -11,7 +10,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import io.github.fisher2911.hmccosmetics.hook.item.PAPIExpansion;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginManager;
@@ -29,6 +27,7 @@ public class HookManager {
private final ItemHooks itemHooks;
private final PAPIHook papiHook;
private final CitizensHook citizensHook;
private final ModelEngineHook modelEngineHook;
private final Set<Class<? extends Hook>> registeredHooks;
private final Set<Listener> listeners;
@@ -48,6 +47,7 @@ public class HookManager {
final OraxenHook oraxenHook = new OraxenHook();
final ItemsAdderHook itemsAdderHook = new ItemsAdderHook();
final CitizensHook citizensHook = new CitizensHook(this.plugin);
final ModelEngineHook modelEngineHook = new ModelEngineHook();
if (pluginManager.getPlugin("Oraxen") != null) {
itemHookMap.put(oraxenHook.getIdentifier(), oraxenHook);
}
@@ -62,6 +62,12 @@ public class HookManager {
} else {
this.citizensHook = null;
}
if (pluginManager.getPlugin("ModelEngine") != null) {
this.registerHook(modelEngineHook.getClass());
this.modelEngineHook = modelEngineHook;
} else {
this.modelEngineHook = null;
}
this.itemHooks = new ItemHooks(itemHookMap);
itemHookMap.values().forEach(hook -> this.registerHook(hook.getClass()));
@@ -102,6 +108,11 @@ public class HookManager {
return this.citizensHook;
}
@Nullable
public ModelEngineHook getModelEngineHook() {
return modelEngineHook;
}
public ItemHooks getItemHooks() {
return itemHooks;
}

View File

@@ -0,0 +1,62 @@
package io.github.fisher2911.hmccosmetics.hook;
import com.ticxo.modelengine.api.ModelEngineAPI;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import com.ticxo.modelengine.api.model.base.BaseEntity;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.UUID;
public class ModelEngineHook implements Hook {
private static final String ID = "model-engine";
public void spawnModel(final String id, final BaseEntity<?> entity) {
if (ModelEngineAPI.getModeledEntity(entity.getUniqueId()) != null) return;
final ActiveModel model = ModelEngineAPI.createActiveModel(id);
ModeledEntity modeledEntity = ModelEngineAPI.api.getModelManager().createModeledEntity(entity);
modeledEntity.addActiveModel(model);
}
public void addPlayerToModel(final Player player, final String id, final BaseEntity<?> entity) {
final ModeledEntity model = ModelEngineAPI.getModeledEntity(entity.getUniqueId());
if (model == null) {
this.spawnModel(id, entity);
return;
}
if (model.getPlayerInRange().contains(player)) return;
model.addPlayerAsync(player);
}
public void removePlayerFromModel(final Player player, final UUID uuid) {
final ModeledEntity model = ModelEngineAPI.getModeledEntity(uuid);
if (model == null) return;
model.removePlayerAsync(player);
}
public void remove(final UUID uuid) {
final ModeledEntity entity = ModelEngineAPI.getModeledEntity(uuid);
if (entity == null) return;
for (final Player player : entity.getPlayerInRange()) {
entity.removePlayer(player);
}
entity.getEntity().remove();
ModelEngineAPI.api.getModelManager().removeModeledEntity(uuid);
}
@Override
public String getId() {
return ID;
}
}

View File

@@ -1,4 +1,4 @@
package io.github.fisher2911.hmccosmetics.hook.item;
package io.github.fisher2911.hmccosmetics.hook;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.api.CosmeticItem;

View File

@@ -0,0 +1,258 @@
package io.github.fisher2911.hmccosmetics.hook.entity;
import com.ticxo.modelengine.api.model.ActiveModel;
import com.ticxo.modelengine.api.model.ModeledEntity;
import com.ticxo.modelengine.api.model.base.BaseEntity;
import com.ticxo.modelengine.api.model.base.EntityData;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class BalloonEntity implements BaseEntity<BalloonEntity> {
private final UUID uuid;
private final int entityId;
private Vector velocity = new Vector(0, 0, 0);
private Location location;
private boolean alive;
public BalloonEntity(final UUID uuid, final int entityId, final Vector velocity, final Location location, final boolean alive) {
this.uuid = uuid;
this.entityId = entityId;
this.velocity = velocity;
this.location = location;
this.alive = alive;
}
public BalloonEntity(final UUID uuid, final int entityId) {
this.uuid = uuid;
this.entityId = entityId;
this.alive = true;
}
public UUID getUuid() {
return uuid;
}
public void setVelocity(final Vector velocity) {
this.velocity = velocity;
}
public void setLocation(final Location location) {
this.location = location;
}
public void setAlive(final boolean alive) {
this.alive = alive;
}
public boolean isAlive() {
return alive;
}
public EntityData getEntityData() {
return entityData;
}
@Override
public BalloonEntity getBase() {
return this;
}
@Override
public Location getLocation() {
return this.location;
}
@Override
public Vector getVelocity() {
return velocity;
}
@Override
public boolean isOnGround() {
return false;
}
@Override
public World getWorld() {
return this.location.getWorld();
}
@Override
public List<Entity> getNearbyEntities(final double v, final double v1, final double v2) {
return Collections.emptyList();
}
@Override
public int getEntityId() {
return -1;
}
@Override
public void remove() {
this.alive = false;
}
@Override
public boolean isCustomNameVisible() {
return false;
}
@Override
public boolean isDead() {
return !this.alive;
}
@Override
public UUID getUniqueId() {
return this.uuid;
}
@Override
public EntityType getType() {
return EntityType.PIG;
}
@Override
public boolean isInvulnerable() {
return true;
}
@Override
public boolean hasGravity() {
return false;
}
@Override
public void setGravity(final boolean flag) {
}
@Override
public double getHealth() {
return 1;
}
@Override
public double getMaxHealth() {
return 1;
}
@Override
public String getCustomName() {
return null;
}
@Override
public void setCustomName(final String s) {
}
@Override
public double getMovementSpeed() {
return 0;
}
@Override
public ItemStack getItemInMainHand() {
return null;
}
@Override
public ItemStack getItemInOffHand() {
return null;
}
@Override
public boolean isLivingEntity() {
return false;
}
@Override
public void addPotionEffect(final PotionEffect potion) {
}
@Override
public void removePotionEffect(final PotionEffectType potion) {
}
@Override
public void setEntitySize(final float width, final float height, final float eye) {
}
@Override
public void sendDespawnPacket(final ModeledEntity modeledEntity) {
}
@Override
public void sendSpawnPacket(final ModeledEntity modeledEntity) {
}
@Override
public double getLastX() {
return this.location.getX();
}
@Override
public double getLastY() {
return this.location.getY();
}
@Override
public double getLastZ() {
return this.location.getZ();
}
@Override
public double getWantedX() {
return this.location.getX();
}
@Override
public double getWantedY() {
return this.location.getY();
}
@Override
public double getWantedZ() {
return this.location.getZ();
}
@Override
public void saveModelList(final Map<String, ActiveModel> models) {
}
@Override
public void saveModelInfo(final ModeledEntity model) {
}
@Override
public List<String> getModelList() {
return Collections.emptyList();
}
final EntityData entityData = new EntityData();
@Override
public EntityData loadModelInfo() {
return this.entityData;
}
}

View File

@@ -1,6 +1,8 @@
package io.github.fisher2911.hmccosmetics.inventory;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import org.bukkit.Bukkit;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;

View File

@@ -54,6 +54,8 @@ public class JoinListener implements Listener {
optionalUser.ifPresent(user -> {
final Wardrobe wardrobe = user.getWardrobe();
user.despawnAttached();
if (wardrobe.isActive()) {
Bukkit.getScheduler().runTaskAsynchronously(
this.plugin,

View File

@@ -35,6 +35,10 @@ public class Messages {
new Message("set-boots", "Set boots");
public static final Message REMOVED_BOOTS =
new Message("removed-boots", "Removed boots");
public static final Message SET_BALLOON =
new Message("set-balloon", "Set balloon");
public static final Message REMOVED_BALLOON =
new Message("removed-balloon", "Removed balloon");
public static final Message SET_DYE_COLOR =
new Message("set-dye-color", "Set dye color of " + Placeholder.ITEM);
public static final Message MUST_BE_PLAYER =
@@ -110,6 +114,10 @@ public class Messages {
"set-other-boots", ChatColor.GREEN + "You have set the boots of " +
Placeholder.PLAYER + " to " + Placeholder.TYPE + "."
);
public static final Message SET_OTHER_BALLOON = new Message(
"set-other-balloon", ChatColor.GREEN + "You have set the balloon of " +
Placeholder.PLAYER + " to " + Placeholder.TYPE + "."
);
public static Message getSetMessage(final ArmorItem.Type type) {
return switch (type) {
@@ -119,6 +127,7 @@ public class Messages {
case CHEST_PLATE -> Messages.SET_CHEST_PLATE;
case PANTS -> Messages.SET_PANTS;
case BOOTS -> Messages.SET_BOOTS;
case BALLOON -> Messages.SET_BALLOON;
};
}
@@ -130,6 +139,7 @@ public class Messages {
case CHEST_PLATE -> Messages.REMOVED_CHEST_PLATE;
case PANTS -> Messages.REMOVED_PANTS;
case BOOTS -> Messages.REMOVED_BOOTS;
case BALLOON -> Messages.REMOVED_BALLOON;
};
}
@@ -141,6 +151,7 @@ public class Messages {
case CHEST_PLATE -> Messages.SET_OTHER_CHEST_PLATE;
case PANTS -> Messages.SET_OTHER_PANTS;
case BOOTS -> Messages.SET_OTHER_BOOTS;
case BALLOON -> Messages.REMOVED_BALLOON;
};
}

View File

@@ -7,6 +7,7 @@ import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.MinecraftKey;
import com.comphenix.protocol.wrappers.Pair;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import io.github.fisher2911.nms.ArmorStandPackets;
import io.github.fisher2911.nms.ArmorStandPackets_1_16_R3;
import io.github.fisher2911.nms.ArmorStandPackets_1_17_R1;
@@ -96,7 +97,28 @@ public class PacketManager {
return packet;
}
public static PacketContainer getLeashPacket(final int entityId, final int balloonId) {
public static PacketContainer getInvisibilityPacket(final int entityId) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
packet.getIntegers().write(0, entityId);
WrappedDataWatcher metaData = new WrappedDataWatcher();
final WrappedDataWatcher.Serializer byteSerializer = WrappedDataWatcher.Registry.get(Byte.class);
metaData.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(0, byteSerializer), (byte) (0x20));
packet.getWatchableCollectionModifier().write(0, metaData.getWatchableObjects());
return packet;
}
public static PacketContainer getTeleportPacket(final int entityId, final Location location) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_TELEPORT);
packet.getIntegers().write(0, entityId);
packet.getDoubles().write(0, location.getX()).write(1, location.getY()).write(2, location.getZ());
return packet;
}
public static PacketContainer getLeashPacket(final int balloonId, final int entityId) {
final PacketContainer packet = new PacketContainer(PacketType.Play.Server.ATTACH_ENTITY);
packet.getIntegers().write(0, balloonId).write(1, entityId);
return packet;

View File

@@ -3,15 +3,20 @@ package io.github.fisher2911.hmccosmetics.user;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.Pair;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.CosmeticSettings;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.BalloonItem;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.ModelEngineHook;
import io.github.fisher2911.hmccosmetics.hook.entity.BalloonEntity;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -26,22 +31,24 @@ import java.util.UUID;
public abstract class BaseUser<T> {
private final HMCCosmetics plugin;
protected final T id;
protected final EntityIds entityIds;
protected final BalloonEntity balloon;
protected final PlayerArmor playerArmor;
protected ArmorItem lastSetItem = ArmorItem.empty(ArmorItem.Type.HAT);
protected boolean hasArmorStand;
protected boolean hasBallon;
// List of players that are currently viewing the armor stand
protected final Set<UUID> viewing = new HashSet<>();
protected final Set<UUID> viewingArmorStand = new HashSet<>();
protected final Set<UUID> viewingBalloon = new HashSet<>();
public BaseUser(final T id, final PlayerArmor playerArmor, final EntityIds entityIds) {
this.id = id;
this.entityIds = entityIds;
this.playerArmor = playerArmor;
this.plugin = HMCCosmetics.getPlugin(HMCCosmetics.class);
this.balloon = new BalloonEntity(UUID.randomUUID(), -1);
}
@Nullable
@@ -89,76 +96,111 @@ public abstract class BaseUser<T> {
this.updateOutsideCosmetics(other, location, settings);
}
private void despawnBalloon(final Player other) {
final PacketContainer removePacket = PacketManager.getEntityDestroyPacket(this.getBalloonId());
PacketManager.sendPacket(other, removePacket);
protected void despawnBalloon() {
final HookManager hookManager = HookManager.getInstance();
if (!hookManager.isEnabled(ModelEngineHook.class)) return;
hookManager.getModelEngineHook().remove(this.balloon.getUniqueId());
PacketManager.sendPacketToOnline(PacketManager.getEntityDestroyPacket(this.getBalloonId()));
this.viewingBalloon.clear();
}
protected void despawnBalloon(final Player other) {
final HookManager hookManager = HookManager.getInstance();
if (!hookManager.isEnabled(ModelEngineHook.class)) return;
hookManager.getModelEngineHook().removePlayerFromModel(other, this.balloon.getUniqueId());
PacketManager.sendPacket(other, PacketManager.getEntityDestroyPacket(this.getBalloonId()));
this.viewingBalloon.remove(other.getUniqueId());
if (this.viewingBalloon.isEmpty()) {
this.despawnBalloon();
}
}
private void spawnBalloon(final Player other, final Location location, final CosmeticSettings settings) {
final Location actual = location.add(0, 5, 0);
final PacketContainer spawnPacket = PacketManager.getEntitySpawnPacket(actual, this.getBalloonId(), EntityType.PIG);
final PacketContainer leashPacket = PacketManager.getLeashPacket(this.getBalloonId(), this.getEntityId());
PacketManager.sendPacket(other, spawnPacket, leashPacket);
final Location actual = location.clone().add(settings.getBalloonOffset());
final World world = location.getWorld();
if (world == null) return;
final BalloonItem balloonItem = (BalloonItem) this.playerArmor.getItem(ArmorItem.Type.BALLOON);
final String id = balloonItem.getModelId();
final HookManager hookManager = HookManager.getInstance();
if (id.isBlank() || !hookManager.isEnabled(ModelEngineHook.class)) return;
other.sendMessage("Spawned balloon");
this.balloon.setAlive(true);
this.viewingBalloon.add(other.getUniqueId());
this.balloon.setLocation(actual);
final ModelEngineHook hook = hookManager.getModelEngineHook();
hook.spawnModel(id, this.balloon);
hook.addPlayerToModel(other, id, this.balloon);
this.updateBalloon(other, location, settings);
PacketManager.sendPacket(
other,
PacketManager.getEntitySpawnPacket(
actual,
this.getBalloonId(),
EntityType.PIG
),
PacketManager.getInvisibilityPacket(this.getBalloonId()),
PacketManager.getLeashPacket(
this.getBalloonId(),
this.getEntityId()
)
);
}
private void updateBalloon(final CosmeticSettings settings) {
final Location location = this.getLocation();
for (final Player player : Bukkit.getOnlinePlayers()) {
if (!this.hasBallon) {
this.spawnBalloon(player, location, settings);
} else {
this.updateBalloon(player, location, settings);
}
protected void updateBalloon(final Player other, final Location location, final CosmeticSettings settings) {
if (!this.viewingBalloon.contains(other.getUniqueId())) {
this.spawnBalloon(other, location, settings);
return;
}
this.hasBallon = true;
final Location actual = location.clone().add(settings.getBalloonOffset());
this.balloon.setLocation(actual);
PacketManager.sendPacket(
other,
PacketManager.getTeleportPacket(this.getBalloonId(), actual)
);
}
private void updateBalloon(final Player other, final Location location, final CosmeticSettings settings) {
// final PacketContainer spawnPacket = PacketManager.getEntitySpawnPacket(location, this.getBalloonId(), EntityType.PARROT);
// PacketManager.sendPacket(other, spawnPacket, spawnPacket);
}
private void spawnArmorStand(final Player other, final Location location, final CosmeticSettings settings) {
// if (!this.isInViewDistance(this.getLocation(), other.getLocation(), settings) || !shouldShow(other)) return;
private void spawnArmorStand(final Player other, final Location location) {
final PacketContainer packet = PacketManager.getEntitySpawnPacket(location, this.getArmorStandId(), EntityType.ARMOR_STAND);
PacketManager.sendPacket(other, packet);
}
// private void spawnArmorStand(final Settings settings) {
// if (this.hasArmorStand) {
// this.updateArmorStand(settings);
// return;
// }
//
// for (final Player p : Bukkit.getOnlinePlayers()) {
// this.spawnArmorStand(p, this.getLocation(), settings.getCosmeticSettings());
// }
//
// this.hasArmorStand = true;
// }
public void updateOutsideCosmetics(final Player player, final Settings settings) {
this.updateOutsideCosmetics(player, this.getLocation(), settings);
}
public void updateOutsideCosmetics(final Settings settings) {
final Location location = this.getLocation();
if (location == null) return;
for (final Player player : Bukkit.getOnlinePlayers()) {
this.spawnOutsideCosmetics(player, this.getLocation(), settings);
this.spawnOutsideCosmetics(player, location, settings);
}
}
public void updateOutsideCosmetics(final Player other, final Location location, final Settings settings) {
final boolean inViewDistance = this.isInViewDistance(this.getLocation(), other.getLocation(), settings.getCosmeticSettings());
if (!this.viewing.contains(other.getUniqueId())) {
if (!inViewDistance || !shouldShow(other)) return;
this.spawnArmorStand(other, location, settings.getCosmeticSettings());
this.spawnBalloon(other, location, settings.getCosmeticSettings());
} else if (!inViewDistance || !shouldShow(other)) {
final boolean inViewDistance = this.isInViewDistance(location, other.getLocation(), settings.getCosmeticSettings());
final boolean shouldShow = shouldShow(other);
final UUID otherUUID = other.getUniqueId();
if (!this.viewingArmorStand.contains(otherUUID)) {
if (!inViewDistance || !shouldShow) {
if (this.viewingBalloon.contains(otherUUID)) {
this.despawnAttached(other);
}
return;
}
this.spawnArmorStand(other, location);
this.viewingArmorStand.add(otherUUID);
} else if (!inViewDistance || !shouldShow) {
this.despawnAttached(other);
this.despawnBalloon(other);
this.viewing.remove(other.getUniqueId());
if (this.viewingBalloon.contains(otherUUID)) {
this.despawnBalloon(other);
}
return;
}
if (!this.viewingBalloon.contains(otherUUID)) {
this.spawnBalloon(other, location, settings.getCosmeticSettings());
} else if (!this.hasBalloon()) {
this.despawnBalloon(other);
}
final List<Pair<EnumWrappers.ItemSlot, ItemStack>> equipmentList = new ArrayList<>();
final boolean hidden = !this.shouldShow(other);
if (hidden) {
@@ -180,7 +222,6 @@ public abstract class BaseUser<T> {
PacketManager.sendPacket(other, armorPacket, armorStandMetaContainer, rotationPacket, ridingPacket);
if (hidden) return;
this.updateBalloon(other, location, settings.getCosmeticSettings());
final int lookDownPitch = settings.getCosmeticSettings().getLookDownPitch();
@@ -196,6 +237,11 @@ public abstract class BaseUser<T> {
}
}
private boolean hasBalloon() {
return (this.playerArmor.getItem(ArmorItem.Type.BALLOON) instanceof final BalloonItem balloonItem &&
!balloonItem.getModelId().isBlank());
}
public abstract boolean shouldShow(final Player other);
protected boolean isInViewDistance(final Location location, final Location other, final CosmeticSettings settings) {
@@ -209,17 +255,12 @@ public abstract class BaseUser<T> {
public void despawnAttached(final Player other) {
PacketManager.sendPacket(other, PacketManager.getEntityDestroyPacket(this.getArmorStandId()));
this.viewing.remove(other.getUniqueId());
this.hasArmorStand = false;
this.viewingArmorStand.remove(other.getUniqueId());
}
public void despawnAttached() {
PacketManager.sendPacketToOnline(PacketManager.getEntityDestroyPacket(this.getArmorStandId()));
this.hasArmorStand = false;
}
public boolean hasArmorStand() {
return hasArmorStand;
this.viewingArmorStand.clear();
}
public ArmorItem getLastSetItem() {

View File

@@ -1,4 +1,4 @@
package io.github.fisher2911.hmccosmetics.packet;
package io.github.fisher2911.hmccosmetics.user;
import java.util.EnumMap;
import java.util.Map;

View File

@@ -1,9 +1,8 @@
package io.github.fisher2911.hmccosmetics.user;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.item.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import net.citizensnpcs.api.npc.NPC;
import org.bukkit.Location;
import org.bukkit.entity.Entity;

View File

@@ -3,7 +3,6 @@ package io.github.fisher2911.hmccosmetics.user;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.gui.CosmeticGui;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;

View File

@@ -2,9 +2,8 @@ package io.github.fisher2911.hmccosmetics.user;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.hook.HookManager;
import io.github.fisher2911.hmccosmetics.hook.item.CitizensHook;
import io.github.fisher2911.hmccosmetics.hook.CitizensHook;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.Nullable;

View File

@@ -1,11 +1,5 @@
package io.github.fisher2911.hmccosmetics.user;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.Pair;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
@@ -29,7 +23,6 @@ import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -39,6 +32,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class UserManager {
@@ -46,7 +40,7 @@ public class UserManager {
private final Settings settings;
private final MessageHandler messageHandler;
private final Map<UUID, User> userMap = new HashMap<>();
private final Map<UUID, User> userMap = new ConcurrentHashMap<>();
public UserManager(final HMCCosmetics plugin) {
this.plugin = plugin;
@@ -106,7 +100,6 @@ public class UserManager {
public void updateCosmetics(final UUID uuid) {
this.get(uuid).ifPresent(this::updateCosmetics);
}
public void updateCosmetics(final BaseUser user) {

View File

@@ -2,11 +2,9 @@ package io.github.fisher2911.hmccosmetics.user;
import com.comphenix.protocol.events.PacketContainer;
import io.github.fisher2911.hmccosmetics.HMCCosmetics;
import io.github.fisher2911.hmccosmetics.config.Settings;
import io.github.fisher2911.hmccosmetics.config.WardrobeSettings;
import io.github.fisher2911.hmccosmetics.gui.ArmorItem;
import io.github.fisher2911.hmccosmetics.inventory.PlayerArmor;
import io.github.fisher2911.hmccosmetics.packet.EntityIds;
import io.github.fisher2911.hmccosmetics.packet.PacketManager;
import io.github.fisher2911.hmccosmetics.task.SupplierTask;
import io.github.fisher2911.hmccosmetics.task.Task;
@@ -103,7 +101,6 @@ public class Wardrobe extends User {
this.plugin,
() -> {
PacketManager.sendPacket(viewer, playerInfoPacket, playerSpawnPacket);
this.spawnOutsideCosmetics(viewer, this.currentLocation, this.plugin.getSettings());
this.updateOutsideCosmetics(viewer, this.currentLocation, plugin.getSettings());
PacketManager.sendPacket(
viewer,
@@ -119,11 +116,6 @@ public class Wardrobe extends User {
this.startSpinTask(viewer);
}
@Override
public void updateOutsideCosmetics(final Player player, final Settings settings) {
this.updateOutsideCosmetics(player, this.currentLocation, settings);
}
public void despawnFakePlayer(final Player viewer) {
this.active = false;
final WardrobeSettings settings = this.plugin.getSettings().getWardrobeSettings();
@@ -138,6 +130,7 @@ public class Wardrobe extends User {
// PacketManager.getEntityDestroyPacket(this.viewerId)
);
this.despawnAttached();
this.despawnBalloon();
this.showPlayer(this.plugin.getUserManager());
this.spawned = false;
this.cameraLocked = false;
@@ -167,7 +160,10 @@ public class Wardrobe extends User {
PacketManager.sendPacket(player, PacketManager.getLookPacket(this.getEntityId(), location));
this.updateOutsideCosmetics(player, location, this.plugin.getSettings());
location.setYaw(this.getNextYaw(yaw - 30, rotationSpeed));
PacketManager.sendPacket(player, PacketManager.getRotationPacket(this.getEntityId(), location));
PacketManager.sendPacket(
player,
PacketManager.getRotationPacket(this.getEntityId(), location)
);
data.set(this.getNextYaw(yaw, rotationSpeed));
},
() -> !this.spawned || this.currentLocation == null

View File

@@ -13,6 +13,11 @@ cosmetic-settings:
# setting this to lower than the server player view distance should fix the
# bug where players see random backpacks
view-distance: 32
# how the balloon should be positioned relative to the player
balloon-offset:
x: 0.5
y: 3
z: 0.5
wardrobe:
# if true, the wardrobe will be removed when the player is damaged
disable-on-damage: true

View File

@@ -104,6 +104,20 @@ items:
type: BOOTS
permission: ""
id: boots
8:
material: BARRIER
name: "<blue>Balloon"
lore:
- ""
- "<gray>Enabled: <#6D9DC5>%enabled%"
- "<gray>Allowed: <#6D9DC5>%allowed%"
locked-lore:
- "<red>You do not own this item!"
amount: 1
type: BALLOON
permission: ""
id: barrier
balloon: "kindletronjr"
37:
material: PAPER
name: "<#40B7D6>Previous Page"