查看: 762|回復: 4

[問題] 關於火神融煉封包的問題

[複製鏈接]

30

主題

117

帖子

3725

金錢

暗殺軍王.史雷佛

Rank: 8Rank: 8

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
45
積分
3842
在線時間
128 小時
相冊
0
日誌
0
好友
5
發表於 2026-5-5 19:21 | 顯示全部樓層 |閱讀模式
WARN - 找不到指定的材料 ObjId (main=0, aid=0)

關於您在「[版本] 815登入器+主程式+核心源碼_整理過的」的帖子
yasioukon大大  我卡住了
package com.lineage.server.serverpackets;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.lineage.server.model.Instance.L1ItemInstance;
import com.lineage.server.model.Instance.L1NpcInstance;
import java.util.List;
import java.util.ArrayList;




public class S_ItemSmelt extends ServerBasePacket {

    private static final Log _log = LogFactory.getLog(S_ItemSmelt.class);

    public S_ItemSmelt(L1NpcInstance npc) {
        try {
            // Opcode: 熔煉 UI
            writeC(OpcodesServer.S_VOICE_CHAT); // 156
            writeC(48);                         // 熔煉 UI type
            writeD(npc.getId());                // NPC ObjectId
        } catch (Exception e) {
            _log.error(e.getLocalizedMessage(), e);
        }
    }
   
   
   
    public S_ItemSmelt(L1NpcInstance npc, List<Integer> mainMaterials, List<Integer> aidMaterials, int resultItemId, int successRate) {
        try {
            // 打開熔煉 UI
            writeC(OpcodesServer.S_VOICE_CHAT); // 156
            writeC(48);                         // 熔煉 UI type
            writeD(npc.getId());                // NPC ObjectId

            // 主材料清單
            writeC(mainMaterials.size());
            for (int itemId : mainMaterials) {
                writeD(itemId);
            }

            // 輔助材料清單
            writeC(aidMaterials.size());
            for (int itemId : aidMaterials) {
                writeD(itemId);
            }

            // 熔煉結果
            writeD(resultItemId);   // 火神結晶 itemId
            writeC(successRate);    // 成功率 (例如 80%)

        } catch (Exception e) {
            _log.error("S_ItemSmelt error: " + e.getMessage(), e);
        }
    }


   
   
   
//    /**
//     * 熔煉結果封包
//     * @param isSuccess 熔煉是否成功
//     * @param resultItems 熔煉後給予的物品清單
//     */
//        public S_ItemSmelt(final boolean isSuccess, final List<L1ItemInstance> giveItemObjs) {
//                try {
//                        writeC(S_EXTENDED_PROTOBUF);
//                        writeC(59);
//                        a(8, isSuccess ? 0L : 1L);
//                        if (giveItemObjs != null) {
//                                for (final L1ItemInstance itemObj : giveItemObjs) {
//                                        a(18, new S_CraftContent().jdMethod_if(itemObj));
//                                }
//                        }
//                        writeC(3);
//                        writeC(116);
//
//                } catch (final Exception e) {
//                        _log.error(e.getLocalizedMessage(), e);
//                }
//        }
   
   
   

    @Override
    public byte[] getContent() {
        return _bao.toByteArray();
    }

    @Override
    public String getType() {
        return this.getClass().getSimpleName();
    }
}


-------------------------------
package com.lineage.server.clientpackets;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.lineage.echo.ClientExecutor;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.Instance.L1ItemInstance;
import com.lineage.server.datatables.ItemTable;
import com.lineage.server.serverpackets.S_ItemSmeltResult;

/**
* 熔煉確認封包 (Opcode=250)
* 玩家在熔煉 UI 按下「確認」時送出
*/
public class C_ItemSmelt extends ClientBasePacket {

    private static final Log _log = LogFactory.getLog(C_ItemSmelt.class);
    private static final Random random = new Random();

    // 熔煉成功率 (可調整)
    private static final int SUCCESS_RATE = 80;

