From b20cf29888fd94ad02520a2f093b961ff8487e9c Mon Sep 17 00:00:00 2001 From: somehussar <148253652+somehussar@users.noreply.github.com> Date: Sun, 20 Oct 2024 22:57:31 +0200 Subject: [PATCH 01/10] 1.0.2 --- build.gradle | 2 +- gradle.properties | 2 +- src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 74661c1fb..443615511 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id 'com.gtnewhorizons.gtnhconvention' } -version = "1.0.2-devbranch-URGENT" +version = "1.0.2" group= "kamkeel.npcdbc" tasks.runServer { setWorkingDir(file("run/server")) } diff --git a/gradle.properties b/gradle.properties index 385df5e9e..7c540f721 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ modName = CustomNPC-Plus-DBC-Addon # This is a case-sensitive string to identify your mod. Convention is to use lower case. modId = npcdbc modGroup = kamkeel.npcdbc -modVersion = 1.0.2-devbranch-URGENT +modVersion = 1.0.2 gtnh.modules.codeStyle=true gtnh.modules.gitVersion=false diff --git a/src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java b/src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java index 2e1d6f517..2a9d0cbec 100644 --- a/src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java +++ b/src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java @@ -19,7 +19,7 @@ public class CustomNpcPlusDBC { public static final String name = "CustomNPC+ DBC Addon"; - public static final String version = "1.0.2-devbranch-URGENT"; + public static final String version = "1.0.2"; public static final String ID = "npcdbc"; @SidedProxy(clientSide = "kamkeel.npcdbc.client.ClientProxy", serverSide = "kamkeel.npcdbc.CommonProxy") public static CommonProxy proxy; From 45870ed340e950df27a836e0c98f61cf64f06ac4 Mon Sep 17 00:00:00 2001 From: Kam Date: Thu, 29 May 2025 18:38:59 -0400 Subject: [PATCH 02/10] Fix Index of DBC Addon Effects --- src/main/java/kamkeel/npcdbc/data/effects/AddonEffect.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/kamkeel/npcdbc/data/effects/AddonEffect.java b/src/main/java/kamkeel/npcdbc/data/effects/AddonEffect.java index 2d524d002..19170524c 100644 --- a/src/main/java/kamkeel/npcdbc/data/effects/AddonEffect.java +++ b/src/main/java/kamkeel/npcdbc/data/effects/AddonEffect.java @@ -10,6 +10,7 @@ public class AddonEffect extends CustomEffect { public AddonEffect() { icon = CustomNpcPlusDBC.ID + ":textures/gui/icons.png"; + index = 1; } public int getWidth() { From 243ef556bb2eac00c3c003c95c5dabcbf34d80de Mon Sep 17 00:00:00 2001 From: Kam Date: Mon, 2 Jun 2025 19:16:45 -0400 Subject: [PATCH 03/10] Update MixinJRMCoreEH.java --- .../kamkeel/npcdbc/mixins/late/impl/dbc/MixinJRMCoreEH.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/kamkeel/npcdbc/mixins/late/impl/dbc/MixinJRMCoreEH.java b/src/main/java/kamkeel/npcdbc/mixins/late/impl/dbc/MixinJRMCoreEH.java index 7950a8bfa..16bf9b5be 100644 --- a/src/main/java/kamkeel/npcdbc/mixins/late/impl/dbc/MixinJRMCoreEH.java +++ b/src/main/java/kamkeel/npcdbc/mixins/late/impl/dbc/MixinJRMCoreEH.java @@ -55,7 +55,7 @@ public void dbcAttackFromPlayer(LivingHurtEvent event, CallbackInfo ci, @Local(n return; } - damageCalc.damage = (int) damagedEvent.damage; + damageCalc.damage = damagedEvent.damage; damageCalc.stamina = damagedEvent.getStaminaReduced(); damageCalc.ki = damagedEvent.getKiReduced(); damageCalc.willKo = damagedEvent.willKo(); @@ -72,7 +72,7 @@ public void dbcAttackFromNonPlayer(LivingHurtEvent event, CallbackInfo ci, @Loca return; } - damageCalc.damage = (int) damagedEvent.damage; + damageCalc.damage = damagedEvent.damage; damageCalc.stamina = damagedEvent.getStaminaReduced(); damageCalc.ki = damagedEvent.getKiReduced(); damageCalc.willKo = damagedEvent.willKo(); From 92bc5132b17635109f5fce780fff96d29d726e77 Mon Sep 17 00:00:00 2001 From: ten <123556224+kaixiten@users.noreply.github.com> Date: Wed, 4 Jun 2025 01:11:25 +0800 Subject: [PATCH 04/10] Update zh_CN.lang Updated translations --- .../resources/assets/npcdbc/lang/zh_CN.lang | 64 ++++++++++++++++--- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/src/main/resources/assets/npcdbc/lang/zh_CN.lang b/src/main/resources/assets/npcdbc/lang/zh_CN.lang index 3b228c1f1..9c26df117 100644 --- a/src/main/resources/assets/npcdbc/lang/zh_CN.lang +++ b/src/main/resources/assets/npcdbc/lang/zh_CN.lang @@ -12,8 +12,10 @@ dbc.clientsettings.aura.firstPersonOpacity=第一人称3D气焰不透明度: %s% global.customforms=形态 global.customauras=气焰 global.customoutlines=气轮廓 +global.customeffects=状态 stats.dbcsettings=DBC 设置 +inventory.extras=气焰 gui.clone=复制 @@ -28,9 +30,21 @@ stats.ignoreFormDefense=忽略形态减伤 stats.hasDefensePenetration=有防御穿透 stats.defensePenetration=防御穿透 +effect.runsEveryX=每X个tick运行一次 +effect.defaultLength=默认长度 + +# These are supposed to be shorter +effect.editor.runsEveryX=每个X点 +effect.editor.defaultLength=长度 +effect.editor.height=高度 +effect.editor.width=宽度 +effect.editor.xPos=X Pos +effect.editor.yPos=Y Pos +effect.editor.lossOnDeath=死亡损失 + mastery.maxLevel=最大形态等级 -mastery.multiFlat=固定加成 -mastery.multiMinMax=最小/最大增幅范围 +mastery.multiFlat=固定倍率加成 +mastery.multiMinMax=最小/最大等级范围 mastery.multiPerLevel=每升一级增加 mastery.instantTransform=瞬间变身等级需求 mastery.healthReqSettings=血量要求设置 @@ -77,7 +91,8 @@ mastery.destroyerSettings=破坏能量设置 mastery.destroyerKiDamage=破坏能量气功伤害倍率 mastery.linkedMastery=关联等级 - +display.attri=属性设置 +display.adv=龙珠属性加成 display.human=人类 display.saiyan=赛亚人 display.halfsaiyan=混血赛亚人 @@ -135,15 +150,18 @@ display.raditz=拉帝兹 display.kiBarColor=气条颜色 display.eye=眼睛 display.isBerserk=狂暴状态 +display.normalEye=正常 display.hasEyebrows=眉毛 display.mouth=嘴巴 display.nose=鼻子 +display.formCanFormbeCustomized=玩家自定义 display.color=颜色 display.modify=修改 +display.formWidth=形态宽度 display.formSize=形态大小 display.aura=气焰 display.auraOn=气焰开 -isplay.fur=毛发 +display.fur=毛发 display.hair=头发 display.hairType=发型 display.majinHair=魔人发型 @@ -180,7 +198,7 @@ display.outline=气轮廓 display.selectOutline=无气轮廓 display.extra=额外 display.size=大小 -display.speed=速度 +display.speed=流动速度 display.overrideDBC=覆盖DBC形态 display.color1=颜色1 display.color2=颜色2 @@ -227,8 +245,12 @@ display.kettleOnly=仅魔人气焰 display.kettlePlusAura=魔人气焰 + 气焰 display.revampAura=重塑气焰 display.dbcAura=DBC气焰 +display.bloom=泛光 +display.outlines=气轮廓 +display.shaders=着色器 +display.firstPersonAura=第一人称气轮廓透明度 -outline.noiseSize=声音大小 +outline.noiseSize=轮廓光效粗糙度 outline.colorSmoothness=颜色平滑度 outline.colorInterpolation=颜色过渡 outline.pulsingSpeed=闪烁速度 @@ -294,8 +316,10 @@ npcdbc.inventory.willpower=意志 npcdbc.inventory.mastery=形态等级 npcdbc.inventory.selected=已选择 npcdbc.inventory.noauraselected=未选择气焰 +npcdbc.inventory.tweaks=调整 +npcdbc.inventory.revampAura=修改气焰 -npcdbc.inventory.stackable.dbc=DBC +npcdbc.inventory.stackable.dbc=龙块C npcdbc.inventory.stackable.kk=界王拳 npcdbc.inventory.stackable.ui=自在 npcdbc.inventory.stackable.godofdestruction=自我 @@ -340,7 +364,7 @@ npcdbc.spectator=作为副体无法变身 npcdbc.raceIneligible=您的种族不符合此形态要求 npcdbc.healthRequirement=您需要在 %d 百分之以下的生命值才能变身所选形态 npcdbc.pain=无法在痛苦状态中变身 -npcdbc.wrongDBC=您处于错误的 DBC 形态 +npcdbc.wrongDBC=您处于错误的形态 npcdbc.transformFromParent=必须从前置形态变身 npcdbc.fusionSkillFusion=没有启用融合技能 npcdbc.holdPotara=双方玩家必须各带波塔拉耳环 @@ -362,6 +386,9 @@ npcdbc.transform=变身为 npcdbc.descend=降级至 npcdbc.descendFrom=已解除 npcdbc.timeExpired=计时器已到期! +npcdbc.full=你感觉有点吃不下了 +npcdbc.bloated=你已经完成吃不下去了。 +npcdbc.humanSpiritMessage=你感觉到人类的精神。 ############################ ## ITEMS @@ -379,9 +406,9 @@ capsule.stamina=耐力 # (1) - Status effect name # (2) - Status effect level # (3) - Effect time -capsule.effect=在等级 %2s 时,给予 "%1s" 效果,持续 %3s 秒 +capsule.effect=使用胶囊会得到 %2s 状态,根据 "%1s" 等级给与 %3s 秒状态 -tem.npcdbc:base_healthcapsule.name=基础生命胶囊 +item.npcdbc:base_healthcapsule.name=基础生命胶囊 item.npcdbc:super_healthcapsule.name=初级生命胶囊 item.npcdbc:mega_healthcapsule.name=中级生命胶囊 item.npcdbc:giga_healthcapsule.name=高级生命胶囊 @@ -422,3 +449,20 @@ item.npcdbc:fruitofmight.name=精神树果实 item.npcdbc:one_potara.name=波塔拉耳环 item.npcdbc:two_potara.name=波塔拉耳环[金] item.npcdbc:three_potara.name=波塔拉耳环[豪华] + +effect.healthregeneration=生命回复 +effect.exhausted=疲惫 +effect.darkness=黑暗 +effect.chocolated=有点吃不下 +effect.bloated=吃不下了 +effect.fruitofmight=精神树果实 +effect.humanspirit=人类精神 +effect.meditation=冥想 +effect.namekianregeneration=那美克星人再生 +effect.overpower=压倒 +effect.potara=波塔拉 +effect.kiregeneration=气回复 +effect.staminaregeneration=耐力回复 +effect.zenkai=濒死复活强化 + +stats.ki=气 From 663cb5a2a158b8222749972272a073f60e2b179f Mon Sep 17 00:00:00 2001 From: somehussar <148253652+somehussar@users.noreply.github.com> Date: Sun, 20 Jul 2025 23:48:04 +0200 Subject: [PATCH 05/10] this apparently didnt get added last time lmfao --- .../npcdbc/api/effect/IDBCEffectHandler.html | 447 ++++++++++++++++++ .../api/event/IDBCEvent.SenzuUsedEvent.html | 259 ++++++++++ .../npcdbc/api/form/IAdvancedFormStat.html | 319 +++++++++++++ .../npcdbc/api/form/IFormAdvanced.html | 353 ++++++++++++++ 4 files changed, 1378 insertions(+) create mode 100644 docs/kamkeel/npcdbc/api/effect/IDBCEffectHandler.html create mode 100644 docs/kamkeel/npcdbc/api/event/IDBCEvent.SenzuUsedEvent.html create mode 100644 docs/kamkeel/npcdbc/api/form/IAdvancedFormStat.html create mode 100644 docs/kamkeel/npcdbc/api/form/IFormAdvanced.html diff --git a/docs/kamkeel/npcdbc/api/effect/IDBCEffectHandler.html b/docs/kamkeel/npcdbc/api/effect/IDBCEffectHandler.html new file mode 100644 index 000000000..25d88188f --- /dev/null +++ b/docs/kamkeel/npcdbc/api/effect/IDBCEffectHandler.html @@ -0,0 +1,447 @@ + + + + + +IDBCEffectHandler + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Interface IDBCEffectHandler

