/*
文件名:FatalismStone.nut
路径:Dps_A/ProjectClass/FatalismStone/FatalismStone.nut
创建日期:2025-06-22	12:54
文件用途:
*/


class FatalismStone_Stone {
    //编号
    Id = null;
    //唯一ID
    Uuid = null;
    //类型
    StoneType = null;
    //洗练度
    CultivationDegree = null;


    constructor() {

    }


    //反序列化构造
    function Deserialize(StoneId, StoneUuid) {
        this.Id = StoneId;
        this.Uuid = StoneUuid;
        this.StoneType = ProjectInitFuncMap.P_FatalismStone.GetStoneData(this.Id)["stone type"];
    }

    function Blob2Hex(buf) {
        local str = "";
        for (local i = 0; i< buf.len(); i++) {
            str += format("%02X", buf[i]);
        }
        return str;
    }

    function Serialize() {
        local B = blob(0);
        B.writen(Id, 'i'); //写入ID
        B.writen(Uuid, 'i'); //写入Uuid
        return Blob2Hex(B);
    }
}

//魂石背包类
class FatalismStone_BackPack {

    //背包总格子数
    GridCount = 77;
    //穿戴总格子数
    WearCount = 6;
    StoneArr = null;

    constructor() {
        StoneArr = [];
    }

    //通过数据构造背包  反序列化
    function Deserialize(N_Data) {
        local BackpackData = N_Data[0][0];
        local WearData = N_Data[0][1];

        //转换背包数据
        local BackPackArr = [];
        for (local i = 0; i<(GridCount * 3); i++) {
            local StoneId = BackpackData.add(i * 8).readInt();
            local StoneUuid = BackpackData.add(i * 8 + 4).readInt();
            if (StoneId != 0 && StoneUuid != 0) {
                local StoneObj = FatalismStone_Stone();
                StoneObj.Deserialize(StoneId, StoneUuid)
                BackPackArr.push(StoneObj);
            } else {
                BackPackArr.push(null);
            }
        }
        //转化穿戴数据
        local WearArr = [];
        for (local i = 0; i< WearCount; i++) {
            local StoneId = WearData.add(i * 8).readInt();
            local StoneUuid = WearData.add(i * 8 + 4).readInt();
            if (StoneId != 0 && StoneUuid != 0) {
                local StoneObj = FatalismStone_Stone();
                StoneObj.Deserialize(StoneId, StoneUuid)
                WearArr.push(StoneObj);
            } else {
                WearArr.push(null);
            }
        }

        //两段数据放入总数据
        StoneArr.extend(BackPackArr);
        StoneArr.extend(WearArr);
    }

    //序列化
    function Serialize() {
        //背包数据
        local BackpackArr = StoneArr.slice(0, GridCount * 3);
        local BackpackHex = "0x";
        foreach(Pos, StoneObject in BackpackArr) {
            if (StoneObject) BackpackHex += StoneObject.Serialize();
            else BackpackHex += "0000000000000000";
        }
        //穿戴数据
        local WearArr = StoneArr.slice(GridCount * 3, GridCount * 3 + WearCount);
        local WearHex = "0x";
        foreach(Pos, StoneObject in WearArr) {
            if (StoneObject) WearHex += StoneObject.Serialize();
            else WearHex += "0000000000000000";
        }
        //返回
        return {
            inventory = BackpackHex,
            wear = WearHex
        };
    }

    //获取魂石的列表 3为身上穿戴的
    function GetList(Page) {
        local SliceLength = GridCount;
        if (Page == 3) SliceLength = WearCount;
        return StoneArr.slice(Page * 77, Page * 77 + SliceLength);
    }
}

class FatalismStone {

    //总格子数
    GridCount = 77;
    //总穿戴数
    WearCount = 6;

    //属性数据位数
    AttrCount = 2;

    //魂石Lst
    FatalismStoneLst = null;
    //魂石配置
    FatalismStoneConfig = null;

    constructor() {
        Script();
        local PoolObj = MysqlPool.GetInstance();
        PoolObj.SetBaseConfiguration("127.0.0.1", 3306, "game", "uu5!^%jg");
        //连接池大小
        PoolObj.PoolSize = 10;
        //初始化
        PoolObj.Init();

        //读取pvf的魂石相关数据
        InitFatalismStoneData();

        //创建新架构表
        SelectSql("CREATE TABLE `zyk`.`f_user_info`  (  `cid` int(250) NOT NULL,  `inventory` varbinary(1848) NULL,  `wear` varbinary(48) NULL,  PRIMARY KEY (`cid`));", []);
        SelectSql("CREATE TABLE `zyk`.`f_stone_map`  (  `uuid` int(250) NOT NULL AUTO_INCREMENT,  `cultivation` float NULL DEFAULT NULL,  PRIMARY KEY (`uuid`)  USING BTREE);", []);
        // UpdateNewMysqlData();



        //注册客户端收包
        RegisterClient();
        //注册调试命令
        RegisterDebugCmd();
    }