    @Override
    public void start(byte[] decrypt, ClientExecutor client) throws Exception {
        try {
            read(decrypt);
            L1PcInstance pc = client.getActiveChar();
            if (pc == null) {
                return;
            }

            
            
            int reservedH  = readH();   // 保留 short
            int reservedD  = readD();   // 保留 int
            int msgId      = readH();   // 封包訊息 ID
            int mainObjId  = readD();   // 主材料 ObjId
            int aidObjId   = readD();   // 輔助材料 ObjId

            _log.debug(String.format(
                "Smelt Packet解析: reservedH=%d, reservedD=%d, msgId=%d, mainObjId=%d, aidObjId=%d",
                reservedH, reservedD, msgId, mainObjId, aidObjId
            ));





            // 用 ObjId 查找背包物品
            L1ItemInstance mainItem = pc.getInventory().getItem(mainObjId);
            L1ItemInstance aidItem  = pc.getInventory().getItem(aidObjId);

            boolean success = false;
            L1ItemInstance resultItem = null;

            if (mainItem == null || aidItem == null) {
                _log.warn("找不到指定的材料 ObjId (main=" + mainObjId + ", aid=" + aidObjId + ")");
                pc.sendPackets(new S_ItemSmeltResult(false, new ArrayList<>()));
                return;
            }

            _log.info("主材料存在: ObjId=" + mainItem.getId() + ", itemId=" + mainItem.getItemId());
            _log.info("輔助材料存在: ObjId=" + aidItem.getId() + ", itemId=" + aidItem.getItemId());

            // 驗證配方
            if ((mainItem.getItemId() == 200041 || mainItem.getItemId() == 100037 || mainItem.getItemId() == 200052) &&
                (aidItem.getItemId() == 80027 || aidItem.getItemId() == 80028 || aidItem.getItemId() == 80322)) {

                // 消耗材料
                pc.getInventory().removeItem(mainItem, 1);
                pc.getInventory().removeItem(aidItem, 1);

                // 成功率判斷
                success = random.nextInt(100) < SUCCESS_RATE;

                if (success) {
                    resultItem = ItemTable.get().createItem(80029); // 火神結晶
                    resultItem.setCount(1);
                    pc.getInventory().storeItem(resultItem);
                    _log.info("熔煉成功,生成火神結晶 itemId=80029");
                } else {
                    _log.info("熔煉失敗,沒有生成結晶");
                }
            } else {
                _log.warn("材料不符合熔煉配方");
            }

            List<L1ItemInstance> results = new ArrayList<>();
            if (resultItem != null) {
                results.add(resultItem);
            }

            pc.sendPackets(new S_ItemSmeltResult(success, results));
            _log.info("Send SmeltResult with subId=61, success=" + success);

        } catch (Exception e) {
            _log.error("C_ItemSmelt error: " + e.getMessage(), e);
        } finally {
            over();
        }
    }
}
-------------------------------------
package com.lineage.server.serverpackets;

import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.lineage.server.model.Instance.L1ItemInstance;

/**
* 熔煉結果封包
* 成功/失敗 + 結果物品清單
*/
public class S_ItemSmeltResult extends ServerBasePacket {

    private static final Log _log = LogFactory.getLog(S_ItemSmeltResult.class);
    private static final String TYPE = "[S] S_ItemSmeltResult";

    public S_ItemSmeltResult(boolean isSuccess, List<L1ItemInstance> resultItems) {
        try {
            _log.info("SmeltResult: success=" + isSuccess);

            if (resultItems != null) {
                for (L1ItemInstance item : resultItems) {
                    _log.info("ResultItem: id=" + item.getItemId() + ", count=" + item.getCount());
                }
            }

            // 封包結構
            writeC(OpcodesServer.S_EXTENDED_PROTOBUF); // 主 opcode
            writeH(61); // 子編號 (熔煉結果)
            writeH(0);  // 保留

            _log.info("Send SmeltResult with subId=61, success=" + isSuccess);

            
            // 成功/失敗 flag
            writeC(isSuccess ? 1 : 0);

            // 結果物品清單
            if (resultItems != null && !resultItems.isEmpty()) {
                writeC(resultItems.size()); // 結果數量
                for (L1ItemInstance item : resultItems) {
                    writeD((int) item.getItemId());   // ★ 強制轉型成 int
                    writeD((int) item.getCount());    // ★ 強制轉型成 int
                }
            } else {
                writeC(0); // 沒有結果
            }

        } catch (Exception e) {
            _log.error("S_ItemSmeltResult error: " + e.getMessage(), e);
        }
    }