+
+
+
+
    +
  • +
    +
    public interface IDBCEffectHandler
    +
    Interface for handling custom effects within the NPCDBC mod. +

    + Provides methods to check, apply, remove, and clear effects on players. + This includes managing effect duration, levels, and verifying the existence + of specific effects. +

    +
  • +
+
+
+
    +
  • + +
    +
      +
    • + + +

      Method Summary

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      All Methods Instance Methods Abstract Methods 
      Modifier and TypeMethodDescription
      voidapplyEffect​(IPlayer player, + int id) +
      Applies the effect with the specified ID to the given player using default duration and level.
      +
      voidapplyEffect​(IPlayer player, + int id, + int duration) +
      Applies the effect with the specified ID to the given player with a custom duration.
      +
      voidapplyEffect​(IPlayer player, + int id, + int duration, + byte level) +
      Applies the effect with the specified ID to the given player with a custom duration and level.
      +
      voidclearDBCEffects​(IPlayer player) +
      Clears all effects managed by the NPCDBC effect handler from the specified player.
      +
      intgetEffectDuration​(IPlayer player, + int id) +
      Retrieves the remaining duration of the effect with the specified ID for the given IPlayer.
      +
      intgetEffectLevel​(IPlayer player, + int id) +
      Retrieves the level of the effect with the specified ID for the given IPlayer.
      +
      booleanhasEffect​(IPlayer player, + int id) +
      Checks if the specified player currently has the effect with the given ID.
      +
      voidremoveEffect​(IPlayer player, + int id) +
      Removes the effect with the specified ID from the given player.
      +
      +
    • +
    +
    +
  • +
