```
feat(broadcast): 添加全服广播功能并完善相关逻辑 新增 Broadcast 结构体及 Server 的 Broadcast 方法,用于实现全服广播消息, 并在 RPC 客户端中增加对应接口。同时在 fight 模块中添加聊天信息结构体和处理逻辑。 refactor(pet_skill): 优化宠物技能设置逻辑 修复宠物技能替换判断条件错误的问题,并调整相关逻辑顺序以提高代码可读性与健壮性。 feat(chat): 实现战斗内聊天功能 新增战斗中的聊天指令结构体 ChatInfo 和对应的控制器方法 FightChat, 支持玩家在战斗中发送聊天消息。 refactor(item_buy): 调整金币购买道具的扣费方式 将原直接比较金币数量改为调用
This commit is contained in:
@@ -2,6 +2,7 @@ package xmlres
|
||||
|
||||
import (
|
||||
"blazing/common/utils"
|
||||
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
@@ -55,7 +56,7 @@ var (
|
||||
GoldProductMap = make(map[int]GoldProductItem, 0)
|
||||
)
|
||||
|
||||
func initfile() {
|
||||
func Initfile() {
|
||||
path1, _ := os.Getwd()
|
||||
path = path1 + "/public/config/"
|
||||
MapConfig = getXml[Maps](path + "210.xml")
|
||||
@@ -133,8 +134,6 @@ func initfile() {
|
||||
|
||||
func init() {
|
||||
|
||||
initfile() //先初始化一次
|
||||
|
||||
go func() {
|
||||
|
||||
if !gfile.Exists(path) {
|
||||
|
||||
@@ -36,6 +36,7 @@ func GetServerInfoList() []ServerInfo {
|
||||
if ok {
|
||||
cool.Loger.Info(context.TODO(), "服务器假踢人")
|
||||
err := t.KickPerson(0) //实现指定服务器踢人
|
||||
|
||||
if err == nil {
|
||||
// tt.Friends = v.Friends
|
||||
ret1 = append(ret1, *tt)
|
||||
|
||||
@@ -43,6 +43,7 @@ func getClient(id uint16) (*ClientHandler, bool) {
|
||||
type ClientHandler struct {
|
||||
KickPerson func(uint32) error //踢人,这里是返回具体的logic
|
||||
QuitSelf func(int) error //关闭服务器进程
|
||||
Broadcast func(string) int //全服广播,返回的是在线人数
|
||||
}
|
||||
|
||||
// Define the server handler
|
||||
|
||||
@@ -7,6 +7,23 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Broadcast struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (h *Server) Broadcast(t string) int {
|
||||
cool.Loger.Info(context.TODO(), "全服广播", t)
|
||||
var count int
|
||||
player.Mainplayer.Range(func(key uint32, value *player.Player) bool {
|
||||
count++
|
||||
value.SendPackCmd(50003, &Broadcast{
|
||||
Name: t,
|
||||
})
|
||||
return true
|
||||
})
|
||||
|
||||
return count
|
||||
}
|
||||
func (h *Server) KickPerson(a int) error {
|
||||
cool.Loger.Info(context.TODO(), "检测到踢人请求", a)
|
||||
if a == 0 {
|
||||
|
||||
@@ -17,3 +17,10 @@ func LastFourElements[T any](s []T, n1 int) []T {
|
||||
// 切片长度大于4时,返回最后4个元素(从n-4索引到末尾)
|
||||
return s[n-n1:]
|
||||
}
|
||||
func RemoveLast(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
runes := []rune(s)
|
||||
return string(runes[:len(runes)-1])
|
||||
}
|
||||
|
||||
@@ -84,3 +84,12 @@ func (h Controller) UsePetItemInboundInfo(data *fight.UsePetItemInboundInfo, c *
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
func (h Controller) FightChat(data *fight.ChatInfo, c *player.Player) (result *fight.NullOutboundInfo, err errorcode.ErrorCode) {
|
||||
if c.FightC == nil {
|
||||
return nil, errorcode.ErrorCodes.ErrBattleEnded
|
||||
}
|
||||
|
||||
c.FightC.Chat(c, data.Message)
|
||||
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (h Controller) BuyMItem(data *item.BuyMultiInboundInfo, c *player.Player) (
|
||||
func (h Controller) BuyGoldItem(data *item.C2S_GOLD_BUY_PRODUCT, c *player.Player) (result *item.S2C_GoldBuyProductInfo, err errorcode.ErrorCode) {
|
||||
r := xmlres.GoldProductMap[int(data.ProductID)]
|
||||
|
||||
if uint32(data.Count)*uint32(gconv.Uint32(r.Price)) > c.Info.GoldBean {
|
||||
if !c.UseGold(uint32(data.Count) * uint32(gconv.Uint32(r.Price))) {
|
||||
return nil, errorcode.ErrorCodes.ErrSystemError
|
||||
}
|
||||
c.ItemAdd(model.ItemInfo{ItemId: uint32(gconv.Uint32(r.ItemID)), ItemCnt: uint32(data.Count)})
|
||||
@@ -69,6 +69,7 @@ func (h Controller) BuyGoldItem(data *item.C2S_GOLD_BUY_PRODUCT, c *player.Playe
|
||||
PayGold: uint32(data.Count) * uint32(gconv.Uint32(r.Price)),
|
||||
Reserved: 0,
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
@@ -16,17 +16,16 @@ func (h Controller) SetPetSkill(data *pet.ChangeSkillInfo, c *player.Player) (re
|
||||
}
|
||||
|
||||
_, onpet, ok := c.FindPet(data.CatchTime)
|
||||
if ok {
|
||||
_, HasSkill, ok := utils.FindWithIndex(onpet.SkillList, func(item model.SkillInfo) bool { //已经存在技能
|
||||
return item.ID == data.ReplaceSkill
|
||||
})
|
||||
if !ok {
|
||||
HasSkill.ID = data.ReplaceSkill
|
||||
HasSkill.PP = uint32(xmlres.SkillMap[int(HasSkill.ID)].MaxPP)
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return result, errorcode.ErrorCodes.ErrSystemBusy
|
||||
}
|
||||
_, HasSkill, ok := utils.FindWithIndex(onpet.SkillList, func(item model.SkillInfo) bool { //已经存在技能
|
||||
return item.ID == data.HasSkill
|
||||
})
|
||||
if !ok {
|
||||
HasSkill.ID = data.ReplaceSkill
|
||||
HasSkill.PP = uint32(xmlres.SkillMap[int(HasSkill.ID)].MaxPP)
|
||||
}
|
||||
|
||||
return &pet.ChangeSkillOutInfo{
|
||||
CatchTime: data.CatchTime,
|
||||
}, 0
|
||||
|
||||
@@ -2,6 +2,7 @@ package controller
|
||||
|
||||
import (
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/common/utils"
|
||||
"blazing/cool"
|
||||
"blazing/logic/service/item"
|
||||
"blazing/logic/service/player"
|
||||
@@ -51,7 +52,7 @@ func (h Controller) Chat(data *user.ChatInboundInfo, c *player.Player) (result *
|
||||
|
||||
result = &user.ChatOutboundInfo{
|
||||
|
||||
Message: string([]byte(data.Message)[:data.MessageLen-1]),
|
||||
Message: utils.RemoveLast(data.Message),
|
||||
SenderNickname: c.Info.Nick,
|
||||
SenderId: c.Info.UserID,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/common/rpc"
|
||||
"blazing/common/socket"
|
||||
|
||||
@@ -76,7 +77,7 @@ func Start(serverid uint16) {
|
||||
|
||||
controller.Maincontroller.RPCClient = *t //将RPC赋值Start
|
||||
controller.Maincontroller.Port = uint16(port) //赋值服务器ID
|
||||
|
||||
xmlres.Initfile()
|
||||
blservice.NewLoginServiceService().SetServerID(serverid, gconv.Uint16(port))
|
||||
ser.Boot()
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ type FightI interface {
|
||||
GetRand() *rand.Rand
|
||||
LoadPercent(c PlayerI, percent int32)
|
||||
UseItem(c PlayerI, cacthid, itemid uint32)
|
||||
|
||||
Chat(c PlayerI, msg string)
|
||||
IsFirst(c PlayerI) bool
|
||||
GetOverChan() chan struct{}
|
||||
}
|
||||
|
||||
@@ -117,3 +117,9 @@ type UsePetItemInboundInfo struct {
|
||||
ItemId uint32 `description:"使用的物品ID" codec:"itemId"` // 结构体标签模拟@FieldDescription和@AutoCodec注解
|
||||
Reversed1 uint32 `description:"填充字段 0" codec:"reversed1"` // reversed1对应原Java的填充字段
|
||||
}
|
||||
type ChatInfo struct {
|
||||
Head common.TomeeHeader `cmd:"50002" struc:"skip"`
|
||||
Reserve uint32 `json:"reserve" fieldDescription:"填充 默认值为0" uint:"true"` // @UInt long reserve,无符号长整数
|
||||
MessageLen uint32 `struc:"sizeof=Message"`
|
||||
Message string `json:"message" fieldDescription:"消息内容, 结束符为utf-8的数字0"` // 消息内容,包含utf-8空字符('\x00')作为结束符
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package fight
|
||||
|
||||
import (
|
||||
"blazing/common/data/xmlres"
|
||||
"blazing/common/socket/errorcode"
|
||||
"blazing/common/utils"
|
||||
"blazing/cool"
|
||||
"blazing/modules/blazing/model"
|
||||
"fmt"
|
||||
|
||||
"blazing/logic/service/common"
|
||||
"blazing/logic/service/fight/action"
|
||||
"blazing/logic/service/fight/info"
|
||||
"blazing/logic/service/fight/input"
|
||||
"blazing/modules/blazing/model"
|
||||
"blazing/logic/service/user"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -94,10 +97,23 @@ func (f *FightC) IsFirst(play common.PlayerI) bool {
|
||||
|
||||
return f.First.Player == play
|
||||
}
|
||||
func (f *FightC) Chat(c common.PlayerI, msg string) {
|
||||
|
||||
f.GetInputByPlayer(c, true).Player.SendPackCmd(50002, &user.ChatOutboundInfo{
|
||||
SenderId: c.GetInfo().UserID,
|
||||
SenderNickname: c.GetInfo().Nick,
|
||||
Message: utils.RemoveLast(msg),
|
||||
})
|
||||
}
|
||||
|
||||
// 加载进度
|
||||
func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
|
||||
|
||||
if f.Info.Mode == info.BattleMode.PET_MELEE {
|
||||
return
|
||||
}
|
||||
if f.Info.Status == info.BattleMode.FIGHT_WITH_NPC {
|
||||
return
|
||||
}
|
||||
f.GetInputByPlayer(c, true).Player.SendPackCmd(2441, &info.LoadPercentOutboundInfo{
|
||||
Id: c.GetInfo().UserID,
|
||||
Percent: uint32(percent),
|
||||
@@ -105,6 +121,18 @@ func (f *FightC) LoadPercent(c common.PlayerI, percent int32) {
|
||||
|
||||
}
|
||||
|
||||
var meetpet = make(map[int]model.PetInfo)
|
||||
|
||||
func initmeetpet() {
|
||||
meetpet = make(map[int]model.PetInfo)
|
||||
for i, v := range xmlres.PetMAP {
|
||||
if v.EvolvesTo == 0 && v.ID < 2000 {
|
||||
r := model.GenPetInfo(int(v.ID), 24, -1, -1, -1, 100)
|
||||
meetpet[i] = *r
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
func (f *FightC) initplayer(c common.PlayerI) (*input.Input, errorcode.ErrorCode) {
|
||||
|
||||
if !c.CanFight() {
|
||||
@@ -126,18 +154,18 @@ func (f *FightC) initplayer(c common.PlayerI) (*input.Input, errorcode.ErrorCode
|
||||
in.AllPet = in.AllPet[:1]
|
||||
case info.BattleMode.PET_MELEE:
|
||||
in.AllPet = make([]*info.BattlePetEntity, 0)
|
||||
for _, v := range RandomElfIDs(3) {
|
||||
p := model.GenPetInfo(v, 24, -1, -1, -1, 100)
|
||||
//p.CatchTime = uint32(v)
|
||||
p.Update()
|
||||
p.Update_EXP()
|
||||
|
||||
p = model.GenPetInfo(int(p.ID), 24, -1, -1, -1, 100)
|
||||
//p.CalculatePetPane()
|
||||
p.CatchTime = uint32(v)
|
||||
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(*p, f.rand))
|
||||
|
||||
if len(meetpet) == 0 {
|
||||
initmeetpet()
|
||||
}
|
||||
for i, v := range meetpet {
|
||||
if len(in.AllPet) > 2 {
|
||||
break
|
||||
}
|
||||
|
||||
v.CatchTime = uint32(i)
|
||||
in.AllPet = append(in.AllPet, info.CreateBattlePetEntity(v, f.rand))
|
||||
}
|
||||
|
||||
//in.AllPet = in.AllPet[:3]
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -18,11 +18,14 @@ func (p *Player) AddPetExp(petinfo *model.PetInfo, addExp uint32) {
|
||||
addExp = utils.Min(addExp, p.Info.ExpPool)
|
||||
originalLevel := petinfo.Level
|
||||
Exp := petinfo.Exp + addExp
|
||||
|
||||
petinfo.Update_EXP()
|
||||
petinfo.Update()
|
||||
p.Info.ExpPool -= addExp //减去已使用的经验
|
||||
for Exp >= petinfo.NextLvExp {
|
||||
petinfo.Level++
|
||||
petinfo.Update_EXP()
|
||||
petinfo.Update()
|
||||
Exp -= petinfo.LvExp
|
||||
if originalLevel < 100 && petinfo.Level == 100 { //升到100了
|
||||
p.Info.ExpPool += Exp //减去已使用的经验
|
||||
|
||||
@@ -86,6 +86,15 @@ func (p *Player) UseCoins(t uint32) bool {
|
||||
p.Info.Coins = p.Info.Coins - t
|
||||
return true
|
||||
|
||||
}
|
||||
func (p *Player) UseGold(t uint32) bool {
|
||||
|
||||
if p.Info.GoldBean < t {
|
||||
return false
|
||||
}
|
||||
p.Info.GoldBean = p.Info.GoldBean - t
|
||||
return true
|
||||
|
||||
}
|
||||
func (p *Player) GetAction() {
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ require (
|
||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/samber/lo v1.52.0
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
|
||||
@@ -62,6 +62,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
|
||||
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tnnmigga/enum v1.0.2 h1:Yvchx0Esc01X5HiphW78sKzH/RXKttdFsfPO1ARiOa4=
|
||||
|
||||
Reference in New Issue
Block a user