    @Override
    public byte[] getContent() {
        return getBytes();
    }

    @Override
    public String getType() {
        return TYPE;
    }
}


----------------------------------
package com.lineage.data.npc;

import com.lineage.data.executor.NpcExecutor;
import com.lineage.server.datatables.T_CraftConfigTable;
import com.lineage.server.model.Broadcaster;
import com.lineage.server.model.Instance.L1NpcInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.serverpackets.S_ChangeHeading;
import com.lineage.server.serverpackets.S_NPCTalkReturn;
import com.lineage.server.serverpackets.S_NpcChatPacket;
import com.lineage.server.thread.GeneralThreadPool;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.lineage.server.serverpackets.S_ItemCraftList;
import com.lineage.server.model.Instance.L1ItemInstance;
import com.lineage.server.serverpackets.S_ItemSmelt;
import com.lineage.server.serverpackets.S_ItemSmeltResult;

import java.util.List;
import java.util.ArrayList;
import com.lineage.server.model.L1ObjectAmount;
import com.lineage.server.datatables.ItemTable;
import java.util.Arrays;




/**
* 火神學徒 NPC 腳本
*/
public class L1NpcFireSmith1 extends NpcExecutor {
        private static final Log _log = LogFactory.getLog(L1NpcFireSmith1.class);

    // 供 NpcTable 反射呼叫
    public static NpcExecutor get() {
        return new L1NpcFireSmith1();
    }
   
    /**
     * 每 15 秒觸發一次工作邏輯
     */
    @Override
    public int workTime() {
        return 15;
    }
   

    @Override
    public void talk(final L1PcInstance pc, final L1NpcInstance npc) {
//            npc.setHeading(pc.getHeading());
//            Broadcaster.broadcastPacket(npc, new S_ChangeHeading(npc));
//        int oid = npc.getId(); // 取得 NPC ObjectId
//        _log.info("NPC ObjectId = " + oid + ", NpcId = " + npc.getNpcId());
        pc.sendPackets(new S_NPCTalkReturn(pc.getId(), "a_firesmith1"));
   
    }