+
+
+
    +
  • + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        hasEffect

        +
        boolean hasEffect​(IPlayer player,
        +                  int id)
        +
        Checks if the specified player currently has the effect with the given ID.
        +
        +
        Parameters:
        +
        player - the player to check
        +
        id - the effect ID to look for
        +
        Returns:
        +
        true if the player has the effect, otherwise false
        +
        +
      • +
      + + + +
        +
      • +

        applyEffect

        +
        void applyEffect​(IPlayer player,
        +                 int id)
        +
        Applies the effect with the specified ID to the given player using default duration and level.
        +
        +
        Parameters:
        +
        player - the player to apply the effect to
        +
        id - the effect ID to be applied
        +
        +
      • +
      + + + +
        +
      • +

        applyEffect

        +
        void applyEffect​(IPlayer player,
        +                 int id,
        +                 int duration)
        +
        Applies the effect with the specified ID to the given player with a custom duration.
        +
        +
        Parameters:
        +
        player - the player to apply the effect to
        +
        id - the effect ID to be applied
        +
        duration - the duration for which the effect should last, in ticks
        +
        +
      • +
      + + + +
        +
      • +

        applyEffect

        +
        void applyEffect​(IPlayer player,
        +                 int id,
        +                 int duration,
        +                 byte level)
        +
        Applies the effect with the specified ID to the given player with a custom duration and level.
        +
        +
        Parameters:
        +
        player - the player to apply the effect to
        +
        id - the effect ID to be applied
        +
        duration - the duration for which the effect should last, in ticks
        +
        level - the level or strength of the effect
        +
        +
      • +
      + + + +
        +
      • +

        clearDBCEffects

        +
        void clearDBCEffects​(IPlayer player)
        +
        Clears all effects managed by the NPCDBC effect handler from the specified player.
        +
        +
        Parameters:
        +
        player - the player from which to clear all effects
        +
        +
      • +
      + + + +
        +
      • +

        removeEffect

        +
        void removeEffect​(IPlayer player,
        +                  int id)
        +
        Removes the effect with the specified ID from the given player.
        +
        +
        Parameters:
        +
        player - the player from which the effect should be removed
        +
        id - the effect ID to be removed
        +
        +
      • +
      + + + +
        +
      • +

        getEffectDuration

        +
        int getEffectDuration​(IPlayer player,
        +                      int id)
        +
        Retrieves the remaining duration of the effect with the specified ID for the given IPlayer. + Uses the DBC effect index.
        +
        +
        Parameters:
        +
        player - the IPlayer to check
        +
        id - the effect ID
        +
        Returns:
        +
        the remaining duration in seconds, or -1 if the effect is not active
        +
        +
      • +
      + + + +
        +
      • +

        getEffectLevel

        +
        int getEffectLevel​(IPlayer player,
        +                   int id)
        +
        Retrieves the level of the effect with the specified ID for the given IPlayer. + Uses the DBC effect index.
        +
        +
        Parameters:
        +
        player - the IPlayer to check
        +
        id - the effect ID
        +
        Returns:
        +
        the effect level, or -1 if the effect is not active
        +
        +
      • +
      +
    • +
    +
    +
  • +
+
+
+
+ +
+ +
+ + diff --git a/docs/kamkeel/npcdbc/api/event/IDBCEvent.SenzuUsedEvent.html b/docs/kamkeel/npcdbc/api/event/IDBCEvent.SenzuUsedEvent.html new file mode 100644 index 000000000..7a8c84888 --- /dev/null +++ b/docs/kamkeel/npcdbc/api/event/IDBCEvent.SenzuUsedEvent.html @@ -0,0 +1,259 @@ + + + + + +IDBCEvent.SenzuUsedEvent + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Interface IDBCEvent.SenzuUsedEvent

+
+
+
+ +
+
+ +
+
+
+ +
+ +
+ + diff --git a/docs/kamkeel/npcdbc/api/form/IAdvancedFormStat.html b/docs/kamkeel/npcdbc/api/form/IAdvancedFormStat.html new file mode 100644 index 000000000..becb7e28a --- /dev/null +++ b/docs/kamkeel/npcdbc/api/form/IAdvancedFormStat.html @@ -0,0 +1,319 @@ + + + + + +IAdvancedFormStat + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Interface IAdvancedFormStat

+
+
+
+
    +
  • +
    +
    public interface IAdvancedFormStat
    +
  • +
+
+
+ +
+
+
    +
  • + +
    +
      +
    • + + +

      Method Detail

      + + + +
        +
      • +

        isEnabled

        +
        boolean isEnabled()
        +
      • +
      + + + +
        +
      • +

        setEnabled

        +
        void setEnabled​(boolean enabled)
        +
      • +
      + + + +
        +
      • +

        getBonus

        +
        int getBonus()
        +
      • +
      + + + +
        +
      • +

        setBonus

        +
        void setBonus​(int bonus)
        +
      • +
      + + + +
        +
      • +

        getMultiplier

        +
        float getMultiplier()
        +
      • +
      + + + +
        +
      • +

        setMultiplier

        +
        void setMultiplier​(float multiplier)
        +
      • +
      +
    • +
    +
    +
  • +
