aboutsummaryrefslogtreecommitdiff
path: root/src/features/cosmetics
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/cosmetics')
-rw-r--r--src/features/cosmetics/cosmetic.js29
-rw-r--r--src/features/cosmetics/cosmetic/dragon/dragonWings.js482
-rw-r--r--src/features/cosmetics/hiddenRequirement.js4
-rw-r--r--src/features/cosmetics/index.js271
-rw-r--r--src/features/cosmetics/metadata.json8
5 files changed, 794 insertions, 0 deletions
diff --git a/src/features/cosmetics/cosmetic.js b/src/features/cosmetics/cosmetic.js
new file mode 100644
index 0000000..878e425
--- /dev/null
+++ b/src/features/cosmetics/cosmetic.js
@@ -0,0 +1,29 @@
+
+class Cosmetic{
+ constructor(player, parent, id){
+
+ if(player.getUUID().toString() === Player.getUUID().toString()) player = Player
+ /**
+ * @type {PlayerMP | Player}
+ */
+ this.player = player
+
+ this.parent = parent
+
+ this.id = id
+
+ this.settings = this.parent.getPlayerCosmeticSettings(this.player, id)
+
+ this.onTick()
+ }
+
+ onRenderEntity(ticks, isInGui){
+ //override
+ }
+
+ onTick(){
+ //override
+ }
+}
+
+export default Cosmetic; \ No newline at end of file
diff --git a/src/features/cosmetics/cosmetic/dragon/dragonWings.js b/src/features/cosmetics/cosmetic/dragon/dragonWings.js
new file mode 100644
index 0000000..944ba78
--- /dev/null
+++ b/src/features/cosmetics/cosmetic/dragon/dragonWings.js
@@ -0,0 +1,482 @@
+import renderLibs from "../../../../../guimanager/renderLibs.js";
+import { f, m } from "../../../../../mappings/mappings.js";
+import ToggleSetting from "../../../settings/settingThings/toggle.js";
+import Cosmetic from "../../cosmetic.js";
+
+const ModelDragon = Java.type("net.minecraft.client.model.ModelDragon")
+
+if (!GlStateManager) {
+ // var GL11 = Java.type("org.lwjgl.opengl.GL11"); //using var so it goes to global scope
+ var GlStateManager = Java.type("net.minecraft.client.renderer.GlStateManager");
+}
+const Essential = Java.type("gg.essential.Essential")
+const EssentialCosmeticSlot = Java.type("gg.essential.mod.cosmetics.CosmeticSlot")
+const EssentialBone = Java.type("gg.essential.model.Bone")
+
+const FACING = Java.type("net.minecraft.block.BlockDirectional").field_176387_N
+let dragon = new ModelDragon(0) //too lazy to make my own model so i just yoink it from modelDragon lmfao
+let textures = new Map()
+let loadingTextures = new Set()
+function loadTexture(id) {
+ new Thread(() => {
+ loadingTextures.add(id)
+ textures.set(id, renderLibs.getImage("http://soopy.dev/api/soopyv2/textures/cosmetic/dragon/" + id + "/img.png", true))
+ }).start()
+}
+loadTexture("classic")
+let wing = getField(dragon, f.wing)
+let wingTip = getField(dragon, f.wingTip)
+
+class DragonWings extends Cosmetic {
+ constructor(player, parent) {
+ super(player, parent, "dragon_wings");
+
+ this.animOffset = Math.random() * 20 * Math.PI
+ this.lastRender = Date.now()
+
+ this.lastFlapSound = this.animOffset
+ this.i = 0
+
+ this.flying = false
+
+ if (!textures.has(this.settings.texture) && !loadingTextures.has(this.settings.texture)) {
+ loadTexture(this.settings.texture)
+ }
+ }
+
+ onRenderEntity(ticks, isInGui) {
+
+ if (this.player.getPlayer()[m.isInvisibleToPlayer](Player.getPlayer()) || this.player.getPlayer()[m.isInvisible]()) {
+ return
+ }
+ if (!textures.has("classic")) return
+
+ let isSelfPlayer = this.player.getUUID().toString() === Player.getUUID().toString()
+ let isInInv = isSelfPlayer && ticks === 1
+ let thirdPersonView = Client.getMinecraft()[f.gameSettings.Minecraft][f.thirdPersonView]
+
+ if (!this.parent.firstPersonVisable.getValue() && thirdPersonView === 0 && isSelfPlayer && !isInInv) return
+
+ // return;
+ // wing.func_78785_a(1)
+
+ let timeSince = (Date.now() - this.lastRender) / 1000
+ this.lastRender = Date.now()
+
+ let rotation = isInInv ? 0 : this.player.getPlayer()[f.prevRenderYawOffset] + (this.player.getPlayer()[f.renderYawOffset] - this.player.getPlayer()[f.prevRenderYawOffset]) * ticks
+ // rotation += entity.field_70761_aq+(entity.field_70761_aq-entity.field_70760_ar)*ticks
+ // console.log(rotation, entity.getEntity().field_70761_aq+(entity.getEntity().field_70761_aq-entity.getEntity().field_70760_ar)*ticks)
+ let horisontalSpeed = Math.hypot((this.player.getPlayer()[f.posX.Entity] - this.player.getPlayer()[f.lastTickPosX]), (this.player.getPlayer()[f.posZ.Entity] - this.player.getPlayer()[f.lastTickPosZ]))
+
+ let verticleSpeed = this.player.getPlayer()[f.posY.Entity] - this.player.getPlayer()[f.lastTickPosY]
+
+ this.animOffset += Math.min(1, horisontalSpeed) * 10 * timeSince + 1 * timeSince
+
+ let flapAmountMultiplyerNoEnd = 1
+ let flapAmountMultiplyer = 1
+
+ let wingEndOffsetThing = 0
+
+ flapAmountMultiplyerNoEnd += Math.min(5, (horisontalSpeed * 5))
+ let flapMainOffsetThing = 0
+
+ let wingBackAmount = 0
+
+ let shouldStandStillWingCurve = true
+
+ if (this.player.getPlayer()[f.hurtResistantTime] > 17) { //damage tick
+ this.animOffset += 25 * timeSince
+ }
+
+
+ // if((this.player === Player &&this.player.getPlayer().field_71075_bZ.field_75100_b) || (this.player !== Player && Math.abs(verticleSpeed)<0.2 && !this.player.getPlayer().field_70122_E)){//playerCapabilities.isFlying
+ if (this.flying) { //flying
+ shouldStandStillWingCurve = false
+ this.animOffset += 5 * timeSince //flap in mid air
+
+ flapAmountMultiplyer *= 1.75 //flap harder
+
+ if (isSelfPlayer && thirdPersonView === 0) {
+ if (!this.parent.lessFirstPersonVisable.getValue()) {
+ flapAmountMultiplyerNoEnd += 0.4
+ flapMainOffsetThing = 0.3
+ }
+ } else {
+ flapAmountMultiplyer *= 1.25
+ flapAmountMultiplyer *= 0.9
+ flapMainOffsetThing = 0.1
+ wingEndOffsetThing += -0.1
+ }
+
+ wingEndOffsetThing += -0.75
+
+ if (verticleSpeed > 0) {
+ this.animOffset += verticleSpeed * 25 * timeSince //flap when flying upwards
+ }
+ } else {
+ if (this.lastFlapSound < this.animOffset - this.animOffset % (Math.PI * 2)) {
+ this.lastFlapSound = this.animOffset - this.animOffset % (Math.PI * 2)
+ }
+ }
+ if (verticleSpeed < -0.5) {
+ wingBackAmount = Math.min(1, (verticleSpeed + 0.5) * -1.5) //lift wings back further ur falling
+
+ this.animOffset += (verticleSpeed + 0.5) * -3 * timeSince
+ }
+
+ GlStateManager[m.pushMatrix](); // pushMatrix
+ Tessellator.colorize(this.settings.color.r, this.settings.color.g, this.settings.color.b);
+
+ if (!isSelfPlayer) {
+ Tessellator.translate(
+ (this.player.getPlayer()[f.lastTickPosX] + (this.player.getPlayer()[f.posX.Entity] - this.player.getPlayer()[f.lastTickPosX]) * ticks) - (Player.getPlayer()[f.lastTickPosX] + (Player.getPlayer()[f.posX.Entity] - Player.getPlayer()[f.lastTickPosX]) * ticks),
+ (this.player.getPlayer()[f.lastTickPosY] + (this.player.getPlayer()[f.posY.Entity] - this.player.getPlayer()[f.lastTickPosY]) * ticks) - (Player.getPlayer()[f.lastTickPosY] + (Player.getPlayer()[f.posY.Entity] - Player.getPlayer()[f.lastTickPosY]) * ticks),
+ (this.player.getPlayer()[f.lastTickPosZ] + (this.player.getPlayer()[f.posZ.Entity] - this.player.getPlayer()[f.lastTickPosZ]) * ticks) - (Player.getPlayer()[f.lastTickPosZ] + (Player.getPlayer()[f.posZ.Entity] - Player.getPlayer()[f.lastTickPosZ]) * ticks))
+ }
+
+ if (textures.get(this.settings.texture || "classic")) {
+ Tessellator.bindTexture(textures.get(this.settings.texture || "classic")) //bind texture
+ } else {
+ Tessellator.bindTexture(textures.get("classic")) //bind default texture (classic)
+ }
+
+ if (this.player.getPlayer()[f.ridingEntity.Entity]) {
+ rotation = this.player.getPlayer()[f.rotationYawHead] + (this.player.getPlayer()[f.rotationYawHead] - this.player.getPlayer()[f.prevRotationYawHead]) * ticks
+ }
+ if (!this.player.getPlayer()[m.isPlayerSleeping]()) { //dont rotate when in bed
+ Tessellator.rotate((180 - rotation), 0, 1, 0)
+
+ Tessellator.translate(0, 1.2, 0.13)
+
+ if (this.player.getPlayer()[m.isSneaking.Entity]()) { //isSneaking
+ Tessellator.translate(0, -0.125, 0)
+ Tessellator.rotate(-20, 1, 0, 0)
+
+ Tessellator.translate(0, 0, 0.1)
+ if (isSelfPlayer && thirdPersonView === 0) { } else {
+ Tessellator.translate(0, -0.125, 0)
+ }
+ }
+
+ if (isSelfPlayer && !isInInv && thirdPersonView === 0) {
+ //Make wings less scuffed when in first person looking down/up
+ Tessellator.translate(0, 0.25, 0.003 * (this.player.getPitch()))
+ }
+ }
+
+
+ //Higher = more elytra like
+ wing[f.rotateAngleY] = 0.25; //rotateAngleY
+
+ let shouldStandingStillWingThing = false
+
+ let changeStandingStillWingThing = 0
+
+ if (horisontalSpeed < 0.01) {
+ if (!(this.flying)) { //not flying
+ let amt = (this.animOffset + Math.PI / 2) % (20 * Math.PI)
+ if (amt < 1 * Math.PI) {
+ this.animOffset += 2 * timeSince * Math.min(1, (amt / (1 * Math.PI)) * 2)
+
+ flapAmountMultiplyer += (amt / (1 * Math.PI)) / 2
+ } else if (amt < 2 * Math.PI) {
+ this.animOffset += 2 * timeSince * Math.min(1, (1 - (amt / (1 * Math.PI) - 1)) * 2)
+
+ flapAmountMultiplyer += (1 - (amt / (1 * Math.PI) - 1)) / 2
+ }
+ }
+ if (this.player.getPlayer()[m.isSneaking.Entity]()) { //isSneaking
+ if (this.player.getPlayer()[f.rotationPitch] > 20) {
+ shouldStandingStillWingThing = true
+ shouldStandStillWingCurve = false
+ changeStandingStillWingThing = Math.max(0, this.player.getPlayer()[f.rotationPitch] / 600)
+ }
+ }
+ }
+
+ if (shouldStandingStillWingThing) {
+ wing[f.rotateAngleY] = 0.25 + (changeStandingStillWingThing) * 3
+ }
+ if (this.player.getPlayer()[m.isPlayerSleeping]()) { //player in bed
+
+ try { //try catch incase no bed at that location
+ let facing = World.getWorld().func_180495_p(this.player.getPlayer()[f.playerLocation])[m.getValue.BlockState$StateImplementation](FACING)[m.getHorizontalIndex]() //0-3 is S-W-N-E
+
+ let rotation = 0
+ switch (facing) {
+ case 0:
+ rotation = 180
+ Tessellator.translate(0, 0, -0.5)
+ break
+ case 1:
+ rotation = 90
+ Tessellator.translate(0.5, 0, 0)
+ break
+ case 2:
+ rotation = 0
+ Tessellator.translate(0, 0, 0.5)
+ break
+ case 3:
+ rotation = 270
+ Tessellator.translate(-0.5, 0, 0)
+ break
+ }
+ // console.log(rotation)
+ // console.log(World.getBlockAt(this.player.getX(), this.player.getY(), this.player.getZ()).getState().func_177229_b(FACING))
+ Tessellator.rotate(rotation, 0, 1, 0)
+ } catch (e) { }
+ Tessellator.translate(0, - this.settings.scale * 25, 0)
+
+ wing[f.rotateAngleX] = 0; //rotateAngleX
+
+ wing[f.rotateAngleZ] = (-0.45 + Math.sin(this.animOffset / 5) * 0.03); //rotateAngleZ
+
+
+ wingTip[f.rotateAngleZ] = -2.5 + Math.sin(this.animOffset / 5) * 0.03
+ } else if (wingBackAmount === 0) {
+ //tilt
+
+
+ let wing_goback_amount = 0.15 / (Math.min(1, horisontalSpeed) * 3 + 0.25)
+ let temp_wing_thing = 1
+
+ if (shouldStandingStillWingThing) {
+ wing_goback_amount /= 1 + (changeStandingStillWingThing) / 50
+ flapAmountMultiplyer /= 1 + (changeStandingStillWingThing) / 50
+
+ temp_wing_thing += changeStandingStillWingThing * 50
+ }
+
+ let wing_tilt_offset = -Math.min(0.8, horisontalSpeed * 3) + 0.3 //When go faster tilt wing back so its in direction of wind
+
+
+ if (shouldStandingStillWingThing) {
+ wing_tilt_offset += (changeStandingStillWingThing) * 4
+ }
+
+ wing[f.rotateAngleX] = 0.85 - Math.cos(this.animOffset) * 0.2 + wing_tilt_offset - (flapAmountMultiplyer - 1) / 3; //rotateAngleX
+
+ let temp_horis_wingthing = 0
+ if (shouldStandingStillWingThing) {
+ temp_horis_wingthing = -(changeStandingStillWingThing) * 0.75
+ }
+
+ wing[f.rotateAngleZ] = (Math.sin(this.animOffset) / temp_wing_thing + 0.125) * wing_goback_amount * (1 + (flapAmountMultiplyer - 1) * 1) * flapAmountMultiplyerNoEnd - 0.4 - wing_tilt_offset / 3 + temp_horis_wingthing + flapMainOffsetThing; //rotateAngleZ
+
+ let standStillCurveThing = shouldStandStillWingCurve ? (2 - flapAmountMultiplyer) * 0.5 : 0
+
+ wingTip[f.rotateAngleZ] = standStillCurveThing - ((Math.sin((this.animOffset + 1.5 + (1 - temp_wing_thing) / 8.5)) / (1 + (temp_wing_thing - 1) / 3) + 0.5)) * 0.75 * (1 + (flapAmountMultiplyer - 1) * 1) / (1 + temp_horis_wingthing) - (1 - flapAmountMultiplyer) * 2 - (1 - temp_wing_thing) / 10 + wingEndOffsetThing; //rotateAngleZ
+ } else {
+ //tilt
+ let wing_tilt_offset = -Math.min(0.8, horisontalSpeed * 3) //When go faster tilt wing back so its in direction of wind
+ wing[f.rotateAngleX] = 0.75 - Math.cos(this.animOffset) * 0.2 + wing_tilt_offset - wingBackAmount / 2; //rotateAngleX
+
+
+ wing[f.rotateAngleZ] = -wingBackAmount; //rotateAngleZ
+
+
+ wingTip[f.rotateAngleZ] = -((Math.sin((this.animOffset)) * 0.5 + 0.3))
+ }
+
+ GlStateManager[m.disableCull]() //disable culling
+
+ let wing_center_dist = ((0 - Math.log(1000 * this.settings.scale + 0.01) - 2) - 100000 * this.settings.scale * this.settings.scale) / 1000
+
+ // GL11.glDepthMask(GL11.GL_FALSE);
+ Tessellator.translate(-wing_center_dist, 0, 0)
+ Tessellator.scale(this.settings.scale, this.settings.scale, this.settings.scale)
+ wing[m.renderWithRotation](1) //render left wing
+
+ Tessellator.translate(2 * wing_center_dist / this.settings.scale, 0, 0)
+ Tessellator.scale(-1, 1, 1)
+ wing[m.renderWithRotation](1) //render right wing
+
+
+ if (this.player.getPlayer()[f.hurtTime] > 0) { //damage tick
+ GlStateManager[m.pushMatrix](); // pushMatrix
+ GlStateManager[m.depthFunc](514);
+ GlStateManager[m.disableTexture2D]();
+ GlStateManager[m.enableBlend]();
+ GlStateManager[m.blendFunc](770, 771);
+ GlStateManager.func_179131_c(1, 0, 0, 0.25); //m.color.glstatemanager.ffff
+
+ Tessellator.scale(-1, 1, 1)
+ Tessellator.translate(-2 * wing_center_dist / this.settings.scale, 0, 0)
+ wing[m.renderWithRotation](1) //render left wing
+
+ Tessellator.translate(2 * wing_center_dist / this.settings.scale, 0, 0)
+ Tessellator.scale(-1, 1, 1)
+ wing[m.renderWithRotation](1) //render right wing
+
+ GlStateManager[m.enableTexture2D]();
+ GlStateManager[m.disableBlend]();
+ GlStateManager[m.depthFunc](515);
+ GlStateManager[m.popMatrix](); // popMatrix
+ }
+ Tessellator.colorize(1, 1, 1)
+ GlStateManager[m.enableCull]() //enable culling
+ GlStateManager[m.popMatrix](); // popMatrix
+ }
+
+ testPlaySound() {
+ if (this.player.getPlayer()[m.isInvisibleToPlayer](Player.getPlayer())) {
+ return
+ }
+ if (!this.parent.ownCosmeticAudio.getValue()) {
+ return
+ }
+
+ if (this.player.getPlayer()[m.isPlayerSleeping]()) return
+
+ let horisontalSpeed = Math.hypot((this.player.getPlayer()[f.posX.Entity] - this.player.getPlayer()[f.lastTickPosX]), (this.player.getPlayer()[f.posZ.Entity] - this.player.getPlayer()[f.lastTickPosZ]))
+
+
+ // if((this.player === Player &&this.player.getPlayer().field_71075_bZ.field_75100_b) || (this.player !== Player && Math.abs(verticleSpeed)<0.2 && !this.player.getPlayer().field_70122_E)){//playerCapabilities.isFlying
+ if (this.flying) { //flying
+
+ if (this.animOffset - this.lastFlapSound > 2 * Math.PI) {
+
+ let dist = Math.hypot((Player.getX() - this.player.getX()), (Player.getY() - this.player.getY()), (Player.getZ() - this.player.getZ())) + 1
+
+ World.playSound("mob.enderdragon.wings", (this.settings.scale * 15) * Math.min(1, 50 / (dist * dist)), 1)
+ this.lastFlapSound = this.animOffset - this.animOffset % (Math.PI * 2)
+ }
+ }
+
+ if (horisontalSpeed < 0.01) {
+ if (!(this.flying)) { //not flying
+ let amt = (this.animOffset + Math.PI / 2) % (20 * Math.PI)
+ if (amt < 1 * Math.PI) {
+ if (amt > 0.65 * Math.PI && (2 * Math.PI + this.animOffset) - this.lastFlapSound > 2 * Math.PI) {
+
+ let dist = Math.hypot((Player.getX() - this.player.getX()), (Player.getY() - this.player.getY()), (Player.getZ() - this.player.getZ())) + 1
+
+ World.playSound("mob.enderdragon.wings", (Math.max(0.005, this.settings.scale - 0.005) * 25) * Math.min(1, 50 / Math.min(1, dist * dist)) / 50, 1 - (Math.max(0.005, this.settings.scale - 0.005) * 25))
+ this.lastFlapSound = 2 * Math.PI + (this.animOffset) - this.animOffset % (Math.PI * 2)
+ }
+ }
+ }
+ }
+ }
+
+ onTick() {
+
+ this.updateIfNotRendering()
+
+ this.testPlaySound()
+
+ }
+
+ removeEssentialCosmetics() {
+ if (!this.player.getPlayer() || !this.player.getPlayer().getCosmeticsState || !this.player.getPlayer().getCosmeticsState() || !this.player.getPlayer().getCosmeticsState().getCosmetics || !this.player.getPlayer().getCosmeticsState().getCosmetics()) return
+ //player.()
+ let wingCosmetic = this.player.getPlayer().getCosmeticsState().getCosmetics().get(EssentialCosmeticSlot.WINGS)
+ if (wingCosmetic !== null) {
+ let cosmetic = this.player.getPlayer().getCosmeticsState().getModels().get(Essential.instance.getConnectionManager().getCosmeticsManager().getCosmetic(wingCosmetic))
+ if (cosmetic) {
+ let model = cosmetic.getModel().getModel()
+
+ let bones = model.getBones(model.getRootBone())
+
+ bones.forEach(b => {
+ setField(b, "showModel", false)
+
+ this.parent.hiddenEssentialCosmetics.push(b)
+ })
+ }
+ } else {
+ let fullBodyCosmetic = this.player.getPlayer().getCosmeticsState().getCosmetics().get(EssentialCosmeticSlot.FULL_BODY)
+ if (fullBodyCosmetic === "DRAGON_ONESIE_2") {
+ let cosmetic = this.player.getPlayer().getCosmeticsState().getModels().get(Essential.instance.getConnectionManager().getCosmeticsManager().getCosmetic(fullBodyCosmetic))
+ if (cosmetic) {
+ let model = cosmetic.getModel().getModel()
+
+ let bones = model.getBones(model.getRootBone())
+
+ bones.forEach(b => {
+ if (b.boxName === "wing_left_1" || b.boxName === "wing_right_1") {
+ setField(b, "showModel", false)
+
+ this.parent.hiddenEssentialCosmetics.push(b)
+ }
+ })
+ }
+ }
+ }
+ }
+
+ updateIfNotRendering() {
+ let verticleSpeed = this.player.getPlayer()[f.posY.Entity] - this.player.getPlayer()[f.lastTickPosY]
+
+ this.flying = (verticleSpeed > -0.2) && !this.player.getPlayer()[f.onGround.Entity]
+
+ let timeSince = (Date.now() - this.lastRender) / 1000
+
+ if (timeSince < 0.020) {
+ return
+ }
+
+ this.lastRender = Date.now()
+
+ let horisontalSpeed = Math.hypot((this.player.getPlayer()[f.posX.Entity] - this.player.getPlayer()[f.lastTickPosX]), (this.player.getPlayer()[f.posZ.Entity] - this.player.getPlayer()[f.lastTickPosZ]))
+
+
+ this.animOffset += Math.min(1, horisontalSpeed) * 10 * timeSince + 1 * timeSince
+
+ if (this.player.getPlayer()[f.hurtResistantTime] > 0) { //damage tick
+ this.animOffset += 5 * timeSince
+ }
+
+
+ // if((this.player === Player &&this.player.getPlayer().field_71075_bZ.field_75100_b) || (this.player !== Player && Math.abs(verticleSpeed)<0.2 && !this.player.getPlayer().field_70122_E)){//playerCapabilities.isFlying
+ if (this.flying) { //flying
+ this.animOffset += 5 * timeSince //flap in mid air
+
+ if (verticleSpeed > 0) {
+ this.animOffset += verticleSpeed * 25 * timeSince //flap when flying upwards
+ }
+ }
+ if (verticleSpeed < -0.5) {
+ this.animOffset += (verticleSpeed + 0.5) * -3 * timeSince
+ }
+
+ if (horisontalSpeed < 0.01) {
+ if (!(this.flying)) { //not flying
+ let amt = (this.animOffset + Math.PI / 2) % (20 * Math.PI)
+ if (amt < 1 * Math.PI) {
+ this.animOffset += 2 * timeSince * Math.min(1, (amt / (1 * Math.PI)) * 2)
+ } else if (amt < 2 * Math.PI) {
+ this.animOffset += 2 * timeSince * Math.min(1, (1 - (amt / (1 * Math.PI) - 1)) * 2)
+ }
+ }
+ }
+ }
+}
+
+export default DragonWings;
+
+
+function getField(e, field) {
+
+ let field2 = e.class.getDeclaredField(field);
+
+ field2.setAccessible(true)
+
+ return field2.get(e)
+}
+
+function setField(e, field, value) {
+
+ let field2 = e.class.getDeclaredField(field);
+
+ field2.setAccessible(true)
+
+ return field2.set(e, value)
+}
+
+let a = 0
+
+register("command", (val) => {
+ a = parseFloat(val)
+ ChatLib.chat("Set a to " + a)
+}).setName("seta", true) \ No newline at end of file
diff --git a/src/features/cosmetics/hiddenRequirement.js b/src/features/cosmetics/hiddenRequirement.js
new file mode 100644
index 0000000..dbc3e06
--- /dev/null
+++ b/src/features/cosmetics/hiddenRequirement.js
@@ -0,0 +1,4 @@
+
+module.exports = {hidden: function(featureManager){
+ return !(featureManager.features.cosmetics?.["class"]?.playerHasACosmeticA || false)
+}} \ No newline at end of file
diff --git a/src/features/cosmetics/index.js b/src/features/cosmetics/index.js
new file mode 100644
index 0000000..f3deece
--- /dev/null
+++ b/src/features/cosmetics/index.js
@@ -0,0 +1,271 @@
+/// <reference types="../../../../CTAutocomplete" />
+/// <reference lib="es2015" />
+import Feature from "../../featureClass/class";
+import DragonWings from "./cosmetic/dragon/dragonWings"
+import Toggle from "../settings/settingThings/toggle"
+import { f } from "../../../mappings/mappings";
+import FakeRequireToggle from "../settings/settingThings/FakeRequireToggle";
+import { fetch } from "../../utils/networkUtils";
+
+class Cosmetics extends Feature {
+ constructor() {
+ super()
+ }
+
+ onEnable() {
+ this.initVariables()
+ this.loadedCosmetics = []
+ this.uuidToCosmetic = {}
+ this.uuidToCosmeticDirect = {}
+
+ this.cosmeticsData = {}
+
+ this.hiddenEssentialCosmetics = []
+
+ this.cosmeticsList = {
+ "dragon_wings": DragonWings
+ }
+
+ this.playerHasACosmeticA = false
+
+ this.firstPersonVisable = new Toggle("Cosmetics visable in first person", "", false, "cosmetics_first_person_visable", this)
+ this.lessFirstPersonVisable = new Toggle("Make cosmetics less visable in first person mode", "", true, "cosmetics_first_person_less_visable", this).requires(this.firstPersonVisable)
+ this.ownCosmeticAudio = new Toggle("Audio for own cosmetics", "", false, "cosmetics_own_audio", this)
+
+ this.dragon_wings_enabled = new Toggle("Dragon Wings Toggle", "", true, "cosmetic_dragon_wings_toggle", this).requires(new FakeRequireToggle(false)).onchange(this, () => {
+ global.soopyV2Server.updateCosmeticsData({
+ cosmetic: "dragon_wings",
+ type: this.dragon_wings_enabled.getValue() ? "enable" : "disable"
+ })
+ })
+
+ this.postRenderEntityTrigger = undefined
+
+ this.loadCosmeticsData()
+
+ this.worldLoad()
+
+ this.registerEvent("tick", this.tick)
+ this.registerEvent("renderWorld", this.renderWorld)
+ this.registerEvent("playerJoined", this.playerJoined)
+ this.registerEvent("playerLeft", this.playerLeft)
+ this.registerEvent("worldLoad", this.worldLoad)
+ this.registerStep(false, 2, this.step)
+ this.registerEvent('gameUnload', () => {
+ if (this.postRenderEntityTrigger) {
+ this.postRenderEntityTrigger.unregister()
+ this.postRenderEntityTrigger = undefined
+ }
+ })
+ // this.registerStep(false, 60*10, ()=>{
+ // new Thread(()=>{this.loadCosmeticsData.call(this)}).start()
+ // })
+ // this.registerEvent("renderEntity", this.renderEntity)
+
+ if (global.soopyV2Server && global.soopyV2Server.userCosmeticPermissions) {
+ this.updateUserCosmeticPermissionSettings()
+ }
+ }
+
+ updateUserCosmeticPermissionSettings() {
+ if (!this.enabled) return
+
+ if (global.soopyV2Server.userCosmeticPermissions === "*" || global.soopyV2Server.userCosmeticPermissions.dragon_wings) {
+ this.dragon_wings_enabled.requiresO.set(true)
+ } else {
+ this.dragon_wings_enabled.requiresO.set(false)
+ }
+ }
+
+ renderWorld(ticks) {
+ for (let i = 0; i < this.loadedCosmetics.length; i++) {
+ this.loadedCosmetics[i].onRenderEntity(ticks, false)
+ }
+ }
+
+ async loadCosmeticsData() {
+ let data = await fetch("http://soopy.dev/api/soopyv2/cosmetics.json").json()
+
+ this.cosmeticsData = data
+ this.playerHasACosmeticA = !!data[Player.getUUID().toString().replace(/-/g, "")]
+ if (this.playerHasACosmeticA && !this.postRenderEntityTrigger) {
+ // this.registerEvent("postRenderEntity", this.renderEntity)
+ this.postRenderEntityTrigger = register("postRenderEntity", (entity, pos, ticks, event) => {
+ if (ticks !== 1) return
+ if (this.uuidToCosmeticDirect[entity.getUUID().toString().replace(/-/g, "")]) {
+ let cosmetics = Object.values(this.uuidToCosmeticDirect[entity.getUUID().toString().replace(/-/g, "")])
+ for (let cosmetic of cosmetics) {
+ cosmetic.onRenderEntity(ticks, true)
+ }
+ }
+ })
+ }
+
+ this.scanForNewCosmetics()
+ }
+
+ setUserCosmeticsInformation(uuid, cosmetics) {
+ if (!this.enabled) return
+ uuid = uuid.replace(/-/g, "")
+
+ this.loadedCosmetics = this.loadedCosmetics.filter(cosmetic => {
+ if (cosmetic.player.getUUID().toString().replace(/-/g, "") === uuid) {
+ return false
+ }
+ return true
+ })
+ Object.keys(this.uuidToCosmetic).forEach(cosmeticName => {
+ delete this.uuidToCosmetic[cosmeticName][uuid]
+ })
+
+ delete this.uuidToCosmeticDirect[uuid]
+
+ if (!cosmetics) {
+ delete this.cosmeticsData[uuid]
+ return
+ }
+ this.cosmeticsData[uuid] = cosmetics
+
+ this.scanForNewCosmetics()
+ }
+
+ step() {
+ this.scanForNewCosmetics()
+
+ this.filterUnloadedCosmetics(false)
+
+ this.restoreEssentialCosmetics()
+
+ this.loadedCosmetics.forEach(c => {
+ c.removeEssentialCosmetics()
+ })
+ }
+ scanForNewCosmetics() {
+ this.loadCosmeticsForPlayer(Player)
+ World.getAllPlayers().forEach(p => {
+ if (p.getUUID().toString().replace(/-/g, "") === Player.getUUID().toString().replace(/-/g, "")) return
+ this.loadCosmeticsForPlayer(p)
+ })
+ }
+
+ loadCosmeticsForPlayer(player) {
+ Object.keys(this.cosmeticsList).forEach(cosmeticName => {
+ if (!this.uuidToCosmetic[cosmeticName]) this.uuidToCosmetic[cosmeticName] = {}
+
+ if (this.uuidToCosmetic[cosmeticName][player.getUUID().toString().replace(/-/g, "")]) return
+
+ if (this.shouldPlayerHaveCosmetic(player, cosmeticName)) {
+ let cosmetic = new (this.cosmeticsList[cosmeticName])(player, this)
+ this.loadedCosmetics.push(cosmetic)
+ this.uuidToCosmetic[cosmeticName][player.getUUID().toString().replace(/-/g, "")] = cosmetic
+
+ if (!this.uuidToCosmeticDirect[player.getUUID.toString()]) this.uuidToCosmeticDirect[player.getUUID().toString().replace(/-/g, "")] = {}
+ this.uuidToCosmeticDirect[player.getUUID().toString().replace(/-/g, "")][cosmeticName] = cosmetic
+ }
+ })
+ }
+
+ worldLoad() {
+ this.loadedCosmetics = []
+ this.uuidToCosmetic = {}
+ this.uuidToCosmeticDirect = {}
+
+ this.loadCosmeticsForPlayer(Player)
+ this.scanForNewCosmetics()
+ }
+
+ playerJoined(player) {
+ if (player.getUUID().toString().replace(/-/g, "") === Player.getUUID().toString().replace(/-/g, "")) return
+
+ this.loadCosmeticsForPlayer(player)
+ }
+
+ playerLeft(playerName) {
+ this.loadedCosmetics = this.loadedCosmetics.filter(cosmetic => {
+ if (cosmetic.player.getUUID().toString().replace(/-/g, "") === Player.getUUID().toString().replace(/-/g, "")) return true
+ if (cosmetic.player.getName() === playerName) {
+ this.uuidToCosmetic[cosmetic.id][cosmetic.player.getUUID().toString().replace(/-/g, "")] = undefined
+
+ this.uuidToCosmeticDirect[cosmetic.player.getUUID().toString().replace(/-/g, "")] = undefined
+ return false
+ }
+ return true
+ })
+ }
+
+ shouldPlayerHaveCosmetic(player, cosmetic) {
+ if (this.getPlayerCosmeticSettings(player, cosmetic)) {
+ if (!this.getPlayerCosmeticSettings(player, cosmetic).enabled) return false
+ return true
+ }
+ return false
+ }
+ getPlayerCosmeticSettings(player, cosmetic) {
+ return this.cosmeticsData[player.getUUID().toString().replace(/-/g, "")]?.[cosmetic]
+ }
+
+ filterUnloadedCosmetics(tick = false) {
+ this.loadedCosmetics = this.loadedCosmetics.filter(cosmetic => {
+ if (tick) cosmetic.onTick()
+ if (cosmetic.player.getUUID().toString().replace(/-/g, "") === Player.getUUID().toString().replace(/-/g, "")) return true
+ if (cosmetic.player.getPlayer()[f.isDead]) { //filter out players that are no longer loaded
+ this.uuidToCosmetic[cosmetic.id][cosmetic.player.getUUID().toString().replace(/-/g, "")] = undefined
+
+ this.uuidToCosmeticDirect[cosmetic.player.getUUID().toString().replace(/-/g, "")] = undefined
+ return false
+ }
+ return true
+ })
+ }
+
+ tick() {
+ for (let cosmetic of this.loadedCosmetics) {
+ cosmetic.onTick()
+ }
+ }
+
+ restoreEssentialCosmetics() {
+ this.hiddenEssentialCosmetics.forEach(cosmetic => {
+ setField(cosmetic, "showModel", true)
+ })
+ this.hiddenEssentialCosmetics = []
+ }
+
+ initVariables() {
+ this.loadedCosmetics = undefined
+ this.uuidToCosmetic = undefined
+ this.uuidToCosmeticDirect = {}
+ this.playerHasACosmeticA = undefined
+ this.cosmeticsData = undefined
+ this.hiddenEssentialCosmetics = undefined
+ this.hiddenEssentialCosmetics = undefined
+ this.cosmeticsList = undefined
+ }
+
+ onDisable() {
+
+ if (this.postRenderEntityTrigger) {
+ this.postRenderEntityTrigger.unregister()
+ this.postRenderEntityTrigger = undefined
+ }
+
+ this.restoreEssentialCosmetics()
+
+ this.initVariables()
+ }
+}
+
+let instance = new Cosmetics()
+
+module.exports = {
+ class: instance
+}
+
+function setField(e, field, value) {
+
+ let field2 = e.class.getDeclaredField(field);
+
+ field2.setAccessible(true)
+
+ return field2.set(e, value)
+} \ No newline at end of file
diff --git a/src/features/cosmetics/metadata.json b/src/features/cosmetics/metadata.json
new file mode 100644
index 0000000..f198cff
--- /dev/null
+++ b/src/features/cosmetics/metadata.json
@@ -0,0 +1,8 @@
+{
+ "name": "Cosmetics",
+ "description": "Cosmetics settings",
+ "isTogglable": false,
+ "defaultEnabled": true,
+ "isHidden": "hiddenRequirement.js",
+ "sortA": 1
+} \ No newline at end of file