    @Override
    public void action(final L1PcInstance pc, final L1NpcInstance npc, final String cmd, final long amount) {
        npc.setHeading(pc.getHeading());
        Broadcaster.broadcastPacket(npc, new S_ChangeHeading(npc));
        try {
            if (cmd.equalsIgnoreCase("openSmelt")) {
                // 主材料:武士刀、大馬士革刀、雙手劍
                List<Integer> mains = Arrays.asList(200041, 100037, 200052);
                // 輔助材料:火神之槌、火神契約、火神痕跡
                List<Integer> aids = Arrays.asList(80027, 80028, 80322);
                // 熔煉結果:火神結晶 (itemId=80029),成功率 80%
                int resultItemId = 80029;
                int successRate = 80;

                pc.sendPackets(new S_ItemSmelt(npc, mains, aids, resultItemId, successRate));
                _log.info("NPCAction: 打開熔煉 UI (openSmelt)");
                return;
            }

            // ⚠️ 熔煉執行不是靠 cmd,而是靠 C_ItemSmelt 封包 (Opcode 250)
            // 在 C_ItemSmelt 裡讀取主材料 objid + 輔助材料 objid,驗證並生成結果
            // 然後回傳 S_ItemSmeltResult 封包給客戶端
            _log.debug("NPCAction: 未知指令 cmd=" + cmd);

        } catch (Exception e) {
            _log.error("Craft/Smelt packet error: " + e.getMessage(), e);
        }
    }



            
            
            
            





   
   
//    @Override
//    public void action(final L1PcInstance pc, final L1NpcInstance npc, final String cmd, final long amount) {
//            npc.setHeading(pc.getHeading());
//            Broadcaster.broadcastPacket(npc, new S_ChangeHeading(npc));
//        try {
//               
//               
//            if (cmd.equalsIgnoreCase("openCrystal")) {
//                      _log.error("MakeCrystal_Window");
//                     pc.sendPackets(new S_ItemSmelt(npc));
//                 return;
//             }
//               
//               
//            // 直接用 cmd 當 Action Name 去查
//            List<T_CraftConfigTable.NewL1NpcMakeItemAction> actions =
//                T_CraftConfigTable.get().getNpcMakeItemActionList(npc.getNpcId(), cmd);
//
//            if (actions != null && !actions.isEmpty()) {
//                for (T_CraftConfigTable.NewL1NpcMakeItemAction action : actions) {
//                    pc.sendPackets(action.getPacket());
//                }
//            } else {
//                pc.sendPackets(new S_NPCTalkReturn(pc.getId(), "smithitem3"));
//            }
//            
//        } catch (Exception e) {
//            _log.error("Craft packet error: " + e.getMessage(), e);
//            pc.sendPackets(new S_NPCTalkReturn(pc.getId(), "smithitem3"));
//        }
//    }


    @Override
    public void spawn(final L1NpcInstance npc) {
        Broadcaster.broadcastPacket(npc,
            new S_NpcChatPacket(npc, "\\fH火神學徒出現了!快來吧!", 2));
        System.out.println("[DEBUG] spawn() 被呼叫, npcId=" + npc.getNpcId());


        // 設定 600 分鐘後自動消失
        GeneralThreadPool.get().schedule(() -> {
            npc.deleteMe();
        }, 3 * 60 * 1000);
    }
   
//    @Override
//    public int type() { return 32 + 4 + 8 + 16 + 2; } // spawn + attack + death + work
   
    @Override
    public int type() {
        // 這裡回傳 NPC 類型代號,對應 NpcExecutor 的 bitmask
        // 2 = NPC 對話執行
        return 2;
    }
}
--------------------------------
結果
【Client → Server】
[C opcode] = 142 [Length] = 16
0000: 8e 61 1b 36 77 6f 70 65 6e 53 6d 65 6c 74 00 00    .a.6wopenSmelt..

→ Opcode = 142
→ 保留 H = 7009
→ 保留 D = 1886353206
→ msgId = 21358
INFO - NPCAction 收到指令: openSmelt
INFO - NPCAction: 打開熔煉 UI (openSmelt)
【Client → Server】
[C opcode] = 250 [Length] = 16
0000: fa 0d 61 1b 36 77 18 05 11 00 24 05 11 00 a0 c9    ..a.6w....$.....

→ Opcode = 250
→ 保留 H = 24845
→ 保留 D = 410465819
→ msgId = 17
DEBUG - Smelt Packet解析: npcObjId=907763981, reservedH=6263, reservedD=603984133, msgId=4357, mainObjId=0, aidObjId=0
WARN - 找不到指定的材料 ObjId (main=0, aid=0)
INFO - SmeltResult: success=false
INFO - Send SmeltResult with subId=61, success=false
---------------------------------
我把道具拖到 榮煉介面之後 有顯示圖案 但是 道具欄沒有扣
只是圖案放上去而已  沒有真正 成功


有沒有大大知道怎麼解決 請大大們 幫幫忙




上一篇︰5/30更新 3.8 登入器(天M天R編碼順跑帶自動練功系統)
下一篇︰請問有大大知道是缺什麼圖嗎
[發帖際遇]: 軒云熊 在論壇發帖時沒有注意,被小偷偷去了 1 金錢. 幸運榜 / 衰神榜