    //查询单个魂石的属性
    function GetStoneAttr(Uuid) {
        local Ret = SelectSql("select cultivation from zyk.f_stone_map where uuid = " + Uuid, ["float"]);
        if (Ret.len() == 0) {
            return null;
        } else {
            return Ret[0];
        }
    }

    //查询多个魂石的属性
    function GetStoneAttrArr(UuidArr) {
        local SqlStr = "select uuid,cultivation from zyk.f_stone_map where uuid in (";
        for (local i = 0; i< UuidArr.len(); i++) {
            SqlStr += UuidArr[i];
            if (i != UuidArr.len() - 1) {
                SqlStr += ",";
            }
        }
        SqlStr += ")";
        local Ret = SelectSql(SqlStr, ["int", "float"]);
        if (Ret.len() == 0) {
            return null;
        } else {
            return Ret;
        }
    }


    function RegisterClient() {

        //查询魂石背包数据
        ClientSocketPackFuncMap.rawset(21000001, function(SUser, Jso) {
            local Ret = GetInvenData(SUser);
            //没查到东西说明没有背包 第一次创建背包
            if (Ret.len() == 0) {
                local SqlStr = format("INSERT INTO zyk.f_user_info (cid, inventory, wear) VALUES (%d,REPEAT(0x00, 1848),REPEAT(0x00, 48))", SUser.GetCID());
                SelectSql(SqlStr, []);
            }
            //有数据的读取
            else {
                local BackPackData = Ret[0][0];
                local WearData = Ret[0][1];
                local PackSize = 4 + 4 + BackPackData.Size + 4 + WearData.Size;
                local Pack = Packet();
                Pack.Put_Header(1, 131);
                Pack.Put_Byte(1);
                Pack.Put_Int(PackSize);
                Pack.Put_Int(21000002);
                Pack.Put_Int(BackPackData.Size);
                Pack.Put_BinaryEx(BackPackData.C_Object, BackPackData.Size);
                Pack.Put_Int(WearData.Size);
                Pack.Put_BinaryEx(WearData.C_Object, WearData.Size);
                Pack.Finalize(true);
                SUser.Send(Pack);
                Pack.Delete();

                //查询身上穿戴的魂石属性
                local BackPack = FatalismStone_BackPack();
                BackPack.Deserialize(Ret);
                local WearArr = BackPack.GetList(3);
                local UuidArr = [];
                for (local i = 0; i< WearArr.len(); i++) {
                    if (WearArr[i] != null) {
                        UuidArr.push(WearArr[i].Uuid);
                    }
                }
                if (UuidArr.len() > 0) {
                    local Attr = GetStoneAttrArr(UuidArr);
                    if (Attr) {
                        local PackSize = 4 + 4 + (Attr.len() * 4 * Attr[0].len());
                        local Pack = Packet();
                        Pack.Put_Header(1, 131);
                        Pack.Put_Byte(1);
                        Pack.Put_Int(PackSize);
                        Pack.Put_Int(21000014);
                        Pack.Put_Int(Attr.len());
                        for (local i = 0; i< Attr.len(); i++) {
                            for (local z = 0; z< Attr[i].len(); z++) {
                                Pack.Put_Int(Attr[i][z]);
                            }
                        }
                        Pack.Finalize(true);
                        SUser.Send(Pack);
                        Pack.Delete();
                    }
                }
            }
        }.bindenv(this));

        //查询魂石唯一属性
        ClientSocketPackFuncMap.rawset(21000011, function(SUser, Jso) {
            local Uuid = Jso.uuid;
            SendFatalismStoneData(SUser, Uuid);
        }.bindenv(this));

        //交换魂石位置
        ClientSocketPackFuncMap.rawset(21000003, function(SUser, Jso) {
            local OldType = Jso.oldtype;
            local OldIndex = Jso.oldpos;

            local NewType = Jso.newtype;
            local NewIndex = Jso.newpos;

            local BackPack = GetInven(SUser);
            if (!BackPack) return;

            //直接去交换位置
            local Buffer = BackPack.StoneArr[OldType * 77 + OldIndex];
            BackPack.StoneArr[OldType * 77 + OldIndex] = BackPack.StoneArr[NewType * 77 + NewIndex];
            BackPack.StoneArr[NewType * 77 + NewIndex] = Buffer;

            SaveInven(BackPack, SUser);
        }.bindenv(this));

        //魂石洗练
        ClientSocketPackFuncMap.rawset(21000005, function(SUser, Jso) {
            local Uuid = Jso.uuid;
            local rarity = Jso.rarity;
            //获取背包对象
            local InvenObj = SUser.GetInven();
            local Flag = InvenObj.DeleteItemCount(FatalismStoneConfig["wash_item"], FatalismStoneConfig["wash_cost"][rarity]);
            //扣除不成功
            if (!Flag) {
                SUser.SendNotiPacketMessage("精炼魂石所需的材料不足!", 8);
                return;
            }

            local Rand = MathClass.Rand(1, 105);
            if (Rand > 100) Rand = 100;

            //将新的精炼值写入数据库
            local Sql = "update zyk.f_stone_map set cultivation = " + Rand + " where uuid = " + Uuid;
            SelectSql(Sql, []);
            SendFatalismStoneData(SUser, Uuid)
        }.bindenv(this));

        Cb_User_Insert_Item_Leave_Func["宿命魂石"] <- function(args) {
            local SUser = User(NativePointer(args[0]).readPointer());
            local InvenObj = SUser.GetInven();
            local idx = args.pop();
            if (idx > 0) {
                local inven_item = InvenObj.GetSlot(1, idx);
                local item_id = inven_item.GetIndex();
                if (item_id >= 200625000 && item_id< 200626000) {
                    local Ret = AddFatalismStone(SUser, item_id - 200625000);
                    //删除原道具
                    Timer.SetTimeOut(function() {
                        inven_item.Delete();
                        SUser.SendUpdateItemList(1, 0, idx);
                    }, 1000);
                    //如果满了就发邮件
                    if (!Ret) {
                        local T = {};
                        T.rawset(item_id, 1);
                        SUser.SendMail(T, {
                            Title = "系统",
                            Text = "由于你的魂石包裹已满, 请留出足够的空间来接收道具."
                        });
                    }
                    SUser.SendItemSpace(0);
                }
            }
        }.bindenv(this);
    }


