娃娃机

This commit is contained in:
by 2024-08-14 11:33:03 +08:00
parent 49b0c6cc00
commit 775280e03f
3 changed files with 320 additions and 173 deletions

View File

@ -2,99 +2,131 @@ package action
import ( import (
"fmt" "fmt"
"mongo.games.com/game/machine/machinedoll" "net"
"mongo.games.com/game/protocol/machine" "time"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib" "mongo.games.com/goserver/core/netlib"
"time" "mongo.games.com/goserver/core/task"
"mongo.games.com/goserver/core/timer"
"mongo.games.com/game/machine/machinedoll"
"mongo.games.com/game/protocol/machine"
) )
type DoneFunc func(c net.Conn)
func Process(conn *machinedoll.Conn, sec time.Duration, f1, f2 []DoneFunc, isSync bool) {
var ch chan struct{}
if isSync {
ch = make(chan struct{}, 1)
}
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
for _, v := range f1 {
v(conn)
}
if len(f2) > 0 {
timer.AfterTimer(func(h timer.TimerHandle, ud interface{}) bool {
Process(conn, 0, f2, nil, isSync)
if isSync {
ch <- struct{}{}
}
return true
}, nil, sec)
} else {
if isSync {
ch <- struct{}{}
}
}
return nil
}), nil).StartByFixExecutor(fmt.Sprintf("Machine%v", conn.Addr))
if isSync {
<-ch
}
}
// 移动 // 移动
func SMDollMachinePerateHandler(session *netlib.Session, packetId int, data interface{}) error { func SMDollMachinePerateHandler(session *netlib.Session, packetId int, data interface{}) error {
logger.Logger.Tracef("SMDollMachinePerateHandler %v", data)
msg, ok := data.(*machine.SMDollMachineoPerate) msg, ok := data.(*machine.SMDollMachineoPerate)
if !ok { if !ok {
return nil return nil
} }
conn := machinedoll.ConnMap[int(msg.Id)]
if conn == nil { conn, ok := machinedoll.MachineMgr.ConnMap[int(msg.GetId())]
if !ok || conn == nil {
return nil return nil
} }
if msg.Perate == 1 {
switch msg.Perate {
case 1:
//向前移动 //向前移动
machinedoll.Backward(conn) Process(conn, 200*time.Millisecond, []DoneFunc{machinedoll.Backward}, []DoneFunc{machinedoll.BackwardStop}, false)
time.Sleep(200 * time.Millisecond) case 2:
machinedoll.BackwardStop(conn)
} else if msg.Perate == 2 {
//向后移动 //向后移动
machinedoll.Forward(conn) Process(conn, 200*time.Millisecond, []DoneFunc{machinedoll.Forward}, []DoneFunc{machinedoll.ForwardStop}, false)
time.Sleep(200 * time.Millisecond) case 3:
machinedoll.ForwardStop(conn)
} else if msg.Perate == 3 {
//向左移动 //向左移动
machinedoll.Left(conn) Process(conn, 200*time.Millisecond, []DoneFunc{machinedoll.Left}, []DoneFunc{machinedoll.LeftStop}, false)
time.Sleep(200 * time.Millisecond) case 4:
machinedoll.LeftStop(conn)
} else if msg.Perate == 4 {
//向右移动 //向右移动
machinedoll.Right(conn) Process(conn, 200*time.Millisecond, []DoneFunc{machinedoll.Right}, []DoneFunc{machinedoll.RightStop}, false)
time.Sleep(200 * time.Millisecond) case 5:
machinedoll.RightStop(conn)
} else if msg.Perate == 5 {
//投币 //投币
machinedoll.Coin(conn) Process(conn, 200*time.Millisecond, []DoneFunc{machinedoll.Coin, machinedoll.Backward}, []DoneFunc{machinedoll.BackwardStop}, false)
machinedoll.Backward(conn)
time.Sleep(200 * time.Millisecond)
machinedoll.BackwardStop(conn)
} }
return nil return nil
} }
// 下抓 // 下抓
func SMDollMachineGrabHandler(session *netlib.Session, packetId int, data interface{}) error { func SMDollMachineGrabHandler(session *netlib.Session, packetId int, data interface{}) error {
logger.Logger.Tracef("SMDollMachineGrabHandler %v", data)
msg, ok := data.(*machine.SMDollMachineGrab) msg, ok := data.(*machine.SMDollMachineGrab)
if !ok { if !ok {
return nil return nil
} }
conn := machinedoll.ConnMap[int(msg.Id)]
if conn == nil { conn, ok := machinedoll.MachineMgr.ConnMap[int(msg.GetId())]
if !ok || conn == nil {
return nil return nil
} }
typeId := msg.TypeId
if typeId == 1 { send := func(net.Conn) {
//弱抓 session.Send(int(machine.DollMachinePacketID_PACKET_SMDollMachineGrab), &machine.MSDollMachineGrab{
machinedoll.WeakGrab(conn) Snid: msg.Snid,
} else if typeId == 2 { Id: msg.GetId(),
//强力抓 Result: 1,
machinedoll.Grab(conn) })
} else if typeId == 3 { }
//必中抓
machinedoll.SetPower(conn) switch msg.GetTypeId() {
time.Sleep(200 * time.Millisecond) case 1:
machinedoll.Grab(conn) //弱抓
Process(conn, 0, []DoneFunc{machinedoll.WeakGrab}, []DoneFunc{send}, false)
case 2:
//强力抓
Process(conn, 0, []DoneFunc{machinedoll.Grab}, []DoneFunc{send}, false)
case 3:
//必中抓
Process(conn, 200*time.Millisecond, []DoneFunc{machinedoll.SetPower}, []DoneFunc{machinedoll.Grab, send}, false)
} }
//返回消息
session.Send(int(machine.DollMachinePacketID_PACKET_SMDollMachineGrab), &machine.MSDollMachineGrab{
Snid: msg.Snid,
Id: msg.GetId(),
Result: 1,
})
return nil return nil
} }
// 与游戏服务器连接成功,向游戏服务器推送所有娃娃机连接 // 与游戏服务器连接成功,向游戏服务器推送所有娃娃机连接
func SMGameLinkSucceedHandler(session *netlib.Session, packetId int, data interface{}) error { func SMGameLinkSucceedHandler(session *netlib.Session, packetId int, data interface{}) error {
logger.Logger.Trace("与游戏服务器连接成功!!\n") logger.Logger.Trace("与游戏服务器连接成功")
fmt.Printf("与游戏服务器连接成功!!\n")
//开始向游戏服务器发送娃娃机连接信息 //开始向游戏服务器发送娃娃机连接信息
msg := &machine.MSDollMachineList{} msg := &machine.MSDollMachineList{}
for i, _ := range machinedoll.ConnMap { for i, _ := range machinedoll.MachineMgr.ConnMap {
info := &machine.DollMachine{} info := &machine.DollMachine{}
info.Id = int32(i) info.Id = int32(i)
info.VideoAddr = "www.baidu.com" info.VideoAddr = "www.baidu.com"
msg.Data = append(msg.Data, info) msg.Data = append(msg.Data, info)
} }
session.Send(int(machine.DollMachinePacketID_PACKET_MSDollMachineList), msg) session.Send(int(machine.DollMachinePacketID_PACKET_MSDollMachineList), msg)
fmt.Printf("开始向游戏服务器发送娃娃机连接信息!\n", msg) logger.Logger.Tracef("向游戏服务器发送娃娃机连接信息:%v", msg)
return nil return nil
} }
func init() { func init() {

View File

@ -110,6 +110,32 @@ func Grab(conn net.Conn) {
fmt.Println("Failed to read response from server:", err) fmt.Println("Failed to read response from server:", err)
return return
} }
instruction = []byte{0xAA, 0x04, 0x01, 0x50, 0x09, 0x5c, 0xdd}
_, err = conn.Write(instruction)
if err != nil {
fmt.Println("Failed to read response from server:", err)
return
}
}
// 必中抓
func Grab2(conn net.Conn) {
//设置电压
instruction := []byte{0xAA, 0x05, 0x01, 0x50, 0x06, 0x01}
instruction = calculateChecksum(instruction)
_, err := conn.Write(instruction)
if err != nil {
fmt.Println("Failed to send command to server:", err)
return
}
// 读取服务端的响应
buf := make([]byte, 1024)
_, err = conn.Read(buf)
if err != nil {
fmt.Println("Failed to read response from server:", err)
return
}
} }
// 弱抓aa 05 01 50 06 00 52 dd // 弱抓aa 05 01 50 06 00 52 dd
@ -187,6 +213,7 @@ func OpenMusic(conn net.Conn) {
instruction := []byte{0xAA, 0x33, 0x01, 0x06} instruction := []byte{0xAA, 0x33, 0x01, 0x06}
instruction = append(instruction, data...) instruction = append(instruction, data...)
instruction = calculateChecksum(instruction) instruction = calculateChecksum(instruction)
//instruction[1] = byte(len(instruction) - 3)
_, err := conn.Write(instruction) _, err := conn.Write(instruction)
if err != nil { if err != nil {
fmt.Println("Failed to send command to server:", err) fmt.Println("Failed to send command to server:", err)
@ -303,15 +330,11 @@ func queryBaseParam(conn net.Conn) {
fmt.Println("n", n) fmt.Println("n", n)
} }
// 设置强力 // 设置出奖模式
func SetPower(conn net.Conn) { func SetPower(conn net.Conn) {
data[3] = 0x00 data[3] = 0x01
data[16] = 0x01
data[17] = 0xE0
data[18] = 0x13
data[19] = 0x88
fmt.Println("data.len = ", len(data)) fmt.Println("data.len = ", len(data))
instruction := []byte{0xAA, 0x33, 0x01, 0x06} instruction := []byte{0xAA, 0x04, 0x01, 0x06}
instruction = append(instruction, data...) instruction = append(instruction, data...)
instruction = calculateChecksum(instruction) instruction = calculateChecksum(instruction)
_, err := conn.Write(instruction) _, err := conn.Write(instruction)
@ -330,52 +353,114 @@ func SetPower(conn net.Conn) {
} }
var data = []byte{ var data = []byte{
0x65, 0x65, //0 几币几玩
0x00, 0x00, //1 几币几玩占用位
0x0F, 0x1E, //2 游戏时间
0x02, 0x00, //3 出奖模式
0x0F, 0x0F, //4 出奖概率
0x00, 0x00, //5 出奖概率占用位
0x01, 0x00, //6 空中抓物 0关闭 1开启
0x00, 0x00, //7 连续投币赠送 范围0~100
0x00, 0x00, //8 保夹次数 范围06 6为无限次
0x01, 0x01, //9 保夹赠送模式 0送游戏 1送中奖 2送游戏和中奖
0xC8,
0x00, 0x04, //10 强抓力电压
0x7C, 0x50, //11 强抓力电压占用位
0x01, 0x7C, //12 中抓力电压
0x5A, 0x00, //13 中抓力电压占用位
0x00, 0x5A, //14 弱抓力电压
0xE0, 0x00, //15 弱抓力电压占用位
0x01, 0xE0, //16 中奖电压
0xC8, 0x01, //17 中奖电压占用位
0x00, 0xC8, //18 强抓力时间
0x14, 0x00, //19 强抓力时间占用位
0x32,
0x32, 0x14, //20 放抓时间
0x50, 0x32, //21 前后速度
0x34, 0x32, //22 左右速度
0x08, 0x50, //23 上下速度
0x00, 0x34, //24 放线长度
0x00, 0x08, //25 放线长度占用位
0x00, 0x00, //26 礼品下放高度
0x00, 0x00, //27 礼品下放高度占用位
0x78, 0x00, //28 甩抓长度
0x00, 0x00, //29 甩抓保护
0x32,
0x02, 0x78, //30 甩抓电压
0x00, 0x00, //31 甩抓电压占用位
0x00, 0x32, //32 上拉保护
0xC8, 0x02, //33 天车自救时间
0x00, 0x00, //34 下抓延时
0x96, 0x00, //35 下抓延时占用位
0x00, 0xC8, //36 抓物延时
0x00, 0x00, //37 抓物延时占用位
0x00, 0x96, //38 上停延时
0x00, 0x00, //39 上停延时占用位
0x00,
0x0F, 0x00, //40 摇杆延时
0x07, 0x00, //41 摇杆延时占用位
0x08, 0x00, //42 抓物二收
0x00, 0x00, //43 待机音乐开关
0x0F, //44 音量大小调整
0x07, //45 待机音乐选择
0x08, //46 游戏音乐选择
0x00, //47 概率队列自动
} }
/*
var data = []byte{
101, //0 几币几玩
0, //1 几币几玩占用位
30, //2 游戏时间
0, //3 出奖模式0无概率 1随机模式 2固定模式 3冠兴模式
15, //4 出奖概率
0, //5 出奖概率占用位
1, //6 空中抓物 0关闭 1开启
0, //7 连续投币赠送 范围0~100
0, //8 保夹次数 范围06 6为无限次
1, //9 保夹赠送模式 0送游戏 1送中奖 2送游戏和中奖
200, //10 强抓力电压
0, //11 强抓力电压占用位
124, //12 中抓力电压
1, //13 中抓力电压占用位
90, //14 弱抓力电压
0, //15 弱抓力电压占用位
224, //16 中奖电压
1, //17 中奖电压占用位
200, //18 强抓力时间
0, //19 强抓力时间占用位
20, //20 放抓时间
50, //21 前后速度
50, //22 左右速度
80, //23 上下速度
52, //24 放线长度
8, //25 放线长度占用位
0, //26 礼品下放高度
0, //27 礼品下放高度占用位
0, //28 甩抓长度
0, //29 甩抓保护
120, //30 甩抓电压
0, //31 甩抓电压占用位
50, //32 上拉保护
2, //33 天车自救时间
0, //34 下抓延时
0, //35 下抓延时占用位
200, //36 抓物延时
0, //37 抓物延时占用位
150, //38 上停延时
0, //39 上停延时占用位
0, //40 摇杆延时
0, //41 摇杆延时占用位
0, //42 抓物二收
1, //43 待机音乐开关
15, //44 音量大小调整
7, //45 待机音乐选择
8, //46 游戏音乐选择
0, //47 概率队列自动
}
*/

View File

@ -3,38 +3,45 @@ package machinedoll
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"mongo.games.com/goserver/core/timer"
"os/signal"
"syscall"
"mongo.games.com/game/protocol/machine"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/srvlib"
"net" "net"
"os" "os"
"os/signal"
"path/filepath" "path/filepath"
"syscall"
"time" "time"
"mongo.games.com/goserver/core/basic"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/module"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/core/task"
"mongo.games.com/goserver/srvlib"
"mongo.games.com/game/protocol/machine"
) )
var GameConn *netlib.Session var GameConn *netlib.Session
var ConnMap = make(map[int]net.Conn)
type MachineManager struct {
DelConnMap map[int]string
}
var MachineMgr = &MachineManager{ var MachineMgr = &MachineManager{
ConnMap: map[int]*Conn{},
DelConnMap: make(map[int]string), DelConnMap: make(map[int]string),
} }
type Conn struct {
Id int
net.Conn
Addr string
}
type MachineManager struct {
ConnMap map[int]*Conn
DelConnMap map[int]string
}
func (this *MachineManager) ModuleName() string { func (this *MachineManager) ModuleName() string {
return "MachineManager" return "MachineManager"
} }
// 心跳间隔时间(秒)
const heartbeatInterval = 1
func (this *MachineManager) Init() { func (this *MachineManager) Init() {
var serverAddrs []string var serverAddrs []string
programDir, err := os.Getwd() programDir, err := os.Getwd()
@ -62,70 +69,91 @@ func (this *MachineManager) Init() {
fmt.Println("Failed to connect to server:", err) fmt.Println("Failed to connect to server:", err)
continue continue
} }
ConnMap[i+1] = conn this.ConnMap[i+1] = &Conn{
go this.StartHeartbeat(i+1, &conn, addr) Id: i + 1,
Conn: conn,
Addr: addr,
}
} }
fmt.Println("Connected to server:\n", ConnMap[1].RemoteAddr()) fmt.Println("Connected to server:\n", this.ConnMap[1].RemoteAddr())
fmt.Println("投币请按Q") fmt.Println("投币请按Q")
fmt.Println("w向前s向后a向左d向右 j强力抓取k弱力抓取") fmt.Println("w向前s向后a向左d向右 j强力抓取k弱力抓取")
// 监听 WASD 按键事件 // 监听 WASD 按键事件
/* go listenKeyboardEvents(ConnMap[1]) go listenKeyboardEvents(this.ConnMap[1])
// 监听中断信号,等待用户退出
waitForUserExit()
// 监听中断信号,等待用户退出
waitForUserExit()*/
} }
func (this *MachineManager) StartHeartbeat(id int, conn *net.Conn, addr string) {
// 定期发送心跳包
ticker := time.NewTicker(heartbeatInterval * time.Second)
defer ticker.Stop()
for { func (this *MachineManager) Update() {
select { var delConn []*Conn
case <-ticker.C: task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
// 发送心跳包 for _, v := range this.ConnMap {
_, err := (*conn).Write([]byte("heartbeat")) _, err := v.Write([]byte("heartbeat"))
if err != nil { if err != nil {
fmt.Println("Failed to send heartbeat:", err) delConn = append(delConn, v)
delete(ConnMap, id) v.Close()
this.DelConnMap[id] = addr logger.Logger.Tracef("断开连接:%v", v.Addr)
//通知游戏服
this.UpdateToGameServer(id, 0)
fmt.Println("删除链接addr = ", addr)
go timer.StartTimer(timer.TimerActionWrapper(func(h timer.TimerHandle, ud interface{}) bool {
this.ReConnect()
return true
}), nil, time.Duration(5)*time.Second, 100)
return
} }
} }
} return nil
} }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) {
for _, v := range delConn {
// 重连 delete(this.ConnMap, v.Id)
func (this *MachineManager) ReConnect() bool { this.DelConnMap[v.Id] = v.Addr
fmt.Println("================重连============")
delIds := []int{}
for id, addr := range this.DelConnMap {
conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
if err != nil {
continue
} }
ConnMap[id] = conn if len(delConn) > 0 {
delIds = append(delIds, id) this.UpdateToGameServer()
this.UpdateToGameServer(id, 1) }
} // 重连
for _, id := range delIds { var delIds []*Conn
delete(this.DelConnMap, id) status := false
fmt.Println("重新链接成功id = ", id) task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
} for id, addr := range this.DelConnMap {
return false conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
if err != nil {
continue
}
logger.Logger.Tracef("重连成功:%v", addr)
delIds = append(delIds, &Conn{
Id: id,
Conn: conn,
Addr: addr,
})
status = true
}
return nil
}), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) {
for _, v := range delIds {
this.ConnMap[v.Id] = v
delete(this.DelConnMap, v.Id)
}
if status {
this.UpdateToGameServer()
}
})).StartByFixExecutor(this.ModuleName())
})).StartByFixExecutor(this.ModuleName())
} }
func (this *MachineManager) UpdateToGameServer(id int, status int32) { func (this *MachineManager) Shutdown() {
msg := &machine.MSUpdateDollMachineStatus{} for _, v := range this.ConnMap {
msg.Status = status v.Close()
msg.Id = int32(id) }
SendToGameServer(int(machine.DollMachinePacketID_PACKET_MSUpdateDollMachineStatus), msg) this.UpdateToGameServer()
module.UnregisteModule(this)
}
func (this *MachineManager) UpdateToGameServer() {
msg := &machine.MSDollMachineList{}
for i, _ := range this.ConnMap {
info := &machine.DollMachine{}
info.Id = int32(i)
info.VideoAddr = "www.baidu.com"
msg.Data = append(msg.Data, info)
}
SendToGameServer(int(machine.DollMachinePacketID_PACKET_MSDollMachineList), msg)
} }
func SendToGameServer(pid int, msg interface{}) { func SendToGameServer(pid int, msg interface{}) {
@ -140,7 +168,7 @@ func SendToGameServer(pid int, msg interface{}) {
} }
func init() { func init() {
MachineMgr.Init() module.RegisteModule(MachineMgr, time.Second, 0)
} }
func listenKeyboardEvents(conn net.Conn) { func listenKeyboardEvents(conn net.Conn) {
@ -218,6 +246,8 @@ func listenKeyboardEvents(conn net.Conn) {
SetPower(conn) SetPower(conn)
case "8": case "8":
CloseMusic(conn) CloseMusic(conn)
case "9":
queryBaseParam(conn)
} }
} }
} }