3

主題

1381

帖子

3萬

金錢

安塔瑞斯

紅茶 LINE: lineageapp

Rank: 11Rank: 11Rank: 11Rank: 11

威望
5
精華
0
貢獻
0
鑽石
0
閱讀權限
65
積分
36777
在線時間
1080 小時
相冊
0
日誌
0
好友
0
發表於 2026-5-5 20:15 | 顯示全部樓層
我看了你的版本 裡面本來就有熔煉C包

在C_PledgeContent 13那個 火神精煉

你去改13裡面條件 就可以用了

你沒發現我截圖給你看的 就是你傳的版本嗎

只要改條件就好 不用再新增C包

你改的地方應該是製作吧 才會有Array材料清單

熔煉只有你拉上去的那個 不會用到Array

紅茶
聯絡方式
LINE: lineageapp
回復 支持 反對

使用道具 舉報

30

主題

117

帖子

3725

金錢

暗殺軍王.史雷佛

Rank: 8Rank: 8

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
45
積分
3842
在線時間
128 小時
相冊
0
日誌
0
好友
5
 樓主| 發表於 2026-5-5 21:06 | 顯示全部樓層
yasioukon 發表於 2026-5-5 20:15
我看了你的版本 裡面本來就有熔煉C包

在C_PledgeContent 13那個 火神精煉


yasioukon大大  我看 你發的 照片裡 沒有這樣的訊息

「你不能把東西丟到那麼遠的地方。」


這是東西拉進去之後 在聊天室窗出現的錯誤  訊息  
這有影響嗎?

[發帖際遇]: 軒云熊 撿了錢沒交公 金錢 降了 2 . 幸運榜 / 衰神榜
回復 支持 反對

使用道具 舉報

3

主題

1381

帖子

3萬

金錢

安塔瑞斯

紅茶 LINE: lineageapp

Rank: 11Rank: 11Rank: 11Rank: 11

威望
5
精華
0
貢獻
0
鑽石
0
閱讀權限
65
積分
36777
在線時間
1080 小時
相冊
0
日誌
0
好友
0
發表於 2026-5-5 21:13 | 顯示全部樓層
本帖最後由 yasioukon 於 2026-5-5 21:37 編輯
軒云熊 發表於 2026-5-5 21:06
yasioukon大大  我看 你發的 照片裡 沒有這樣的訊息

「你不能把東西丟到那麼遠的地方。」

單純東西拉太遠的關係

不影響熔煉使用

跟喝水不顯示舒服多了一樣

補丁刪除文字

815.gif


你可以看到 點確定 會正常給東西



這是用你原本C包去測試的

你可能是你DB沒設定 我是有去設定給1個

紅茶
聯絡方式
LINE: lineageapp
回復 支持 反對

使用道具 舉報

30

主題

117

帖子

3725

金錢

暗殺軍王.史雷佛

Rank: 8Rank: 8

威望
0
精華
0
貢獻
0
鑽石
0
閱讀權限
45
積分
3842
在線時間
128 小時
相冊
0
日誌
0
好友
5
 樓主| 發表於 2026-5-5 22:48 | 顯示全部樓層
yasioukon 發表於 2026-5-5 21:13
單純東西拉太遠的關係

不影響熔煉使用

未命8888888999999997名.jpg

成功了  謝謝 yasioukon大大

回復 支持 反對

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 註冊會員

本版積分規則

天堂私服列表

45客服

Archiver| 45天堂私服論壇   分享到微博! 分享到臉書! 分享到噗浪! 分享到維特! 分享到Google+! 分享到LINE!

45天堂私服發佈站 ©    天堂私服架設教學  提供最新天堂私服最新資訊

流量最高、品質最好、服務最優、玩家首選、最新天堂私服資訊,都在45天堂私服發佈站.    免責聲明

Sitetag
line客服聯繫
掃一掃二碼
Line客服聯繫
24H專人回覆
返回頂部 返回列表