    function RegisterDebugCmd() {
        Gm_InputFunc_Handle["给魂石"] <- function(SUser, CmdString) {
            local count = -1;
            local pos = 0;
            local handler = [];
            do {
                local start = pos;
                pos = CmdString.find(" ", pos + 1);
                if (pos != null) {
                    handler.append(CmdString.slice(start + 1, pos));
                } else
                    handler.append(CmdString.slice(start + 1));
                count = count + 1
            } while (pos != null)

            //得到空格数量
            if (count == 1) {
                AddFatalismStone(SUser, handler[1].tointeger());
            }
        }.bindenv(this);
    }

    //获取玩家背包数据
    function GetInvenData(SUser) {
        local Ret = SelectSql("select inventory,wear from zyk.f_user_info where cid = " + SUser.GetCID(), ["binary", "binary"]);
        if (!Ret || Ret.len() == 0) return null;
        else return Ret;
    }

    //获取玩家背包
    function GetInven(SUser) {
        local Ret = GetInvenData(SUser);
        if (Ret) {
            local BackPack = FatalismStone_BackPack();
            BackPack.Deserialize(Ret);
            return BackPack;
        } else return null;
    }

    //固化背包数据到数据库
    function SaveInven(Inven, SUser) {
        //获取背包整体信息并储存
        local Hex = Inven.Serialize();
        //更新数据库
        local Sql = "update zyk.f_user_info set inventory = " + Hex.inventory + ",wear = " + Hex.wear + " where cid = " + SUser.GetCID();
        SelectSql(Sql, []);
    }

    //发送uuid的魂石数据给客户端
    function SendFatalismStoneData(SUser, Uuid) {
        local Attr = GetStoneAttr(Uuid);
        if (!Attr) {
            SUser.SendNotiPacketMessage("魂石属性异常,请联系管理员！", 8);
        } else {
            local Cultivation = Attr[0];
            local PackSize = 4 + 4 + 4;
            local Pack = Packet();
            Pack.Put_Header(1, 131);
            Pack.Put_Byte(1);
            Pack.Put_Int(PackSize);
            Pack.Put_Int(21000012);
            Pack.Put_Int(Uuid);
            Pack.Put_Int(Cultivation);
            Pack.Finalize(true);
            SUser.Send(Pack);
            Pack.Delete();
        }
    }

    //给指定玩家新增魂石
    function AddFatalismStone(SUser, FatalismStoneID) {
        local CID = SUser.GetCID();


    }