+
+
+
+ +
+ +
+ + diff --git a/docs/kamkeel/npcdbc/api/form/IFormAdvanced.html b/docs/kamkeel/npcdbc/api/form/IFormAdvanced.html new file mode 100644 index 000000000..f407893dc --- /dev/null +++ b/docs/kamkeel/npcdbc/api/form/IFormAdvanced.html @@ -0,0 +1,353 @@ + + + + + +IFormAdvanced + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +

Interface IFormAdvanced

+
+
+
+
    +
  • +
    +
    public interface IFormAdvanced
    +
  • +
+
+
+ +
+
+
    +
  • + +
    +
      +
    • + + +

      Method Detail

      + + + + + + + +
        +
      • +

        setStatEnabled

        +
        void setStatEnabled​(int id,
        +                    boolean enabled)
        +
      • +
      + + + +
        +
      • +

        isStatEnabled

        +
        boolean isStatEnabled​(int id)
        +
      • +
      + + + +
        +
      • +

        setStatBonus

        +
        void setStatBonus​(int id,
        +                  int bonus)
        +
      • +
      + + + +
        +
      • +

        getStatBonus

        +
        int getStatBonus​(int id)
        +
      • +
      + + + +
        +
      • +

        setStatMulti

        +
        void setStatMulti​(int id,
        +                  float multiplier)
        +
      • +
      + + + +
        +
      • +

        getStatMulti

        +
        float getStatMulti​(int id)
        +
      • +
      + + + + +
    • +
    +
    +
  • +
