Implement 40250 classic client port
This commit is contained in:
@@ -13,9 +13,23 @@
|
||||
# (`OnSelectItemSlot` / `DelPrivateShopItemStock`)。OkButton(`BuildPrivateShop`):stock 按
|
||||
# 格号排序、`display_pos = 格号`、上限 39(`PRIVATE_SHOP_ITEM_MAX_NUM`)打包成
|
||||
# `M2Client.open_private_shop(sign, [{vnum,count,inv_cell,price,display_pos}])`
|
||||
# (= `TPacketCGMyShop` + `TShopItemTable`×N)。철수 `close_private_shop()` = SHOP_CG_END。
|
||||
# (= `TPacketCGMyShop` + `TShopItemTable`×N)。40250 收摊用空的 `CG_MYSHOP`
|
||||
# (服务端 `OpenMyShop` 会先关闭已有的个人摊位);`close_private_shop()` 已在
|
||||
# M2Client classic 分支按该语义发送。
|
||||
extends Node
|
||||
|
||||
class PrivateShopDragButton extends Button:
|
||||
var drag_entry: Dictionary = {}
|
||||
|
||||
func _get_drag_data(_at_position: Vector2):
|
||||
if drag_entry.is_empty():
|
||||
return null
|
||||
var preview := Label.new()
|
||||
preview.text = String(text)
|
||||
preview.add_theme_color_override("font_color", Color(1, 0.9, 0.55))
|
||||
set_drag_preview(preview)
|
||||
return {"private_shop_entry": drag_entry.duplicate(true)}
|
||||
|
||||
const PRIVATE_SHOP_ITEM_MAX := 39 # PRIVATE_SHOP_ITEM_MAX_NUM (TPacketCGMyShop::bCount 上限)
|
||||
const SIGN_MAX := 25 # NameLine input_limit
|
||||
|
||||
@@ -33,6 +47,7 @@ var _status: Label
|
||||
var _stock: Dictionary = {} # 格号:int -> {cell, vnum, count, price}
|
||||
var _picked = null # {cell, vnum, count} 等待落位
|
||||
var _price_dialog: Control = null
|
||||
var _server_prices: Dictionary = {} # vnum -> last price returned by MyShopPriceList
|
||||
|
||||
func setup(m2client: Node, ui_manager: CanvasLayer, proto_node: Node = null, assets := "") -> void:
|
||||
client = m2client
|
||||
@@ -46,6 +61,10 @@ func setup(m2client: Node, ui_manager: CanvasLayer, proto_node: Node = null, ass
|
||||
uiscript_dir = assets_root.path_join("uiscript")
|
||||
if client and client.has_signal("inventory_changed"):
|
||||
client.inventory_changed.connect(func(_w, _c): if is_open(): _refresh())
|
||||
if client and client.has_signal("my_shop_price_list"):
|
||||
client.my_shop_price_list.connect(_on_server_price)
|
||||
if client and client.has_signal("private_shop_open_requested"):
|
||||
client.private_shop_open_requested.connect(open)
|
||||
|
||||
# --- open / close --------------------------------------------------
|
||||
|
||||
@@ -101,6 +120,10 @@ func _index_cells(root: Node) -> void:
|
||||
n.gui_input.connect(func(e: InputEvent) -> void:
|
||||
if e is InputEventMouseButton and e.button_index == MOUSE_BUTTON_LEFT and e.pressed:
|
||||
_on_slot_clicked(idx))
|
||||
# 同时支持从右侧背包候选区拖到空货位;点击选取仍保留给触屏/无鼠标场景。
|
||||
n.set_drag_forwarding(Callable(self, "_no_drag_data"),
|
||||
Callable(self, "_can_drop_slot").bind(idx),
|
||||
Callable(self, "_drop_slot").bind(idx))
|
||||
|
||||
# NameLine 在 uiscript 里是 text(Label)—— 盖一个 LineEdit 上去
|
||||
func _overlay_name_edit(root: Control) -> void:
|
||||
@@ -194,12 +217,13 @@ func _refresh_inv() -> void:
|
||||
continue
|
||||
var vnum := int(it.get("vnum", 0))
|
||||
var count := int(it.get("count", 1))
|
||||
var b := Button.new()
|
||||
var b := PrivateShopDragButton.new()
|
||||
b.text = "%s ×%d" % [_name_of(vnum), count]
|
||||
b.alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||||
b.custom_minimum_size = Vector2(196, 22)
|
||||
b.toggle_mode = true
|
||||
var entry := {"cell": cell, "vnum": vnum, "count": count}
|
||||
b.drag_entry = entry
|
||||
b.pressed.connect(func() -> void: _pick(entry, b))
|
||||
if _picked != null and int(_picked["cell"]) == cell:
|
||||
b.button_pressed = true
|
||||
@@ -246,6 +270,20 @@ func _pick(entry: Dictionary, _btn: Button) -> void:
|
||||
_picked = entry
|
||||
_refresh_grid()
|
||||
|
||||
func _no_drag_data(_at_position: Vector2):
|
||||
return null
|
||||
|
||||
func _can_drop_slot(_at_position: Vector2, data, slot: int) -> bool:
|
||||
return slot >= 0 and slot < 40 and not _stock.has(slot) \
|
||||
and data is Dictionary and data.has("private_shop_entry")
|
||||
|
||||
func _drop_slot(_at_position: Vector2, data, slot: int) -> void:
|
||||
if not _can_drop_slot(Vector2.ZERO, data, slot):
|
||||
return
|
||||
var entry: Dictionary = data["private_shop_entry"] as Dictionary
|
||||
_picked = entry.duplicate(true)
|
||||
_ask_price(slot)
|
||||
|
||||
func _on_slot_clicked(slot: int) -> void:
|
||||
if _stock.has(slot):
|
||||
_stock.erase(slot)
|
||||
@@ -276,7 +314,10 @@ func _ask_price(slot: int) -> void:
|
||||
spin.min_value = 1
|
||||
spin.max_value = 2000000000
|
||||
spin.step = 1
|
||||
spin.value = int(_stock.get(slot, {}).get("price", 1))
|
||||
var default_price := int(_server_prices.get(int(_picked["vnum"]), 1))
|
||||
if _stock.has(slot):
|
||||
default_price = int(_stock[slot].get("price", default_price))
|
||||
spin.value = default_price
|
||||
spin.position = Vector2(12, 40)
|
||||
spin.size = Vector2(216, 28)
|
||||
dlg.add_child(spin)
|
||||
@@ -299,7 +340,7 @@ func _dismiss_price_dialog() -> void:
|
||||
_price_dialog = null
|
||||
|
||||
func _place(slot: int, price: int) -> void:
|
||||
if price <= 0 or _picked == null:
|
||||
if slot < 0 or slot >= 40 or price <= 0 or price > 2000000000 or _picked == null:
|
||||
_dismiss_price_dialog()
|
||||
return
|
||||
_stock[slot] = {"cell": int(_picked["cell"]), "vnum": int(_picked["vnum"]),
|
||||
@@ -308,7 +349,16 @@ func _place(slot: int, price: int) -> void:
|
||||
_dismiss_price_dialog()
|
||||
_refresh()
|
||||
|
||||
func _on_server_price(vnum: int, price: int) -> void:
|
||||
if vnum > 0 and price >= 0:
|
||||
_server_prices[vnum] = price
|
||||
|
||||
func _ok() -> void:
|
||||
var sign := _sign.text.strip_edges()
|
||||
if sign.is_empty() or sign.length() > SIGN_MAX:
|
||||
if is_instance_valid(_status):
|
||||
_status.text = "请输入 1~%d 个字符的摊位名称" % SIGN_MAX
|
||||
return
|
||||
if _stock.is_empty():
|
||||
if is_instance_valid(_status):
|
||||
_status.text = "판매할 아이템을 올리세요"
|
||||
@@ -323,8 +373,10 @@ func _ok() -> void:
|
||||
items.append({"vnum": s["vnum"], "count": s["count"], "inv_cell": s["cell"],
|
||||
"price": s["price"], "display_pos": slot})
|
||||
if client and client.has_method("open_private_shop"):
|
||||
client.open_private_shop(_sign.text.strip_edges(), items)
|
||||
close()
|
||||
if client.open_private_shop(sign, items):
|
||||
close()
|
||||
elif is_instance_valid(_status):
|
||||
_status.text = "摆摊请求发送失败"
|
||||
|
||||
func _close_shop() -> void:
|
||||
if client and client.has_method("close_private_shop"):
|
||||
|
||||
Reference in New Issue
Block a user