    function InitFatalismStoneData() {
        // Script();
        FatalismStoneLst = {};
        ScriptData.GetFileData("fatalismstone/fatalismstone.lst", function(DataTable, Data) {
            while (!Data.Eof()) {
                local Id = Data.Get();
                local Path = Data.Get();
                FatalismStoneLst.rawset(Id, Path);
            }
        }.bindenv(this));

        FatalismStoneConfig = ScriptData.GetFileData("fatalismstone/fatalismstone.etc", function(DataTable, Data) {
            while (!Data.Eof()) {
                local Str = Data.Get();
                if (Str == "[wash item]") {
                    DataTable.wash_item <- Data.Get();
                } else if (Str == "[wash cost]") {
                    DataTable.wash_cost <- [Data.Get(), Data.Get(), Data.Get(), Data.Get(), Data.Get(), Data.Get(), Data.Get()];
                }
            }
        }.bindenv(this));
    }

    function GetStoneData(Index) {
        if (FatalismStoneLst.rawin(Index)) {
            //还是路径就读取数据
            if (typeof FatalismStoneLst[Index] == "string") {
                FatalismStoneLst[Index] = ScriptData.GetFileData("fatalismstone/" + FatalismStoneLst[Index], function(DataTable, Data) {
                    DataTable.Attribute <- {};
                    while (!Data.Eof()) {
                        local Key = Data.Get();
                        if (Key == "[rarity]" || Key == "[stone type]" || Key == "[move wav]" || Key == "[front effect]" || Key == "[back effect]") {
                            DataTable[Key.slice(1, -1)] <- Data.Get();
                        } else if (Key == "[icon]") {
                            DataTable.icon <- {
                                img = Data.Get(),
                                index = Data.Get()
                            }
                        }
                    }
                });
            }
            return FatalismStoneLst[Index];
        } else error("没有ID为: " + Index + " 的魂石数据！");
    }






























































    //执行数据库命令
    function SelectSql(Sql, Type) {
        local SqlObj = MysqlPool.GetInstance().GetConnect();
        local Ret = SqlObj.Select(Sql, Type);
        //把连接还池子
        MysqlPool.GetInstance().PutConnect(SqlObj);
        return Ret;
    }


    //UpdateNewMysqlData
    function UpdateNewMysqlData() {

        local Ret = SelectSql("select * from zyk.fatalismstone", ["int", "binary", "binary"]);

        foreach(Index, Info in Ret) {
            local cid = Info[0];
            local inventory = Info[1];
            local wear = Info[2];

            //处理背包里的魂石
            local NewBlob = blob();
            for (local i = 0; i< 462; i += 2) {
                local item_id = inventory.add(i * 4).readInt();
                local cultivation = inventory.add(i * 4 + 4).readInt();
                if (item_id > 0) {
                    //在新表中建立这件装备的uuid
                    local Sql = "insert into zyk.f_stone_map (cultivation) values (" + cultivation + ")";
                    SelectSql(Sql, []);
                    //查询最后新增条目的uuid
                    Sql = "select LAST_INSERT_ID() as uuid";
                    local uuid = SelectSql(Sql, ["int"])[0][0];

                    NewBlob.writen(item_id, 'i');
                    NewBlob.writen(uuid, 'i');
                } else {
                    NewBlob.writen(0, 'i');
                    NewBlob.writen(0, 'i');
                }
            }
            local inventoryBinary = "0x" + Blob2Hex(NewBlob);

            //处理身上穿戴的魂石
            NewBlob.resize(0);
            for (local i = 0; i< 12; i += 2) {
                local item_id = wear.add(i * 4).readInt();
                print(item_id);

                local cultivation = wear.add(i * 4 + 4).readInt();
                if (item_id > 0) {
                    //在新表中建立这件装备的uuid
                    local Sql = "insert into zyk.f_stone_map (cultivation) values (" + cultivation + ")";
                    SelectSql(Sql, []);
                    //查询最后新增条目的uuid
                    Sql = "select LAST_INSERT_ID() as uuid";
                    local uuid = SelectSql(Sql, ["int"])[0][0];

                    NewBlob.writen(item_id, 'i');
                    NewBlob.writen(uuid, 'i');
                } else {
                    NewBlob.writen(0, 'i');
                    NewBlob.writen(0, 'i');
                }
            }
            local wearBinary = "0x" + Blob2Hex(NewBlob);

            local Sql = "insert into zyk.f_user_info (cid,inventory, wear) values (" + cid + "," + inventoryBinary + "," + wearBinary + ")";
            SelectSql(Sql, []);
        }
    }

    function Blob2Hex(buf) {
        local str = "";
        for (local i = 0; i< buf.len(); i++) {
            str += format("%02X", buf[i]);
        }
        return str;
    }
}




ProjectInitFuncMap.P_FatalismStone <- FatalismStone();