# private_shop_system.gd —— 个人私有商店摆摊系统(40250 官方 1:1 对齐) # 对齐源码: # - 40250 server/game/src/char_item.cpp (ITEM_BUNDLE 50200, OpenMyShop) # - 40250 root/uiprivateshopbuilder.py (PrivateShopBuilder) # - 40250 uiscript/privateshopbuilder.py (40 格摊位格) class_name PrivateShopSystem extends RefCounted const VNUM_ITEM_BUNDLE := 50200 # 束发包袱皮 const VNUM_SHOP_HOST_STALL := 30000 # 摆摊木箱/桌子外观模型 Vnum const PRIVATE_SHOP_SLOTS_MAX := 39 # 官方上限 39 件商品 const SIGN_LENGTH_MAX := 25 # 摊位招牌字数上限 ## 检查物品是否为包袱皮 static func is_bundle(vnum: int) -> bool: return vnum == VNUM_ITEM_BUNDLE ## 校验是否能开店 (40250 官方前置条件:非战斗、非骑乘、非死亡) static func can_open_private_shop(is_fighting: bool, is_mounted: bool, is_dead: bool) -> Dictionary: if is_dead: return {"ok": false, "code": "CANNOT_DEAD", "msg": "死亡状态下无法摆摊!"} if is_mounted: return {"ok": false, "code": "CANNOT_MOUNTED", "msg": "骑乘状态下无法摆摊,请先下马!"} if is_fighting: return {"ok": false, "code": "CANNOT_FIGHTING", "msg": "战斗中无法摆摊!"} return {"ok": true} ## 校验摊位招牌名称 static func validate_sign(sign_text: String) -> Dictionary: var trimmed := sign_text.strip_edges() if trimmed.is_empty(): return {"ok": false, "code": "SIGN_EMPTY", "msg": "请输入有效的摊位名称!"} if trimmed.length() > SIGN_LENGTH_MAX: return {"ok": false, "code": "SIGN_TOO_LONG", "msg": "摊位名称不能超过 25 个字符!"} return {"ok": true, "sign": trimmed} ## 验证并将物品上架到摊位 static func add_item_to_stock(stock_dict: Dictionary, slot_idx: int, inv_item: Dictionary, price: int) -> Dictionary: if slot_idx < 0 or slot_idx >= PRIVATE_SHOP_SLOTS_MAX: return {"ok": false, "code": "INVALID_SLOT", "msg": "无效的摊位格子!"} if price <= 0: return {"ok": false, "code": "INVALID_PRICE", "msg": "出售价格必须大于 0 金币!"} if stock_dict.size() >= PRIVATE_SHOP_SLOTS_MAX and not stock_dict.has(slot_idx): return {"ok": false, "code": "SHOP_FULL", "msg": "摊位已达到最大商品容量 (39 件)!"} var cell := int(inv_item.get("cell", -1)) var vnum := int(inv_item.get("vnum", 0)) var count := int(inv_item.get("count", 1)) stock_dict[slot_idx] = { "slot": slot_idx, "cell": cell, "vnum": vnum, "count": count, "price": price, } return { "ok": true, "code": "SUCCESS", "slot": slot_idx, "price": price, "msg": "商品成功上架到摊位第 %d 格,单价 %d 金币。" % [slot_idx + 1, price] } ## 撤下摊位商品 static func remove_item_from_stock(stock_dict: Dictionary, slot_idx: int) -> bool: if stock_dict.has(slot_idx): stock_dict.erase(slot_idx) return true return false ## 开市创建摆摊实体 static func build_private_shop(sign_text: String, stock_dict: Dictionary, stall_pos: Vector3) -> Dictionary: var v_sign := validate_sign(sign_text) if not bool(v_sign.get("ok", false)): return v_sign if stock_dict.is_empty(): return {"ok": false, "code": "NO_ITEMS", "msg": "摊位上没有任何商品,无法开市!"} return { "ok": true, "code": "SHOP_OPENED", "stall_vnum": VNUM_SHOP_HOST_STALL, "sign": v_sign.get("sign", ""), "items_count": stock_dict.size(), "position": stall_pos, "msg": "【%s】正式开市!摊位已在当前位置建立。" % v_sign.get("sign", "") }