Golang中resp.Insert操作问题求解

Golang中resp.Insert操作问题求解 你好,

我正在开发一款游戏,遇到了一个问题。 我找不到索引插入的顺序,过去一周这让我非常困扰。 请提供任何帮助,我将不胜感激。

这是第一个代码片段:

在这个函数中,resp.Insert 用于 TITLE 的部分工作正常:

func (c *Character) SpawnCharacter() ([]byte, error) {

	if c == nil {
		return nil, nil
	}
	if c.Socket == nil || c.Socket.Stats == nil {
		return nil, nil
	}

	resp := CHARACTER_SPAWNED
	index := 6
	resp.Insert(utils.IntToBytes(uint64(c.PseudoID), 2, true), index) // character pseudo id
	index += 2
	resp.Insert([]byte{0xee, 0x22, 0x00, 0x00}, index)
	index += 4
	if c.IsActive {
		resp.Insert([]byte{0x03, 0x00, 0x00, 0x00, 0x00}, index)
	} else {
		resp.Insert([]byte{0x04, 0x00, 0x00, 0x00, 0x00}, index)
	}
	index += 5

	if c.DuelID > 0 {
		resp.Overwrite(utils.IntToBytes(500, 2, true), 13) // duel state
	}

	resp.Insert(utils.IntToBytes(uint64(len(c.Name)), 1, true), index)
	index++
	resp.Insert([]byte(c.Name), index) // character name
	index += len(c.Name)
	resp.Insert(utils.IntToBytes(uint64(c.Level), 4, true), index)
	index += 4
	resp.Insert([]byte{byte(c.Type), byte(c.Class)}, index) // character type-class
	index += 2
	resp.Insert([]byte{0x01, 0x00, 0x20, 0x1c, 0x00, 0x00, 0x00}, index)
	index += 7

	coordinate := ConvertPointToLocation(c.Coordinate)
	resp.Insert(utils.FloatToBytes(coordinate.X, 4, true), index) // coordinate-x
	index += 4

	resp.Insert(utils.FloatToBytes(coordinate.Y, 4, true), index) // coordinate-y
	index += 4

	resp.Insert([]byte{0x00, 0x00, 0x60, 0x41}, index)
	index += 4

	resp.Insert(utils.FloatToBytes(coordinate.X, 4, true), index) // coordinate-x
	index += 4

	resp.Insert(utils.FloatToBytes(coordinate.Y, 4, true), index) // coordinate-y
	index += 4
	resp.Insert([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}, index)
	index += 10
	resp.Insert(utils.IntToBytes(uint64(c.Socket.Stats.Honor), 4, true), index) // HONOR
	index += 4
	resp.Insert([]byte{0xc8, 0x00, 0x00, 0x00}, index)
	index += 4

	resp.Insert(utils.IntToBytes(uint64(c.Socket.Stats.HP), 4, true), index) // hp
	index += 4
	resp.Insert([]byte{0x00, 0x00, 0x00, 0x00, 0x00}, index)
	index += 5
	resp.Insert(utils.IntToBytes(uint64(c.WeaponSlot), 1, true), index)
	index++
	resp.Insert([]byte{0xf2, 0x03}, index)
	index += 2
	resp.Insert(utils.IntToBytes(uint64(c.BattleMode), 1, true), index) //battle mode
	index++
	resp.Insert([]byte{0x00, 0x00, 0x05}, index)
	index += 3
	if c.Morphed {
		resp.Insert(utils.IntToBytes(uint64(c.MorphedNPCID), 4, true), index)
		index += 4
	} else {
		resp.Insert([]byte{0x00, 0x00, 0x00, 0x00}, index)
		index += 4
	}
	//index += 5
	**resp.Insert(utils.IntToBytes(uint64(c.HonorRank), 4, true), index) // TITLE **
	index += 4
	resp.Insert(utils.IntToBytes(uint64(c.Type), 1, true), index)
	index++
	resp.Insert(utils.IntToBytes(uint64(c.GuildID), 4, true), index) // guild id
	index += 4
	resp.Insert([]byte{0x01, 0x00, 0x00, 0x00}, index)
	index += 4
	resp.Insert([]byte{byte(c.Faction)}, index) // character faction
	index++
	resp.Insert([]byte{0x00, 0x00, 0x00, 0x00, 0x64, 0xff, 0xff, 0xff, 0xff}, index)
	index += 9
	items, err := c.ShowItemsByCharacter()
	if err != nil {
		return nil, err
	}

	itemsData := items
	sale := FindSale(c.PseudoID)
	if sale != nil {
		itemsData = []byte{0x05, 0xAA, 0x45, 0xF1, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x6C, 0xF1, 0x00, 0x01, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	}
	//myString := hex.EncodeToString(itemsData)
	//log.Print("String:", myString)
	resp.Insert(itemsData, index)
	index += len(itemsData)

	if sale != nil {
		resp.Insert([]byte{0x02}, index) // sale indicator
		index++

		resp.Insert([]byte{byte(len(sale.Name))}, index) // sale name length
		index++

		resp.Insert([]byte(sale.Name), index) // sale name
		index += len(sale.Name)

		resp.Insert([]byte{0x00}, index)
		index++
	}
	resp.SetLength(int16(binary.Size(resp) - 6))
	dataItems, _ := c.ShowItems()
	resp.Concat(dataItems) // FIX => workaround for weapon slot

	if c.GuildID > 0 {
		guild, err := FindGuildByID(c.GuildID)
		if err == nil && guild != nil {
			resp.Concat(guild.GetInfo())
		}
	}

	STYLE_MENU := utils.Packet{0xaa, 0x55, 0x0d, 0x00, 0x01, 0xb5, 0x0a, 0x00, 0x00, 0x55, 0xaa}
	styleresp := STYLE_MENU
	styleresp[8] = byte(0x02)
	index = 9
	headitem, ok := GetItemInfo(c.HeadStyle)
	if !ok || headitem == nil {
		c.HeadStyle = 0
	}
	faceitem, ok := GetItemInfo(c.FaceStyle)
	if !ok || faceitem == nil {
		c.FaceStyle = 0
	}

	styleresp.Insert(utils.IntToBytes(uint64(c.HeadStyle), 4, true), index)
	index += 4
	styleresp.Insert(utils.IntToBytes(uint64(c.FaceStyle), 4, true), index)
	index += 4
	resp.Concat(styleresp)

	c.DeleteAura()

	return resp, nil
}

然而,当我尝试在这个简化版本中实现它时,它告诉我顺序错误,游戏就会出现问题:

func (c *Character) SpawnCharacter() ([]byte, error) {

	if c == nil {
		return nil, nil
	}

	resp := CHARACTER_SPAWNED
	resp.Insert(utils.IntToBytes(uint64(c.PseudoID), 2, true), 6) // character pseudo id
	if c.IsActive {
		resp[12] = 3
	} else {
		resp[12] = 4
	}

	/*
		if c.DuelID > 0 {
			resp.Overwrite(utils.IntToBytes(500, 2, true), 13) // duel state
		}
	*/

	resp[17] = byte(len(c.Name))    // character name length
	resp.Insert([]byte(c.Name), 18) // character name

	index := len(c.Name) + 18 + 4
	resp[index] = byte(c.Type) // character type
	index += 1

	index += 8

	coordinate := ConvertPointToLocation(c.Coordinate)
	resp.Insert(utils.FloatToBytes(coordinate.X, 4, true), index) // coordinate-x
	index += 4

	resp.Insert(utils.FloatToBytes(coordinate.Y, 4, true), index) // coordinate-y
	index += 8

	resp.Insert(utils.FloatToBytes(coordinate.X, 4, true), index) // coordinate-x
	index += 4

	resp.Insert(utils.FloatToBytes(coordinate.Y, 4, true), index) // coordinate-y
	index += 4
	index += 18

	resp.Overwrite(utils.IntToBytes(uint64(c.Socket.Stats.HP), 4, true), index) // hp
	index += 9

	resp[index] = byte(c.WeaponSlot) // weapon slot
	index += 16

	resp.Insert(utils.IntToBytes(uint64(c.GuildID), 4, true), index) // guild id
	index += 8

	**resp.Insert(utils.IntToBytes(uint64(c.HonorRank), 4, true), index) // TITLE**
	index += 4

	resp[index] = byte(c.Faction) // character faction
	index += 10

	items, err := c.ShowItems()
	if err != nil {
		return nil, err
	}

	itemsData := items[11 : len(items)-2]
	sale := FindSale(c.PseudoID)
	if sale != nil {
		itemsData = []byte{0x05, 0xAA, 0x45, 0xF1, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x6C, 0xF1, 0x00, 0x01, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
	}

	resp.Insert(itemsData, index)
	index += len(itemsData)

	length := int16(len(itemsData) + len(c.Name) + 111)

	if sale != nil {
		resp.Insert([]byte{0x02}, index) // sale indicator
		index++

		resp.Insert([]byte{byte(len(sale.Name))}, index) // sale name length
		index++

		resp.Insert([]byte(sale.Name), index) // sale name
		index += len(sale.Name)

		resp.Insert([]byte{0x00}, index)
		index++
		length += int16(len(sale.Name) + 3)
	}

	resp.SetLength(length)
	resp.Concat(items) // FIX => workaround for weapon slot

	if c.GuildID > 0 {
		guild, err := FindGuildByID(c.GuildID)
		if err == nil && guild != nil {
			resp.Concat(guild.GetInfo())
		}
	}

	return resp, nil
}

更多关于Golang中resp.Insert操作问题求解的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中resp.Insert操作问题求解的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题在于第二个简化版本中的索引计算不准确,导致数据插入位置错误。resp.Insert 操作需要精确的字节偏移量,而硬编码的索引值在数据结构变化时容易出错。

以下是修复后的关键部分,使用动态索引跟踪:

func (c *Character) SpawnCharacter() ([]byte, error) {
    if c == nil {
        return nil, nil
    }

    resp := CHARACTER_SPAWNED
    index := 6
    
    // 伪ID
    resp.Insert(utils.IntToBytes(uint64(c.PseudoID), 2, true), index)
    index += 2
    
    // 状态标志
    resp.Insert([]byte{0xee, 0x22, 0x00, 0x00}, index)
    index += 4
    
    // 活动状态
    if c.IsActive {
        resp.Insert([]byte{0x03, 0x00, 0x00, 0x00, 0x00}, index)
    } else {
        resp.Insert([]byte{0x04, 0x00, 0x00, 0x00, 0x00}, index)
    }
    index += 5
    
    // 名称
    resp.Insert(utils.IntToBytes(uint64(len(c.Name)), 1, true), index)
    index++
    resp.Insert([]byte(c.Name), index)
    index += len(c.Name)
    
    // 等级和类型
    resp.Insert(utils.IntToBytes(uint64(c.Level), 4, true), index)
    index += 4
    resp.Insert([]byte{byte(c.Type), byte(c.Class)}, index)
    index += 2
    
    // 固定字节
    resp.Insert([]byte{0x01, 0x00, 0x20, 0x1c, 0x00, 0x00, 0x00}, index)
    index += 7
    
    // 坐标
    coordinate := ConvertPointToLocation(c.Coordinate)
    resp.Insert(utils.FloatToBytes(coordinate.X, 4, true), index)
    index += 4
    resp.Insert(utils.FloatToBytes(coordinate.Y, 4, true), index)
    index += 4
    
    resp.Insert([]byte{0x00, 0x00, 0x60, 0x41}, index)
    index += 4
    
    resp.Insert(utils.FloatToBytes(coordinate.X, 4, true), index)
    index += 4
    resp.Insert(utils.FloatToBytes(coordinate.Y, 4, true), index)
    index += 4
    
    // 固定字节
    resp.Insert([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}, index)
    index += 10
    
    // 荣誉
    resp.Insert(utils.IntToBytes(uint64(c.Socket.Stats.Honor), 4, true), index)
    index += 4
    
    resp.Insert([]byte{0xc8, 0x00, 0x00, 0x00}, index)
    index += 4
    
    // HP
    resp.Insert(utils.IntToBytes(uint64(c.Socket.Stats.HP), 4, true), index)
    index += 4
    
    resp.Insert([]byte{0x00, 0x00, 0x00, 0x00, 0x00}, index)
    index += 5
    
    // 武器槽和战斗模式
    resp.Insert(utils.IntToBytes(uint64(c.WeaponSlot), 1, true), index)
    index++
    resp.Insert([]byte{0xf2, 0x03}, index)
    index += 2
    resp.Insert(utils.IntToBytes(uint64(c.BattleMode), 1, true), index)
    index++
    resp.Insert([]byte{0x00, 0x00, 0x05}, index)
    index += 3
    
    // 变形状态
    if c.Morphed {
        resp.Insert(utils.IntToBytes(uint64(c.MorphedNPCID), 4, true), index)
    } else {
        resp.Insert([]byte{0x00, 0x00, 0x00, 0x00}, index)
    }
    index += 4
    
    // 荣誉等级(TITLE)- 关键修复
    resp.Insert(utils.IntToBytes(uint64(c.HonorRank), 4, true), index)
    index += 4
    
    // 类型和公会ID
    resp.Insert(utils.IntToBytes(uint64(c.Type), 1, true), index)
    index++
    resp.Insert(utils.IntToBytes(uint64(c.GuildID), 4, true), index)
    index += 4
    
    resp.Insert([]byte{0x01, 0x00, 0x00, 0x00}, index)
    index += 4
    
    // 阵营
    resp.Insert([]byte{byte(c.Faction)}, index)
    index++
    
    resp.Insert([]byte{0x00, 0x00, 0x00, 0x00, 0x64, 0xff, 0xff, 0xff, 0xff}, index)
    index += 9
    
    // 物品数据
    items, err := c.ShowItemsByCharacter()
    if err != nil {
        return nil, err
    }
    
    itemsData := items
    sale := FindSale(c.PseudoID)
    if sale != nil {
        itemsData = []byte{0x05, 0xAA, 0x45, 0xF1, 0x00, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x6C, 0xF1, 0x00, 0x01, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
    }
    
    resp.Insert(itemsData, index)
    index += len(itemsData)
    
    if sale != nil {
        resp.Insert([]byte{0x02}, index)
        index++
        resp.Insert([]byte{byte(len(sale.Name))}, index)
        index++
        resp.Insert([]byte(sale.Name), index)
        index += len(sale.Name)
        resp.Insert([]byte{0x00}, index)
        index++
    }
    
    resp.SetLength(int16(binary.Size(resp) - 6))
    
    dataItems, _ := c.ShowItems()
    resp.Concat(dataItems)
    
    if c.GuildID > 0 {
        guild, err := FindGuildByID(c.GuildID)
        if err == nil && guild != nil {
            resp.Concat(guild.GetInfo())
        }
    }
    
    return resp, nil
}

主要修复点:

  1. 使用动态index变量跟踪当前位置,避免硬编码偏移
  2. 确保每个数据字段插入后正确更新索引
  3. 保持与原始工作版本相同的字段顺序和大小
  4. 荣誉等级(TITLE)字段在正确的位置插入(在变形状态之后,类型之前)

这种动态索引方法比硬编码偏移更可靠,特别是在数据结构可能变化的情况下。

回到顶部