+
+
+
+ +
+ +
+ + From 64fa74d570ad38331db0332507abfb1b4cab8076 Mon Sep 17 00:00:00 2001 From: Trent Date: Mon, 6 Oct 2025 19:48:56 -0400 Subject: [PATCH 06/10] Fix: update icons to replace missing icons --- .../assets/npcdbc/textures/gui/icons.png | Bin 6242 -> 10301 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/assets/npcdbc/textures/gui/icons.png b/src/main/resources/assets/npcdbc/textures/gui/icons.png index c3e1ed8368fd609ba63e11133ce8568e7ab9a0fc..fa95bc83652ab260ac04817484c126b249ed6e44 100644 GIT binary patch literal 10301 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 BQB(i` literal 6242 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 tC3p`{M99|#9*Ft> Date: Sat, 15 Nov 2025 02:30:09 +0100 Subject: [PATCH 07/10] Packets to force form color customizations instantly Technically for script use although not exposed in the API whatsoever. Whoopsies. --- .../kamkeel/npcdbc/data/dbcdata/DBCData.java | 25 +++++++-- .../npcdbc/network/DBCPacketHandler.java | 1 + .../network/packets/EnumPacketPlayer.java | 1 + .../packets/player/PingFormColorPacket.java | 56 +++++++++++++++++++ 4 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 src/main/java/kamkeel/npcdbc/network/packets/player/PingFormColorPacket.java diff --git a/src/main/java/kamkeel/npcdbc/data/dbcdata/DBCData.java b/src/main/java/kamkeel/npcdbc/data/dbcdata/DBCData.java index 600103c82..49d728a35 100644 --- a/src/main/java/kamkeel/npcdbc/data/dbcdata/DBCData.java +++ b/src/main/java/kamkeel/npcdbc/data/dbcdata/DBCData.java @@ -28,10 +28,7 @@ import kamkeel.npcdbc.data.outline.Outline; import kamkeel.npcdbc.entity.EntityAura; import kamkeel.npcdbc.network.DBCPacketHandler; -import kamkeel.npcdbc.network.packets.player.DBCSetFlight; -import kamkeel.npcdbc.network.packets.player.DBCUpdateLockOn; -import kamkeel.npcdbc.network.packets.player.PingPacket; -import kamkeel.npcdbc.network.packets.player.TurboPacket; +import kamkeel.npcdbc.network.packets.player.*; import kamkeel.npcdbc.util.DBCUtils; import kamkeel.npcdbc.util.PlayerDataUtil; import net.minecraft.client.Minecraft; @@ -53,7 +50,7 @@ import static kamkeel.npcdbc.constants.DBCForm.*; import static kamkeel.npcdbc.controllers.DBCEffectController.DBC_EFFECT_INDEX; -public class DBCData extends DBCDataUniversal implements IAuraData { +public class DBCData extends DBCDataUniversal implements IAuraData { public static String DBCPersisted = "PlayerPersisted"; public final Side side; @@ -283,6 +280,11 @@ public void loadClientSideData(NBTTagCompound c) { } } + loadClientSideFormColorData(c); + } + + @SideOnly(Side.CLIENT) + public void loadClientSideFormColorData(NBTTagCompound c) { currentCustomizedColors = new FormDisplay.BodyColor(); if (c.hasKey("CustomFormColors", Constants.NBT.TAG_COMPOUND)) { currentCustomizedColors.readFromNBT(c.getCompoundTag("CustomFormColors")); @@ -1041,4 +1043,17 @@ public FormDisplay.BodyColor getCurrentFormColorCustomization() { PlayerDBCInfo info = getDBCInfo(); return info.configuredFormColors.get(form.id); } + + public void sendCurrentFormColorData() { + FormDisplay.BodyColor currentColors = getCurrentFormColorCustomization(); + NBTTagCompound dataNeededOnClient = new NBTTagCompound(); + + if (currentColors != null) { + NBTTagCompound colorCompound = new NBTTagCompound(); + currentColors.writeToNBT(colorCompound); + dataNeededOnClient.setTag("CustomFormColors", colorCompound); + } + + DBCPacketHandler.Instance.sendTracking(new PingFormColorPacket(this, dataNeededOnClient), player); + } } diff --git a/src/main/java/kamkeel/npcdbc/network/DBCPacketHandler.java b/src/main/java/kamkeel/npcdbc/network/DBCPacketHandler.java index 77df27e37..5cf5bad90 100644 --- a/src/main/java/kamkeel/npcdbc/network/DBCPacketHandler.java +++ b/src/main/java/kamkeel/npcdbc/network/DBCPacketHandler.java @@ -82,6 +82,7 @@ private void registerPlayerPackets() { PLAYER_PACKETS.registerPacket(new SaveFormCustomization()); PLAYER_PACKETS.registerPacket(new PlaySound()); PLAYER_PACKETS.registerPacket(new PingPacket()); + PLAYER_PACKETS.registerPacket(new PingFormColorPacket()); PLAYER_PACKETS.registerPacket(new LoginInfo()); PLAYER_PACKETS.registerPacket(new DBCUpdateLockOn()); PLAYER_PACKETS.registerPacket(new DBCSetValPacket()); diff --git a/src/main/java/kamkeel/npcdbc/network/packets/EnumPacketPlayer.java b/src/main/java/kamkeel/npcdbc/network/packets/EnumPacketPlayer.java index 2f706747e..150f9ddb8 100644 --- a/src/main/java/kamkeel/npcdbc/network/packets/EnumPacketPlayer.java +++ b/src/main/java/kamkeel/npcdbc/network/packets/EnumPacketPlayer.java @@ -15,6 +15,7 @@ public enum EnumPacketPlayer { LockOn, LoginInfo, PingPacket, + PingFormColorPacket, PlaySound, FormSaveCustiomization, SendChat, diff --git a/src/main/java/kamkeel/npcdbc/network/packets/player/PingFormColorPacket.java b/src/main/java/kamkeel/npcdbc/network/packets/player/PingFormColorPacket.java new file mode 100644 index 000000000..08039f67d --- /dev/null +++ b/src/main/java/kamkeel/npcdbc/network/packets/player/PingFormColorPacket.java @@ -0,0 +1,56 @@ +package kamkeel.npcdbc.network.packets.player; + +import io.netty.buffer.ByteBuf; +import kamkeel.npcdbc.data.dbcdata.DBCData; +import kamkeel.npcdbc.network.AbstractPacket; +import kamkeel.npcdbc.network.DBCPacketHandler; +import kamkeel.npcdbc.network.PacketChannel; +import kamkeel.npcdbc.network.packets.EnumPacketPlayer; +import kamkeel.npcs.util.ByteBufUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; + +import java.io.IOException; + +public final class PingFormColorPacket extends AbstractPacket { + public static final String packetName = "NPC|PingFormCustom"; + + private DBCData data; + private NBTTagCompound clientData; + + public PingFormColorPacket() { + } + + + public PingFormColorPacket(DBCData dbcData, NBTTagCompound dataNeededOnClient) { + this.data = dbcData; + this.clientData = dataNeededOnClient; + } + + @Override + public Enum getType() { + return EnumPacketPlayer.PingFormColorPacket; + } + + @Override + public PacketChannel getChannel() { + return DBCPacketHandler.PLAYER_PACKETS; + } + + @Override + public void sendData(ByteBuf out) throws IOException { + ByteBufUtils.writeUTF8String(out, this.data.player.getCommandSenderName()); + ByteBufUtils.writeNBT(out, this.clientData); + } + + @Override + public void receiveData(ByteBuf in, EntityPlayer player) throws IOException { + String playerName = ByteBufUtils.readUTF8String(in); + EntityPlayer sendingPlayer = Minecraft.getMinecraft().theWorld.getPlayerEntityByName(playerName); + if (sendingPlayer != null) { + DBCData dbcData = DBCData.get(sendingPlayer); + dbcData.loadClientSideFormColorData(ByteBufUtils.readNBT(in)); + } + } +} From 507757eeedcec025df6c464fcc12590f6f4b10ea Mon Sep 17 00:00:00 2001 From: somehussar <148253652+somehussar@users.noreply.github.com> Date: Sat, 15 Nov 2025 02:30:56 +0100 Subject: [PATCH 08/10] Update version number --- build.gradle | 2 +- gradle.properties | 2 +- src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index dcb1ea6ea..851317e2c 100644 --- a/build.gradle +++ b/build.gradle @@ -8,6 +8,6 @@ group= "kamkeel.npcdbc" tasks.runServer { setWorkingDir(file("run/server")) } -version = "1.1.2" +version = "1.1.3" group= "kamkeel.npcdbc" archivesBaseName = "npcdbc" diff --git a/gradle.properties b/gradle.properties index b5b4de328..4dcc76157 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ modName = CustomNPC+ DBC Addon # This is a case-sensitive string to identify your mod. Convention is to use lower case. modId = npcdbc modGroup = kamkeel.npcdbc -modVersion = 1.1 +modVersion = 1.1.3 gtnh.modules.codeStyle=true gtnh.modules.gitVersion=false diff --git a/src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java b/src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java index 2322d8251..0886dc0ee 100644 --- a/src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java +++ b/src/main/java/kamkeel/npcdbc/CustomNpcPlusDBC.java @@ -25,7 +25,7 @@ public class CustomNpcPlusDBC { public static final String name = "CustomNPC+ DBC Addon"; public static final String ID = "npcdbc"; - public static final String version = "1.1.2"; + public static final String version = "1.1.3"; @SidedProxy(clientSide = "kamkeel.npcdbc.client.ClientProxy", serverSide = "kamkeel.npcdbc.CommonProxy") public static CommonProxy proxy; From 44524b2e455bb166e9338b48ff58fcb33f9bb91e Mon Sep 17 00:00:00 2001 From: somehussar <148253652+somehussar@users.noreply.github.com> Date: Sat, 15 Nov 2025 23:42:49 +0100 Subject: [PATCH 09/10] Imaginary Technique : Fake Color --- .../kamkeel/npcdbc/client/model/ModelDBC.java | 47 +++++++------- .../npcdbc/client/model/part/DBCBody.java | 7 +- .../npcdbc/client/model/part/DBCEars.java | 7 +- .../npcdbc/client/model/part/DBCHorns.java | 19 +++--- .../npcdbc/client/model/part/DBCLeftArms.java | 11 ++-- .../client/model/part/DBCRightArms.java | 11 ++-- .../client/model/part/hair/DBCHair.java | 12 ++-- .../kamkeel/npcdbc/data/npc/DBCDisplay.java | 29 +++++++++ .../npcdbc/network/DBCPacketHandler.java | 1 + .../network/packets/EnumPacketPlayer.java | 2 +- .../packets/player/NPCUpdateForcedColors.java | 64 +++++++++++++++++++ 11 files changed, 161 insertions(+), 49 deletions(-) create mode 100644 src/main/java/kamkeel/npcdbc/network/packets/player/NPCUpdateForcedColors.java diff --git a/src/main/java/kamkeel/npcdbc/client/model/ModelDBC.java b/src/main/java/kamkeel/npcdbc/client/model/ModelDBC.java index 3f13bb75b..ede810f1a 100644 --- a/src/main/java/kamkeel/npcdbc/client/model/ModelDBC.java +++ b/src/main/java/kamkeel/npcdbc/client/model/ModelDBC.java @@ -158,13 +158,14 @@ public void renderFace(EntityCustomNpc entity, DBCDisplay display) { Form form = display.getForm(); if (form != null) { FormDisplay d = form.display; + FormDisplay.BodyColor customClr = display.formColor; - if (d.hasColor("eye")) - eyeColor = d.bodyColors.eyeColor; - if (d.hasColor("hair")) - eyeBrowColor = d.bodyColors.hairColor; - if (d.hasColor("bodycm")) - bodyCM = d.bodyColors.bodyCM; + if (customClr.hasAnyColor(d, "eye")) + eyeColor = customClr.getProperColor(d, "eye"); + if (customClr.hasAnyColor(d, "hair")) + eyeBrowColor = customClr.getProperColor(d, "hair"); + if (customClr.hasAnyColor(d, "bodycm")) + bodyCM = customClr.getProperColor(d, "bodyCM"); if (d.hasArcoMask) hasArcoMask = true; @@ -176,7 +177,7 @@ else if (d.hairType.equals("ssj4")) isSSJ4 = true; else if (d.hairType.equals("oozaru")) { isOozaru = true; - if (d.bodyColors.eyeColor == -1) + if (customClr.getProperColor(d, "eye") == -1) eyeColor = 0xFF0000; } @@ -385,25 +386,27 @@ public void renderBodySkin(DBCDisplay display, ModelRenderer model) { Form form = display.getForm(); if (form != null) { FormDisplay d = form.display; - if (d.hasColor("eye")) - eyeColor = d.bodyColors.eyeColor; - if (d.hasColor("hair")) - hairColor = d.bodyColors.hairColor; - if (d.hasColor("bodycm")) - bodyCM = d.bodyColors.bodyCM; - if (d.hasColor("bodyc1")) - bodyC1 = d.bodyColors.bodyC1; - if (d.hasColor("bodyc2")) - bodyC2 = d.bodyColors.bodyC2; - if (d.hasColor("bodyc3")) - bodyC3 = d.bodyColors.bodyC3; - if (d.hasColor("fur")) - furColor = d.bodyColors.furColor; + FormDisplay.BodyColor customClr = display.formColor; + + if (customClr.hasAnyColor(d, "eye")) + eyeColor = customClr.getProperColor(d, "eye"); + if (customClr.hasAnyColor(d, "hair")) + hairColor = customClr.getProperColor(d, "hair"); + if (customClr.hasAnyColor(d, "bodycm")) + bodyCM = customClr.getProperColor(d, "bodycm"); + if (customClr.hasAnyColor(d, "bodyc1")) + bodyC1 = customClr.getProperColor(d, "bodyc1"); + if (customClr.hasAnyColor(d, "bodyc2")) + bodyC2 = customClr.getProperColor(d, "bodyc2"); + if (customClr.hasAnyColor(d, "bodyc3")) + bodyC3 = customClr.getProperColor(d, "bodyc3"); + if (customClr.hasAnyColor(d, "fur")) + furColor = customClr.getProperColor(d, "fur"); hasFur = d.hasBodyFur; if (d.hairType.equals("ssj4")) { isSSJ4 = true; - if (d.bodyColors.eyeColor == -1) + if (customClr.getProperColor(d, "eye") == -1) eyeColor = 0xF3C807; } else if (d.hairType.equals("oozaru")) { isOozaru = true; diff --git a/src/main/java/kamkeel/npcdbc/client/model/part/DBCBody.java b/src/main/java/kamkeel/npcdbc/client/model/part/DBCBody.java index bf9fb6d4e..0c2849fe6 100644 --- a/src/main/java/kamkeel/npcdbc/client/model/part/DBCBody.java +++ b/src/main/java/kamkeel/npcdbc/client/model/part/DBCBody.java @@ -82,8 +82,11 @@ public void render(float par1) { Form form = display.getForm(); if (form != null) { FormDisplay d = form.display; - if (d.hasColor("bodycm")) - bodyCM = d.bodyColors.bodyCM; + FormDisplay.BodyColor customClr = display.formColor; + + if (customClr.hasAnyColor(d, "bodycm")) + bodyCM = customClr.getProperColor(d, "bodycm"); + } ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// diff --git a/src/main/java/kamkeel/npcdbc/client/model/part/DBCEars.java b/src/main/java/kamkeel/npcdbc/client/model/part/DBCEars.java index bcfff9320..08ff8b507 100644 --- a/src/main/java/kamkeel/npcdbc/client/model/part/DBCEars.java +++ b/src/main/java/kamkeel/npcdbc/client/model/part/DBCEars.java @@ -69,8 +69,11 @@ public void render(float par1) { Form form = display.getForm(); if (form != null) { FormDisplay d = form.display; - if (d.hasColor("bodycm")) - bodyCM = d.bodyColors.bodyCM; + FormDisplay.BodyColor customClr = display.formColor; + + if (customClr.hasAnyColor(d, "bodycm")) + bodyCM = customClr.getProperColor(d, "bodycm"); + } ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// diff --git a/src/main/java/kamkeel/npcdbc/client/model/part/DBCHorns.java b/src/main/java/kamkeel/npcdbc/client/model/part/DBCHorns.java index 06a8d3330..0ff65d556 100644 --- a/src/main/java/kamkeel/npcdbc/client/model/part/DBCHorns.java +++ b/src/main/java/kamkeel/npcdbc/client/model/part/DBCHorns.java @@ -205,14 +205,17 @@ public void render(float par1) { Form form = display.getForm(); if (form != null) { FormDisplay d = form.display; - if (d.hasColor("bodycm")) - bodyCM = d.bodyColors.bodyCM; - if (d.hasColor("bodyc1")) - bodyC1 = d.bodyColors.bodyC1; - if (d.hasColor("bodyc2")) - bodyC2 = d.bodyColors.bodyC2; - if (d.hasColor("bodyc3")) - bodyC3 = d.bodyColors.bodyC3; + FormDisplay.BodyColor customClr = display.formColor; + + if (customClr.hasAnyColor(d, "bodycm")) + bodyCM = customClr.getProperColor(d, "bodycm"); + if (customClr.hasAnyColor(d, "bodyc1")) + bodyC1 = customClr.getProperColor(d, "bodyc1"); + if (customClr.hasAnyColor(d, "bodyc2")) + bodyC2 = customClr.getProperColor(d, "bodyc2"); + if (customClr.hasAnyColor(d, "bodyc3")) + bodyC3 = customClr.getProperColor(d, "bodyc3"); + if (isArco) { if (form.display.bodyType.equals("firstform")) { diff --git a/src/main/java/kamkeel/npcdbc/client/model/part/DBCLeftArms.java b/src/main/java/kamkeel/npcdbc/client/model/part/DBCLeftArms.java index 9405f748b..166e9b7d1 100644 --- a/src/main/java/kamkeel/npcdbc/client/model/part/DBCLeftArms.java +++ b/src/main/java/kamkeel/npcdbc/client/model/part/DBCLeftArms.java @@ -79,10 +79,13 @@ public void render(float par1) { Form form = display.getForm(); if (form != null) { FormDisplay d = form.display; - if (d.hasColor("bodycm")) - bodyCM = d.bodyColors.bodyCM; - if (d.hasColor("bodyc2")) - bodyC2 = d.bodyColors.bodyC2; + FormDisplay.BodyColor customClr = display.formColor; + + if (customClr.hasAnyColor(d, "bodycm")) + bodyCM = customClr.getProperColor(d, "bodycm"); + if (customClr.hasAnyColor(d, "bodyc2")) + bodyC2 = customClr.getProperColor(d, "bodyc2"); + } ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// diff --git a/src/main/java/kamkeel/npcdbc/client/model/part/DBCRightArms.java b/src/main/java/kamkeel/npcdbc/client/model/part/DBCRightArms.java index 8e02c5182..a3f8e80ee 100644 --- a/src/main/java/kamkeel/npcdbc/client/model/part/DBCRightArms.java +++ b/src/main/java/kamkeel/npcdbc/client/model/part/DBCRightArms.java @@ -79,10 +79,13 @@ public void render(float par1) { Form form = display.getForm(); if (form != null) { FormDisplay d = form.display; - if (d.hasColor("bodycm")) - bodyCM = d.bodyColors.bodyCM; - if (d.hasColor("bodyc2")) - bodyC2 = d.bodyColors.bodyC2; + FormDisplay.BodyColor customClr = display.formColor; + + if (customClr.hasAnyColor(d, "bodycm")) + bodyCM = customClr.getProperColor(d, "bodycm"); + if (customClr.hasAnyColor(d, "bodyc2")) + bodyC2 = customClr.getProperColor(d, "bodyc2"); + } ////////////////////////////////////////////////////// ////////////////////////////////////////////////////// diff --git a/src/main/java/kamkeel/npcdbc/client/model/part/hair/DBCHair.java b/src/main/java/kamkeel/npcdbc/client/model/part/hair/DBCHair.java index 384aa9dc8..7d3444356 100644 --- a/src/main/java/kamkeel/npcdbc/client/model/part/hair/DBCHair.java +++ b/src/main/java/kamkeel/npcdbc/client/model/part/hair/DBCHair.java @@ -556,6 +556,8 @@ else if (display.hairType.equals("ssj4")) Form form = display.getForm(); if (form != null) { FormDisplay d = form.display; + FormDisplay.BodyColor customClr = display.formColor; + if (race == 5 && !form.display.effectMajinHair) { effectMajinHair = false; hairCode = MAJIN_HAIR; @@ -567,12 +569,10 @@ else if (display.hairType.equals("ssj4")) else if (d.hairCode.length() > 3) hairCode = d.hairCode; - - if (d.hasColor("hair")) - hairColor = d.bodyColors.hairColor; - else if (display.race == 5 && d.hasColor("bodycm")) { - hairColor = d.bodyColors.bodyCM; - } + if (customClr.hasAnyColor(d, "hair")) + hairColor = customClr.getProperColor(d, "hair"); + else if (display.race == 5 && customClr.hasAnyColor(d, "bodycm")) + hairColor = customClr.getProperColor(d, "bodycm"); if (d.hairType.equals("base")) state = 0; diff --git a/src/main/java/kamkeel/npcdbc/data/npc/DBCDisplay.java b/src/main/java/kamkeel/npcdbc/data/npc/DBCDisplay.java index e3693158c..6c6251ec7 100644 --- a/src/main/java/kamkeel/npcdbc/data/npc/DBCDisplay.java +++ b/src/main/java/kamkeel/npcdbc/data/npc/DBCDisplay.java @@ -21,19 +21,25 @@ import kamkeel.npcdbc.data.aura.Aura; import kamkeel.npcdbc.data.dbcdata.DBCData; import kamkeel.npcdbc.data.form.Form; +import kamkeel.npcdbc.data.form.FormDisplay; import kamkeel.npcdbc.data.outline.Outline; import kamkeel.npcdbc.entity.EntityAura; import kamkeel.npcdbc.mixins.late.INPCDisplay; import kamkeel.npcdbc.mixins.late.INPCStats; +import kamkeel.npcdbc.network.DBCPacketHandler; +import kamkeel.npcdbc.network.packets.player.NPCUpdateForcedColors; +import kamkeel.npcdbc.network.packets.player.PingFormColorPacket; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.Constants; import noppes.npcs.entity.EntityCustomNpc; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.entity.data.ModelData; import noppes.npcs.entity.data.ModelPartData; import noppes.npcs.scripted.CustomNPCsException; import noppes.npcs.util.ValueUtil; +import org.lwjgl.opencl.CL; import java.util.HashMap; import java.util.LinkedList; @@ -89,6 +95,8 @@ public DBCDisplay(EntityNPCInterface npc) { this.npc = npc; } + public FormDisplay.BodyColor formColor = new FormDisplay.BodyColor(); + public NBTTagCompound writeToNBT(NBTTagCompound comp) { comp.setBoolean("DBCDisplayEnabled", enabled); if (enabled) { @@ -866,4 +874,25 @@ public static EntityCustomNpc setupGUINPC(EntityCustomNpc originalNPC) { } return npc; } + + public void sendCurrentFormColorData() { + FormDisplay.BodyColor currentColors = formColor; + NBTTagCompound dataNeededOnClient = new NBTTagCompound(); + + if (currentColors != null) { + NBTTagCompound colorCompound = new NBTTagCompound(); + currentColors.writeToNBT(colorCompound); + dataNeededOnClient.setTag("CustomFormColors", colorCompound); + } + + DBCPacketHandler.Instance.sendTracking(new NPCUpdateForcedColors(npc, dataNeededOnClient), npc); + } + + @SideOnly(Side.CLIENT) + public void loadClientSideFormColorData(NBTTagCompound c) { + formColor = new FormDisplay.BodyColor(); + if (c.hasKey("CustomFormColors", Constants.NBT.TAG_COMPOUND)) { + formColor.readFromNBT(c.getCompoundTag("CustomFormColors")); + } + } } diff --git a/src/main/java/kamkeel/npcdbc/network/DBCPacketHandler.java b/src/main/java/kamkeel/npcdbc/network/DBCPacketHandler.java index 5cf5bad90..cea17ba54 100644 --- a/src/main/java/kamkeel/npcdbc/network/DBCPacketHandler.java +++ b/src/main/java/kamkeel/npcdbc/network/DBCPacketHandler.java @@ -83,6 +83,7 @@ private void registerPlayerPackets() { PLAYER_PACKETS.registerPacket(new PlaySound()); PLAYER_PACKETS.registerPacket(new PingPacket()); PLAYER_PACKETS.registerPacket(new PingFormColorPacket()); + PLAYER_PACKETS.registerPacket(new NPCUpdateForcedColors()); PLAYER_PACKETS.registerPacket(new LoginInfo()); PLAYER_PACKETS.registerPacket(new DBCUpdateLockOn()); PLAYER_PACKETS.registerPacket(new DBCSetValPacket()); diff --git a/src/main/java/kamkeel/npcdbc/network/packets/EnumPacketPlayer.java b/src/main/java/kamkeel/npcdbc/network/packets/EnumPacketPlayer.java index 150f9ddb8..3d422b57b 100644 --- a/src/main/java/kamkeel/npcdbc/network/packets/EnumPacketPlayer.java +++ b/src/main/java/kamkeel/npcdbc/network/packets/EnumPacketPlayer.java @@ -21,5 +21,5 @@ public enum EnumPacketPlayer { SendChat, StopSound, Transform, - Turbo + NPCPingForm, Turbo } diff --git a/src/main/java/kamkeel/npcdbc/network/packets/player/NPCUpdateForcedColors.java b/src/main/java/kamkeel/npcdbc/network/packets/player/NPCUpdateForcedColors.java new file mode 100644 index 000000000..a5ac557f2 --- /dev/null +++ b/src/main/java/kamkeel/npcdbc/network/packets/player/NPCUpdateForcedColors.java @@ -0,0 +1,64 @@ +package kamkeel.npcdbc.network.packets.player; + +import JinRyuu.JRMCore.entity.EntityNPC; +import io.netty.buffer.ByteBuf; +import kamkeel.npcdbc.data.dbcdata.DBCData; +import kamkeel.npcdbc.data.npc.DBCDisplay; +import kamkeel.npcdbc.mixins.late.INPCDisplay; +import kamkeel.npcdbc.network.AbstractPacket; +import kamkeel.npcdbc.network.DBCPacketHandler; +import kamkeel.npcdbc.network.PacketChannel; +import kamkeel.npcdbc.network.packets.EnumPacketPlayer; +import kamkeel.npcdbc.scripted.DBCAPI; +import kamkeel.npcs.util.ByteBufUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.api.entity.ICustomNpc; +import noppes.npcs.entity.EntityCustomNpc; +import noppes.npcs.entity.EntityNPCInterface; + +import java.io.IOException; + +public final class NPCUpdateForcedColors extends AbstractPacket { + public static final String packetName = "NPC|PingFormCustom"; + + private NBTTagCompound clientData; + private EntityNPCInterface npc; + + public NPCUpdateForcedColors() { + } + + + public NPCUpdateForcedColors(EntityNPCInterface npc, NBTTagCompound dataNeededOnClient) { + this.npc = npc; + this.clientData = dataNeededOnClient; + } + + @Override + public Enum getType() { + return EnumPacketPlayer.NPCPingForm; + } + + @Override + public PacketChannel getChannel() { + return DBCPacketHandler.PLAYER_PACKETS; + } + + @Override + public void sendData(ByteBuf out) throws IOException { + out.writeInt(npc.getEntityId()); + ByteBufUtils.writeNBT(out, this.clientData); + } + + @Override + public void receiveData(ByteBuf in, EntityPlayer player) throws IOException { + int entityID = in.readInt(); + Entity ent = player.getEntityWorld().getEntityByID(entityID); + if (ent instanceof EntityNPCInterface) { + DBCDisplay display = ((INPCDisplay) ((EntityNPCInterface) ent).display).getDBCDisplay(); + display.loadClientSideFormColorData(ByteBufUtils.readNBT(in)); + } + } +} From 6a53929c72b7a48453d933c041b8a3af7364e1bf Mon Sep 17 00:00:00 2001 From: somehussar <148253652+somehussar@users.noreply.github.com> Date: Sun, 16 Nov 2025 00:25:32 +0100 Subject: [PATCH 10/10] Le more code to change for rendering! --- .../late/impl/npc/client/MixinModelTail.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/kamkeel/npcdbc/mixins/late/impl/npc/client/MixinModelTail.java b/src/main/java/kamkeel/npcdbc/mixins/late/impl/npc/client/MixinModelTail.java index 936d87773..d44e1ce95 100644 --- a/src/main/java/kamkeel/npcdbc/mixins/late/impl/npc/client/MixinModelTail.java +++ b/src/main/java/kamkeel/npcdbc/mixins/late/impl/npc/client/MixinModelTail.java @@ -8,9 +8,11 @@ import kamkeel.npcdbc.config.ConfigDBCClient; import kamkeel.npcdbc.constants.DBCRace; import kamkeel.npcdbc.data.form.Form; +import kamkeel.npcdbc.data.form.FormDisplay; import kamkeel.npcdbc.data.npc.DBCDisplay; import kamkeel.npcdbc.mixins.late.INPCDisplay; import net.minecraft.client.model.ModelBase; +import net.minecraft.client.model.ModelRenderer; import net.minecraft.util.ResourceLocation; import noppes.npcs.client.ClientProxy; import noppes.npcs.client.model.ModelMPM; @@ -41,6 +43,9 @@ public abstract class MixinModelTail extends ModelScaleRenderer { @Shadow private int color; + @Shadow + public ModelRenderer tail; + public MixinModelTail(ModelBase par1ModelBase) { super(par1ModelBase); } @@ -87,10 +92,12 @@ else if (!monkey.monkey_large.isHidden) Form form = display.getForm(); if (form != null) { - if (form.display.hasColor("hair")) - tailColor = form.display.bodyColors.hairColor; - if (form.display.hasColor("fur")) - furColor = form.display.bodyColors.furColor; + FormDisplay d = form.display; + FormDisplay.BodyColor customClr = display.formColor; + if (customClr.hasAnyColor(d, "hair")) + tailColor = customClr.getProperColor(d, "hair"); + if (customClr.hasAnyColor(d, "fur")) + furColor = customClr.getProperColor(d, "fur"); hasFur = form.display.hasBodyFur; @@ -121,11 +128,14 @@ else if (form.display.hairType.equals("oozaru")) Form form = display.getForm(); if (form != null) { + FormDisplay d = form.display; + FormDisplay.BodyColor customClr = display.formColor; + if ((form.display.bodyType.contains("first") || form.display.bodyType.contains("second") || form.display.bodyType.contains("third"))) { - if (form.display.hasColor("bodyc3")) - tailColor = form.display.bodyColors.bodyC3; - } else if (form.display.hasColor("bodycm")) - tailColor = form.display.bodyColors.bodyCM; + if (customClr.hasAnyColor(d, "bodyc3")) + tailColor = customClr.getProperColor(d, "bodyc3"); + } else if (customClr.hasAnyColor(d, "bodycm")) + tailColor = customClr.getProperColor(d, "bodycm"); }