Add request server to produce item
This commit is contained in:
@@ -1447,6 +1447,13 @@ namespace CSNetwork.S2CCommand
|
||||
public int idTask;
|
||||
}
|
||||
|
||||
public struct NPCSevMakeItemCONTENT
|
||||
{
|
||||
public int idSkill;
|
||||
public int idItem;
|
||||
public uint dwCount;
|
||||
}
|
||||
|
||||
public struct cmd_sevnpc_serve2
|
||||
{
|
||||
public int service_type;
|
||||
|
||||
@@ -686,6 +686,25 @@ namespace CSNetwork.C2SCommand
|
||||
|
||||
return octets;
|
||||
}
|
||||
|
||||
public static Octets CreateNPCSevMakeItemCmd(int idSkill, int idItem, uint dwCount)
|
||||
{
|
||||
var cmd = new cmd_sevnpc_serve
|
||||
{
|
||||
service_type = NPC_service_type.GP_NPCSEV_MAKEITEM,
|
||||
len = (uint)Marshal.SizeOf<NPCSevMakeItemCONTENT>()
|
||||
};
|
||||
|
||||
NPCSevMakeItemCONTENT content = new NPCSevMakeItemCONTENT()
|
||||
{
|
||||
idSkill = idSkill,
|
||||
idItem = idItem,
|
||||
dwCount = dwCount
|
||||
};
|
||||
|
||||
return SerializeCommand(CommandID.SEVNPC_SERVE, cmd, content);
|
||||
}
|
||||
|
||||
public static Octets CreateEmoteActionCmd(int wPose)
|
||||
{
|
||||
cmd_emote_action pCmd = new cmd_emote_action()
|
||||
|
||||
@@ -1369,6 +1369,30 @@ namespace CSNetwork.GPDataType
|
||||
public byte byPackage;
|
||||
public byte bySlot;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_produce_start
|
||||
{
|
||||
public ushort use_time;
|
||||
public ushort count;
|
||||
public int type;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_produce_once
|
||||
{
|
||||
public int type;
|
||||
public uint amount;
|
||||
public uint slot_amount;
|
||||
public byte where; // Which package: 0 standard, 2 trash, 1 equip
|
||||
public byte index; // Which slot in that package
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_produce_null
|
||||
{
|
||||
public int type;
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct info_matter
|
||||
{
|
||||
|
||||
@@ -512,7 +512,7 @@ namespace CSNetwork
|
||||
break;
|
||||
case CommandID.PICKUP_ITEM:
|
||||
case CommandID.HOST_OBTAIN_ITEM:
|
||||
// case CommandID.PRODUCE_ONCE:
|
||||
case CommandID.PRODUCE_ONCE:
|
||||
case CommandID.TASK_DELIVER_ITEM:
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPITEM, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf,
|
||||
pCmdHeader);
|
||||
@@ -807,6 +807,13 @@ namespace CSNetwork
|
||||
case CommandID.FLYSWORD_TIME:
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_FLYSWORDTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
|
||||
break;
|
||||
case CommandID.PRODUCE_START:
|
||||
case CommandID.PRODUCE_END:
|
||||
case CommandID.PRODUCE_NULL:
|
||||
// Post MSG_HST_PRODUCEITEM message with command ID as parameter (matches C++ behavior)
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PRODUCEITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1254,6 +1261,12 @@ namespace CSNetwork
|
||||
gamedatasend.Data = C2SCommandFactory.CreateNPCSevWaypointCmd(NPC_service_type.GP_NPCSEV_WAYPOINT, 0);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
public void c2s_SendCmdNPCSevMakeItem(int idSkill, int idItem, uint dwCount)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
gamedatasend.Data = C2SCommandFactory.CreateNPCSevMakeItemCmd(idSkill, idItem, dwCount);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
public void GetRoleBaseInfo(int iNumRole, List<int> aRoleIDs)
|
||||
{
|
||||
int iNumLimit = 128;
|
||||
|
||||
@@ -292,6 +292,11 @@ namespace BrewMonster.Network
|
||||
Instance._gameSession.c2s_SendCmdNPCSevWaypoint();
|
||||
}
|
||||
|
||||
public static void c2s_CmdNPCSevMakeItem(int idSkill, int idItem, uint dwCount)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdNPCSevMakeItem(idSkill, idItem, dwCount);
|
||||
}
|
||||
|
||||
public void GetFactionInfo(int iNumFaction, int[] aFactinoIDs)
|
||||
{
|
||||
m_stubbornFactionInfoSender.Add(iNumFaction, aFactinoIDs);
|
||||
|
||||
@@ -9,28 +9,33 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using CSNetwork;
|
||||
|
||||
namespace BrewMonster
|
||||
{
|
||||
public class DlgProduce : AUIDialog
|
||||
{
|
||||
[Header("Produce Tabs")]
|
||||
public Transform tabBtnContainer;
|
||||
public GameObject tabBtnPb;
|
||||
public string tabButtonTextComponentName = "Text";
|
||||
[SerializeField] private Transform tabBtnContainer;
|
||||
[SerializeField] private GameObject tabBtnPb;
|
||||
[SerializeField] private string tabButtonTextComponentName = "Text";
|
||||
|
||||
[Header("Produce Detail")]
|
||||
public Transform itemContainer;
|
||||
public GameObject itemPb;
|
||||
[SerializeField] private Transform itemContainer;
|
||||
[SerializeField] private GameObject itemPb;
|
||||
|
||||
[Header("Material Slots")]
|
||||
public List<Transform> materialSlots = new List<Transform>();
|
||||
[SerializeField] private List<Transform> materialSlots = new List<Transform>();
|
||||
|
||||
[Header("Result Slot")]
|
||||
public Transform itemResult;
|
||||
[SerializeField] private Transform itemResult;
|
||||
|
||||
private NPC_MAKE_SERVICE? cachedMakeService = null;
|
||||
private int currentTabIndex = 0;
|
||||
private uint selectedRecipeId = 0; // Track the currently selected recipe
|
||||
|
||||
[SerializeField] private Button startProduceBtn;
|
||||
[SerializeField] private Button cancelProduceBtn;
|
||||
|
||||
public void OpenProduce(uint npcId)
|
||||
{
|
||||
@@ -40,10 +45,27 @@ namespace BrewMonster
|
||||
return;
|
||||
}
|
||||
|
||||
selectedRecipeId = 0; // Reset selected recipe
|
||||
SetupButtonHandlers();
|
||||
CreateTabs();
|
||||
OnTabSelected(0);
|
||||
}
|
||||
|
||||
void SetupButtonHandlers()
|
||||
{
|
||||
if (startProduceBtn != null)
|
||||
{
|
||||
startProduceBtn.onClick.RemoveAllListeners();
|
||||
startProduceBtn.onClick.AddListener(OnStartProduceClicked);
|
||||
}
|
||||
|
||||
if (cancelProduceBtn != null)
|
||||
{
|
||||
cancelProduceBtn.onClick.RemoveAllListeners();
|
||||
cancelProduceBtn.onClick.AddListener(OnCancelProduceClicked);
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadMakeService(uint npcId)
|
||||
{
|
||||
var edm = ElementDataManProvider.GetElementDataMan();
|
||||
@@ -261,6 +283,7 @@ namespace BrewMonster
|
||||
|
||||
public void ShowRecipeMaterials(uint recipeId)
|
||||
{
|
||||
selectedRecipeId = recipeId; // Track the selected recipe
|
||||
ClearMaterialSlots();
|
||||
|
||||
var edm = ElementDataManProvider.GetElementDataMan();
|
||||
@@ -350,6 +373,37 @@ namespace BrewMonster
|
||||
}
|
||||
}
|
||||
|
||||
void OnStartProduceClicked()
|
||||
{
|
||||
if (selectedRecipeId == 0)
|
||||
{
|
||||
Debug.LogWarning("[DlgProduce] No recipe selected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cachedMakeService.HasValue)
|
||||
{
|
||||
Debug.LogError("[DlgProduce] No make service cached");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get skill ID from the service (not from recipe)
|
||||
// The second parameter is the recipe ID (not the item ID)
|
||||
int idSkill = (int)cachedMakeService.Value.id_make_skill;
|
||||
int idRecipe = (int)selectedRecipeId;
|
||||
uint dwCount = 1; // Default count is 1 (matching C++ code for Win_Produce1)
|
||||
|
||||
// Send the command to the server
|
||||
// Parameters: idSkill (from service), idRecipe (recipe ID), dwCount
|
||||
UnityGameSession.c2s_CmdNPCSevMakeItem(idSkill, idRecipe, dwCount);
|
||||
Debug.Log($"[DlgProduce] Sent make item command: skill={idSkill}, recipe={idRecipe}, count={dwCount}");
|
||||
}
|
||||
|
||||
void OnCancelProduceClicked()
|
||||
{
|
||||
CloseProduce();
|
||||
}
|
||||
|
||||
public void CloseProduce()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
@@ -358,9 +412,51 @@ namespace BrewMonster
|
||||
ClearMaterialSlots();
|
||||
cachedMakeService = null;
|
||||
currentTabIndex = 0;
|
||||
selectedRecipeId = 0;
|
||||
Debug.Log("[DlgProduce] Produce dialog closed");
|
||||
}
|
||||
|
||||
// Called when production starts (NOTIFY_PRODUCE_START)
|
||||
public void OnProduceStart(CSNetwork.GPDataType.cmd_produce_start cmd)
|
||||
{
|
||||
Debug.Log($"[DlgProduce] OnProduceStart: type={cmd.type}, use_time={cmd.use_time}, count={cmd.count}");
|
||||
// TODO: Update progress bar, disable start button, etc.
|
||||
// This would typically start a progress bar showing production time
|
||||
if (startProduceBtn != null)
|
||||
{
|
||||
startProduceBtn.interactable = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Called when one item is produced (NOTIFY_PRODUCE_END_ONE)
|
||||
public void OnProduceOnce(CSNetwork.GPDataType.cmd_produce_once cmd)
|
||||
{
|
||||
Debug.Log($"[DlgProduce] OnProduceOnce: type={cmd.type}, amount={cmd.amount}, where={cmd.where}, index={cmd.index}");
|
||||
// TODO: Update UI counters, progress, skill ability, etc.
|
||||
// This would typically update the remaining count and progress
|
||||
}
|
||||
|
||||
// Called when production ends (NOTIFY_PRODUCE_END)
|
||||
public void OnProduceEnd()
|
||||
{
|
||||
Debug.Log("[DlgProduce] OnProduceEnd: Production completed");
|
||||
// TODO: Re-enable start button, reset progress, etc.
|
||||
if (startProduceBtn != null)
|
||||
{
|
||||
startProduceBtn.interactable = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Called when production fails (NOTIFY_PRODUCE_NULL)
|
||||
public void OnProduceNull(CSNetwork.GPDataType.cmd_produce_null cmd)
|
||||
{
|
||||
Debug.Log($"[DlgProduce] OnProduceNull: type={cmd.type} - Production failed");
|
||||
// TODO: Show error message, re-enable start button, etc.
|
||||
if (startProduceBtn != null)
|
||||
{
|
||||
startProduceBtn.interactable = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
|
||||
@@ -3959,81 +3959,6 @@ MonoBehaviour:
|
||||
m_OnClick:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
--- !u!1 &2703059059040193158
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 7991120577813580350}
|
||||
- component: {fileID: 1861257096977318129}
|
||||
- component: {fileID: 4248307541097962793}
|
||||
m_Layer: 0
|
||||
m_Name: Mask
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &7991120577813580350
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2703059059040193158}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1.6, y: 1.6, z: 1.6}
|
||||
m_ConstrainProportionsScale: 1
|
||||
m_Children: []
|
||||
m_Father: {fileID: 8062547726938481465}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 1, y: 1}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &1861257096977318129
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2703059059040193158}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &4248307541097962793
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2703059059040193158}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 0, g: 0, b: 0, a: 0}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Sprite: {fileID: 0}
|
||||
m_Type: 0
|
||||
m_PreserveAspect: 0
|
||||
m_FillCenter: 1
|
||||
m_FillMethod: 4
|
||||
m_FillAmount: 1
|
||||
m_FillClockwise: 1
|
||||
m_FillOrigin: 0
|
||||
m_UseSpriteMesh: 0
|
||||
m_PixelsPerUnitMultiplier: 1
|
||||
--- !u!1 &2805715107032174497
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -7242,6 +7167,8 @@ MonoBehaviour:
|
||||
- {fileID: 7749576438893503211}
|
||||
- {fileID: 4622013364428910847}
|
||||
itemResult: {fileID: 8891250597797895463}
|
||||
startProduceBtn: {fileID: 104721682242719380}
|
||||
cancelProduceBtn: {fileID: 786694399164181467}
|
||||
--- !u!1 &5819068069398175026
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -8472,7 +8399,6 @@ RectTransform:
|
||||
m_ConstrainProportionsScale: 1
|
||||
m_Children:
|
||||
- {fileID: 8572018612644380183}
|
||||
- {fileID: 7991120577813580350}
|
||||
- {fileID: 6993523375080496617}
|
||||
m_Father: {fileID: 1108604418086848939}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
|
||||
@@ -536,6 +536,9 @@ namespace BrewMonster
|
||||
case int value when value == EC_MsgDef.MSG_HST_PICKUPITEM:
|
||||
OnMsgHstPickupItem(Msg);
|
||||
break;
|
||||
case int value when value == EC_MsgDef.MSG_HST_PRODUCEITEM:
|
||||
OnMsgHstProduceItem(Msg);
|
||||
break;
|
||||
case int value when value == EC_MsgDef.MSG_HST_SELTARGET:
|
||||
OnMsgHstSelTarget(Msg); break;
|
||||
case int value when value == EC_MsgDef.MSG_HST_ATKRESULT: OnMsgHstAttackResult(Msg); break;
|
||||
@@ -2014,9 +2017,100 @@ namespace BrewMonster
|
||||
}
|
||||
|
||||
break;
|
||||
case CommandID.PRODUCE_ONCE:
|
||||
{
|
||||
// Parse cmd_produce_once struct data
|
||||
cmd_produce_once produceCmd = GPDataTypeHelper.FromBytes<cmd_produce_once>(data);
|
||||
|
||||
int produceItemId = produceCmd.type;
|
||||
int produceExpireDate = 0;
|
||||
uint produceAmount = produceCmd.amount;
|
||||
byte producePack = produceCmd.where;
|
||||
byte produceSlot = produceCmd.index;
|
||||
|
||||
// Create new inventory item data
|
||||
var produceNewItem = new EC_IvtrItem
|
||||
{
|
||||
Package = producePack,
|
||||
Slot = produceSlot,
|
||||
m_tid = produceItemId,
|
||||
m_expire_date = produceExpireDate,
|
||||
State = 0,
|
||||
m_iCount = (int)produceAmount,
|
||||
Crc = 0,
|
||||
Content = null
|
||||
};
|
||||
|
||||
// TODO: Handle other pickup item commands if necessary
|
||||
// Add item to inventory
|
||||
var produce_ivt = GetInventory(producePack);
|
||||
if (!produce_ivt.MergeItem(produceItemId, produceExpireDate, (int)produceAmount, out var produceLastSlot, out var produceSlotNum) ||
|
||||
produceLastSlot != produceSlot || produceSlotNum != (int)produceCmd.slot_amount)
|
||||
{
|
||||
Debug.LogWarning($"[PRODUCE_ONCE] Failed to merge item {produceItemId} to package {producePack}, slot {produceSlot}");
|
||||
return;
|
||||
}
|
||||
produce_ivt.SetItem(produceSlot, produceNewItem);
|
||||
|
||||
Debug.Log($"[PRODUCE_ONCE] Successfully added produced item {produceItemId} to package {producePack}, slot {produceSlot} with count {produceAmount}");
|
||||
|
||||
// Trigger UI refresh if an EC_InventoryUI is present in scene
|
||||
var produce_ui = GameObject.FindFirstObjectByType<EC_InventoryUI>();
|
||||
if (produce_ui != null)
|
||||
{
|
||||
produce_ui.RefreshAll();
|
||||
}
|
||||
|
||||
UpdateEquipSkins();
|
||||
|
||||
// Notify DlgProduce about successful produce (NOTIFY_PRODUCE_END_ONE)
|
||||
var dlgProduce = GameObject.FindFirstObjectByType<DlgProduce>();
|
||||
if (dlgProduce != null)
|
||||
{
|
||||
dlgProduce.OnProduceOnce(produceCmd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMsgHstProduceItem(in ECMSG Msg)
|
||||
{
|
||||
var data = Msg.dwParam1 as byte[];
|
||||
int cmd = Convert.ToInt32(Msg.dwParam2);
|
||||
|
||||
// Get DlgProduce to notify
|
||||
var dlgProduce = GameObject.FindFirstObjectByType<DlgProduce>();
|
||||
if (dlgProduce == null)
|
||||
{
|
||||
Debug.LogWarning("[OnMsgHstProduceItem] DlgProduce not found");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case CommandID.PRODUCE_START:
|
||||
{
|
||||
cmd_produce_start pCmd = GPDataTypeHelper.FromBytes<cmd_produce_start>(data);
|
||||
Debug.Log($"[PRODUCE_START] type={pCmd.type}, use_time={pCmd.use_time}, count={pCmd.count}");
|
||||
dlgProduce.OnProduceStart(pCmd);
|
||||
}
|
||||
break;
|
||||
case CommandID.PRODUCE_END:
|
||||
{
|
||||
Debug.Log("[PRODUCE_END] Production ended");
|
||||
dlgProduce.OnProduceEnd();
|
||||
}
|
||||
break;
|
||||
case CommandID.PRODUCE_NULL:
|
||||
{
|
||||
cmd_produce_null pCmd = GPDataTypeHelper.FromBytes<cmd_produce_null>(data);
|
||||
Debug.Log($"[PRODUCE_NULL] type={pCmd.type}");
|
||||
dlgProduce.OnProduceNull(pCmd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Debug.LogWarning($"[OnMsgHstProduceItem] Unknown command: {cmd}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user