chore: 删除无用的项目配置和资源文件修改android key,修正godot4.3无法构建的问题
- 移除 .gitattributes 和 .gitignore 文件 - 删除 Asserts 目录下的棋盘和棋子基础资源文件
This commit is contained in:
@ -1,145 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class ChessGame : Node2D
|
||||
{
|
||||
ChessBoard board;
|
||||
Global global;
|
||||
ConfirmationDialog dialog;
|
||||
private bool isSession = false;
|
||||
private Vector2 from;
|
||||
private Vector2 to;
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
// Init.Call();
|
||||
global = GetNode<Global>("/root/Global");
|
||||
board = GetNode<ChessBoard>("Chessboard");
|
||||
dialog = new ConfirmationDialog {
|
||||
DialogAutowrap = true,
|
||||
MinSize = new Vector2I(400, 200),
|
||||
Position = new Vector2I(200, 400),
|
||||
};
|
||||
AddChild(dialog);
|
||||
// GetNode<Button>("Undo").Connect("pressed", Callable.From(board.Undo));
|
||||
// GetNode<Button>("ReInit").Connect("pressed", Callable.From(board.ReInit));
|
||||
// GetNode<Button>("Home").Connect("pressed", Callable.From(this.GoHome));
|
||||
|
||||
if (!global.RPClient.GetIsConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
isSession = true;
|
||||
GD.Print("ws is connected");
|
||||
global.RPClient.OnPRCSessionExit += (cmd, code) => {
|
||||
GoHome();
|
||||
};
|
||||
board.Set("Hello", Callable.From(() => {GD.PrintErr("hello");}));
|
||||
board.Set("chessMoveFunc", Callable.From((Vector2 newPos, Vector2 fromPos) => {
|
||||
if (from.X == fromPos.X && from.Y == fromPos.Y && to.X == newPos.X && to.Y == newPos.Y) {
|
||||
return true;
|
||||
}
|
||||
from = fromPos;
|
||||
to = newPos;
|
||||
var res = global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
{"type", "move"},
|
||||
{"from", fromPos},
|
||||
{"to", newPos},
|
||||
{"fromX", fromPos.X},
|
||||
{"fromY", fromPos.Y},
|
||||
{"toX", newPos.X},
|
||||
{"toY", newPos.Y},
|
||||
});
|
||||
GD.Print($"chessMoveFunc Callback {fromPos} -> {newPos} {res}");
|
||||
return false;
|
||||
}));
|
||||
global.RPClient.OnPRCSessionRecv += (msg) => {
|
||||
SessionMsgHandle(msg["msg"].AsGodotDictionary());
|
||||
};
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta) {
|
||||
}
|
||||
|
||||
private void SessionMsgHandle(Dictionary msg) {
|
||||
GD.PrintErr($"session msg: {msg}");
|
||||
switch (msg["type"].AsString()) {
|
||||
case "over":
|
||||
if (global.RPClient.GetUserId() == msg["id"].AsString()) {
|
||||
break;
|
||||
}
|
||||
dialog.Title = "Opponent Finished";
|
||||
dialog.DialogText = "Turn On You\n";
|
||||
dialog.Visible = true;
|
||||
break;
|
||||
case "move":
|
||||
Vector2 _to = new(GD.StrToVar(msg["toX"].ToString()).AsInt32(),
|
||||
GD.StrToVar(msg["toY"].ToString()).AsInt32());
|
||||
|
||||
Vector2 _from = new(GD.StrToVar(msg["fromX"].ToString()).AsInt32(),
|
||||
GD.StrToVar(msg["fromY"].ToString()).AsInt32());
|
||||
if (_to.X == to.X && _to.Y == to.Y && _from.X == from.X && _from.Y == from.Y) {
|
||||
return;
|
||||
}
|
||||
to = _to;
|
||||
from = _from;
|
||||
board.playerSelf.MoveAndRecord(to, from);
|
||||
break;
|
||||
case "undo":
|
||||
_Undo();
|
||||
break;
|
||||
case "reInit":
|
||||
_ReInit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void _Undo() {
|
||||
board.playerSelf.Undo();
|
||||
}
|
||||
|
||||
private void _ReInit() {
|
||||
board.playerSelf.ReInit();
|
||||
board.InitChessBoard();
|
||||
}
|
||||
|
||||
private void BtnOver() {
|
||||
GD.PrintErr($"BtnOver {isSession}");
|
||||
if (isSession == false) {
|
||||
return;
|
||||
}
|
||||
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
{"type", "over"},
|
||||
{"id", global.RPClient.GetUserId()},
|
||||
});
|
||||
}
|
||||
|
||||
public void GoHome() {
|
||||
if (global.RPClient.IsOnline()) {
|
||||
global.RPClient.ExitServer();
|
||||
}
|
||||
global.GotoScene("res://Main.tscn");
|
||||
}
|
||||
|
||||
public void Undo() {
|
||||
GD.PrintErr($"Undo {isSession}");
|
||||
if (isSession == false) {
|
||||
_Undo();
|
||||
}
|
||||
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
{"type", "undo"},
|
||||
});
|
||||
}
|
||||
|
||||
public void ReInit() {
|
||||
GD.PrintErr($"ReInit {isSession}");
|
||||
if (isSession == false) {
|
||||
_ReInit();
|
||||
}
|
||||
global.RPClient.SendSessionToAll(global.sessionId, new Dictionary{
|
||||
{"type", "reInit"},
|
||||
});
|
||||
}
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class Menu : Control
|
||||
{
|
||||
Global global = null;
|
||||
ItemList lists = null;
|
||||
ConfirmationDialog dialog = null;
|
||||
LineEdit nameLineEdit = null;
|
||||
LineEdit urlLineEdit = null;
|
||||
ColorRect colorRect = null;
|
||||
Timer timer = null;
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
global = GetNode<Global>("/root/Global");
|
||||
nameLineEdit = GetNode<LineEdit>("Name/LineEdit");
|
||||
urlLineEdit = GetNode<LineEdit>("URL");
|
||||
urlLineEdit.Text = global.URL;
|
||||
urlLineEdit.Set("text_submitted", Callable.From(()=>{
|
||||
global.URL = urlLineEdit.Text;
|
||||
}));
|
||||
|
||||
lists = GetNode<ItemList>("Server/ItemList");
|
||||
dialog = GetNode<ConfirmationDialog>("Dialogs/ConfirmationDialog");
|
||||
colorRect = GetNode<ColorRect>("Server/ColorRect");
|
||||
dialog.DialogAutowrap = true;
|
||||
dialog.MinSize = new Vector2I(400, 200);
|
||||
dialog.Canceled += () => {
|
||||
if (dialog.Title == "Session Created")
|
||||
global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), false);
|
||||
};
|
||||
dialog.Confirmed += () => {
|
||||
// GD.PrintErr("confirm", dialog.GetLabel().Text);
|
||||
// goToSignle();
|
||||
if (dialog.Title == "Session Created")
|
||||
global.RPClient.SessionAckCreate(dialog.GetMeta("sessionId").ToString(), true);
|
||||
};
|
||||
|
||||
global.RPClient.RegSessionAckCreateCallback((
|
||||
sessionId,
|
||||
res,
|
||||
reqUserId,
|
||||
reqUserName) => {
|
||||
if (reqUserId != null) {
|
||||
dialog.Title = "Session Created";
|
||||
dialog.SetMeta("reqUserName", reqUserName);
|
||||
dialog.SetMeta("reqUserId", reqUserId);
|
||||
dialog.SetMeta("sessionId", sessionId);
|
||||
// dialog.GetLabel==>Text = $"{sessdata["reqUserName"]}";
|
||||
dialog.DialogText = $"username: {reqUserName}\n" +
|
||||
$"reqUserId: {reqUserId}\n";
|
||||
dialog.Visible = true;
|
||||
} else {
|
||||
if (res) {
|
||||
global.sessionId = sessionId;
|
||||
global.GotoScene("res://Scenes/ChessGame.tscn");
|
||||
} else {
|
||||
dialog.Title = "Failed";
|
||||
dialog.DialogText = $"session create failed";
|
||||
dialog.Visible = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
timer = new Timer();
|
||||
AddChild(timer);
|
||||
timer.Connect("timeout", Callable.From(() => {
|
||||
if (global.RPClient.GetIsConnected()) {
|
||||
colorRect.Color = Colors.Green;
|
||||
} else {
|
||||
colorRect.Color = Colors.Red;
|
||||
}
|
||||
}));
|
||||
timer.Start(1);
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta) {
|
||||
}
|
||||
|
||||
private void OnItemSelected(int index) {
|
||||
Dictionary item = lists.GetItemMetadata(index).AsGodotDictionary();
|
||||
GD.Print($"Item {index} selected, {item}");
|
||||
string[] strings = { item["id"].ToString() };
|
||||
global.RPClient.SessionCreate(strings);
|
||||
}
|
||||
|
||||
private void FlushData()
|
||||
{
|
||||
global.RPClient.RegionInspect("server", (data) => {
|
||||
GD.Print(data);
|
||||
lists.Clear();
|
||||
foreach (Dictionary<string, string> user in data) {
|
||||
string userId = user["id"].ToString();
|
||||
string userName = user["name"].ToString();
|
||||
if (userId == global.RPClient.GetUserId()) {
|
||||
lists.SetItemDisabled(
|
||||
lists.AddItem($"Name: {userName}"),
|
||||
true);
|
||||
continue;
|
||||
}
|
||||
var idx = lists.AddItem($"Name: {userName}");
|
||||
lists.SetItemMetadata(idx, user);
|
||||
lists.SetItemTooltip(idx, $"User ID: {userId}");
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public void Connect()
|
||||
{
|
||||
GD.Print("Connect");
|
||||
global.RPClient.ExitServer();
|
||||
global.RPClient.ConnectToUrlEx(urlLineEdit.Text);
|
||||
global.SetProcess(true);
|
||||
}
|
||||
|
||||
public void EnterName() {
|
||||
var newLine = nameLineEdit.Text;
|
||||
global.RPClient.UserRename(newLine);
|
||||
nameLineEdit.Text = newLine;
|
||||
}
|
||||
|
||||
private void goToHome() {
|
||||
global.RPClient.ExitServer();
|
||||
global.GotoScene("res://Main.tscn");
|
||||
}
|
||||
|
||||
// private void OnItemListItemClicked(int index, Vector2 atPosition, int mouse_button_index)
|
||||
// {
|
||||
// GD.Print($"Item {index} clicked at {atPosition} with mouse button index {mouse_button_index}");
|
||||
// }
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
using Godot;
|
||||
|
||||
public class Player
|
||||
{
|
||||
private VirtualBoard board;
|
||||
private SelectedPiece selectedNode;
|
||||
private MoveRecords<VirtualPiece> moveRecords;
|
||||
|
||||
public enum PlayerType {
|
||||
Human,
|
||||
AI
|
||||
}
|
||||
|
||||
public Player(VirtualBoard board, PlayerType type = PlayerType.Human)
|
||||
{
|
||||
this.board = board;
|
||||
this.selectedNode = new SelectedPiece(board);
|
||||
this.moveRecords = new MoveRecords<VirtualPiece>(onUndoRecordCallback: (newNode, oldNode, newPos, oldPos) => {
|
||||
GD.Print("Undo: ", newNode, "->", oldNode, ":", newPos, "->", oldPos);
|
||||
VirtualPiece newPiece = newNode;
|
||||
VirtualPiece oldPiece = oldNode;
|
||||
this.board.MovePiece(newPos, oldPos);
|
||||
if (newPiece != null) {
|
||||
this.board.InsertPiece(newPiece, newPos);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void HandleBoardPosClick(Vector2 clickPos) {
|
||||
if (board.ArrPosOutOfRange(clickPos)) return;
|
||||
GD.Print($"VirtualBoard {clickPos} clicked");
|
||||
VirtualPiece clickChess = board.GetPiece(clickPos);
|
||||
|
||||
if (!selectedNode.HasSelected()) {
|
||||
// Select piece
|
||||
if (clickChess == null) {
|
||||
// selectedNode.Clear();
|
||||
return;
|
||||
}
|
||||
selectedNode.SetPos(clickPos);
|
||||
} else if (clickChess == selectedNode.GetPiece()) {
|
||||
// Unselect piece
|
||||
selectedNode.Clear();
|
||||
} else {
|
||||
// Move piece
|
||||
GD.Print("default MoveFunc Move: ", selectedNode.GetPos(), "->", clickPos);
|
||||
MoveAndRecord(clickPos, selectedNode.GetPos());
|
||||
}
|
||||
}
|
||||
|
||||
public void MoveAndRecord(Vector2 toPos, Vector2 fromPos) {
|
||||
GD.Print($"{fromPos} move to {toPos}");
|
||||
VirtualPiece toChess = board.GetPiece(toPos);
|
||||
VirtualPiece fromChess = board.GetPiece(fromPos);
|
||||
fromChess?.Selected(false);
|
||||
|
||||
VirtualPiece NowNode;
|
||||
if (toChess != null) {
|
||||
NowNode = toChess;
|
||||
board.RemovePiece(toPos);
|
||||
} else {
|
||||
NowNode = toChess;
|
||||
}
|
||||
moveRecords.AddRecord(NowNode, fromChess, toPos, fromPos);
|
||||
board.MovePiece(fromPos, toPos);
|
||||
|
||||
selectedNode.Clear();
|
||||
}
|
||||
|
||||
public void Undo() {
|
||||
// ChessPiece selected = selectedNode.GetPiece();
|
||||
// selected?.DeSelected();
|
||||
selectedNode.Clear();
|
||||
moveRecords.Undo();
|
||||
}
|
||||
|
||||
public void ReInit() {
|
||||
moveRecords.Clear();
|
||||
board.Clear();
|
||||
selectedNode.Clear();
|
||||
// board.InitChessBoard();
|
||||
}
|
||||
|
||||
private class SelectedPiece
|
||||
{
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
private Vector2 selectedNodePos = Vector2.Inf;
|
||||
private VirtualPiece piece;
|
||||
private VirtualBoard board;
|
||||
|
||||
public SelectedPiece(VirtualBoard board)
|
||||
{
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (selectedNodePos != Vector2.Inf) {
|
||||
selectedNodePos = Vector2.Inf;
|
||||
piece.Selected(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPos(Vector2 pos)
|
||||
{
|
||||
// piece = board.GetNodeFromBoard(pos) as VirtualPiece;
|
||||
selectedNodePos = pos;
|
||||
piece = board.GetPiece(selectedNodePos);
|
||||
piece.Selected(true);
|
||||
}
|
||||
|
||||
public VirtualPiece GetPiece()
|
||||
{
|
||||
return piece;
|
||||
}
|
||||
|
||||
public Vector2 GetPos()
|
||||
{
|
||||
return selectedNodePos;
|
||||
}
|
||||
|
||||
public bool HasSelected()
|
||||
{
|
||||
return selectedNodePos != Vector2.Inf;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,308 +0,0 @@
|
||||
// Chessboard.cs
|
||||
using Godot;
|
||||
|
||||
public partial class ChessBoard : Node2D {
|
||||
public VirtualBoard board = null;
|
||||
public Player playerSelf = null;
|
||||
|
||||
public delegate bool ChessMoveFunc(Vector2 toPos, Vector2 fromPos);
|
||||
public Callable chessMoveFunc { get; set; }
|
||||
|
||||
public override void _Ready() {
|
||||
board = new VirtualBoard(9, 10);
|
||||
playerSelf = new Player(board);
|
||||
board.OnRemove += OnRemove;
|
||||
board.OnInsert += OnInsert;
|
||||
board.OnMove += OnMove;
|
||||
InitChessBoard();
|
||||
}
|
||||
|
||||
public override void _Input(InputEvent @event) {
|
||||
if (@event is InputEventMouseButton mouseEvent &&
|
||||
mouseEvent.Pressed &&
|
||||
mouseEvent.ButtonIndex == MouseButton.Left) {
|
||||
// HandleMouseClick(GetGlobalTransformWithCanvas().AffineInverse() * mouseButton.Position);
|
||||
HandleMouseClick(GetLocalMousePosition());
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleMouseClick(Vector2 clickPosition) {
|
||||
Vector2 clickBoardPos = (PosTrans.transArrToPix.AffineInverse() *
|
||||
clickPosition).Round();
|
||||
|
||||
playerSelf.HandleBoardPosClick(clickBoardPos);
|
||||
}
|
||||
|
||||
void OnMove(Vector2 from, Vector2 to) {
|
||||
chessMoveFunc.Call(to, from);
|
||||
}
|
||||
|
||||
void OnRemove(VirtualPiece piece) {
|
||||
// (piece.data as Node).QueueFree();
|
||||
if (piece?.data != null)
|
||||
RemoveChild(piece.data as Node);
|
||||
}
|
||||
|
||||
void OnInsert(VirtualPiece piece) {
|
||||
ChessPiece chess = piece.data as ChessPiece;
|
||||
AddChild(chess);
|
||||
}
|
||||
|
||||
public void InsertNode(ChessPiece node, Vector2 arrayPos) {
|
||||
AddChild(node);
|
||||
VirtualPiece piece = node.GetVirtualPiece();
|
||||
// piece.Move(vector);
|
||||
board.SetPiecePos(piece, arrayPos);
|
||||
}
|
||||
|
||||
|
||||
// using Godot;
|
||||
|
||||
// public enum ChessType
|
||||
// {
|
||||
// Carriage,
|
||||
// Horse,
|
||||
// Elephant,
|
||||
// Advisor,
|
||||
// General,
|
||||
// Cannon,
|
||||
// Pawn
|
||||
// }
|
||||
|
||||
// public class VirtualBoard
|
||||
// {
|
||||
// // ...其他原有成员变量...
|
||||
|
||||
// public VirtualBoard(Node root = null)
|
||||
// {
|
||||
// BoardRoot = root ?? GetTree().CurrentScene; // 如果未提供root,默认为当前场景
|
||||
// }
|
||||
|
||||
// public void InitChessBoard()
|
||||
// {
|
||||
// // 定义黑色和红色棋子的初始位置和类型
|
||||
// var positions = new (Vector2 position, ChessType type)[]
|
||||
// {
|
||||
// // 黑方棋子初始化...
|
||||
// // 示例省略具体位置和类型,你需要根据实际情况填写
|
||||
// // (new Vector2(x, y), ChessType.Pawn),
|
||||
|
||||
// // 红方棋子初始化...
|
||||
// // 同上
|
||||
// };
|
||||
|
||||
// // 初始化棋子
|
||||
// foreach (var (position, type) in positions)
|
||||
// {
|
||||
// var color = position.Y == 0 ? new Color("black") : new Color("red"); // 根据行判断颜色
|
||||
// var piece = CreateChessPiece(type, color);
|
||||
// InsertChess(piece, position);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private ChessPiece CreateChessPiece(ChessType type, Color labelColor)
|
||||
// {
|
||||
// // 根据ChessType创建对应的棋子实例并设置Label和颜色
|
||||
// // 这里需要你实现具体的逻辑,例如switch case或映射表来决定创建哪种棋子
|
||||
// // 返回创建的棋子实例
|
||||
// }
|
||||
|
||||
// // ...其他原有方法...
|
||||
// }
|
||||
|
||||
public void InitChessBoard() {
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "车",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(0, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "马",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(1, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "象",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(2, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "士",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(3, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "将",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(4, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "士",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(5, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "象",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(6, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "马",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(7, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "车",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(8, 0));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "炮",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(1, 2));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "炮",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(7, 2));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(0, 3));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(2, 3));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(4, 3));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(6, 3));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("black"),
|
||||
}, new Vector2(8, 3));
|
||||
|
||||
// -----------------------------------
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "车",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(0, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "马",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(1, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "象",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(2, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "士",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(3, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "将",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(4, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "士",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(5, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "象",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(6, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "马",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(7, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "车",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(8, 9));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "炮",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(1, 7));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "炮",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(7, 7));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(0, 6));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(2, 6));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(4, 6));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(6, 6));
|
||||
|
||||
InsertNode(new ChessPiece
|
||||
{
|
||||
PieceLabel = "卒",
|
||||
LabelColor = new Color("red"),
|
||||
}, new Vector2(8, 6));
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
// Chesspiece.cs
|
||||
using Godot;
|
||||
|
||||
public partial class ChessPiece : Sprite2D {
|
||||
// 文字内容
|
||||
[Export]
|
||||
public string PieceLabel { get; set; } = null;
|
||||
// 文字颜色(可导出以编辑器调整)
|
||||
[Export]
|
||||
public Color LabelColor { get; set; } = new Color("black");
|
||||
private Vector2 textureSize;
|
||||
|
||||
private Label labelOfChessName;
|
||||
private VirtualPiece piece;
|
||||
|
||||
public VirtualPiece GetVirtualPiece() {
|
||||
return piece;
|
||||
}
|
||||
|
||||
private void OnMove(Vector2 newPos) {
|
||||
Position = PosTrans.transArrToPix * new Vector2(newPos.X, newPos.Y);
|
||||
}
|
||||
|
||||
public void OnSelected(bool isSelected) {
|
||||
if (isSelected) {
|
||||
GD.Print($"{piece.Pos()} is selected");
|
||||
Transform *= transToSeleted;
|
||||
} else {
|
||||
GD.Print($"{piece.Pos()} is deselected");
|
||||
Transform *= transToSeleted.AffineInverse();
|
||||
}
|
||||
}
|
||||
|
||||
Transform2D transToSeleted = new Transform2D(
|
||||
new Vector2(1.2f, 0),
|
||||
new Vector2(0, 1.2f),
|
||||
new Vector2(0, 0)
|
||||
);
|
||||
|
||||
public ChessPiece(string name = "", Vector2 pos = new Vector2()) {
|
||||
PieceLabel = name;
|
||||
piece = new VirtualPiece(name, pos);
|
||||
piece.OnMove += OnMove;
|
||||
piece.OnSelected += OnSelected;
|
||||
piece.data = this;
|
||||
}
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready() {
|
||||
InitLabel();
|
||||
}
|
||||
|
||||
private void InitLabel() {
|
||||
// this.Texture.ResourcePath = "res://Asserts/ChesspieceBase.tres";
|
||||
Texture ??= (Texture2D)ResourceLoader.Load("res://Asserts/ChesspieceBase.tres");
|
||||
textureSize = Texture.GetSize();
|
||||
Vector2 labalPosition = new(
|
||||
-textureSize.X / 2,
|
||||
-textureSize.Y / 2);
|
||||
labelOfChessName = new Label {
|
||||
Text = PieceLabel,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Modulate = LabelColor,
|
||||
Position = labalPosition,
|
||||
Size = textureSize,
|
||||
};
|
||||
// labelOfChessName.SetAnchorsPreset(Control.LayoutPreset.FullRect);
|
||||
AddChild(labelOfChessName);
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
// 帅/将 (General) - 代表双方的最高统帅。
|
||||
// 子类名:ChessGeneral
|
||||
|
||||
// 仕/士 (Advisor) - 保护帅/将的近身侍卫。
|
||||
// 子类名:ChessAdvisor
|
||||
|
||||
// 相/象 (Elephant) - 行动受限,走田字格,不能过河。
|
||||
// 子类名:ChessElephant
|
||||
|
||||
// 車/车 (Chariot) - 横竖移动,威力巨大。
|
||||
// 子类名:ChessChariot
|
||||
|
||||
// 馬/马 (Horse) - 走日字形,跳跃式移动。
|
||||
// 子类名:ChessHorse
|
||||
|
||||
// 砲/炮 (Cannon) - 需要隔子才能吃子,直线移动。
|
||||
// 子类名:ChessCannon
|
||||
|
||||
// 兵/卒 (Pawn) - 最基础的棋子,过河后可横移。
|
||||
// 子类名:ChessPawn
|
@ -1,85 +0,0 @@
|
||||
using Godot;
|
||||
using RPPackage;
|
||||
|
||||
public partial class Global : Node
|
||||
{
|
||||
public RPClientEDWS RPClient = new();
|
||||
public string sessionId;
|
||||
public string URL = "wss://game.zzyxyz.com/";
|
||||
public Node CurrentScene { get; set; }
|
||||
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
RPClient.OnRPCError += (string errCode, string type, string cmd, string errMsg) => {
|
||||
GD.PrintErr($"errCode {errCode}, type/cmd {type}/{cmd}, errMsg {errMsg}");
|
||||
};
|
||||
RPClient.OnClose += (string eventName, object[] args) => {
|
||||
SetProcess(false);
|
||||
};
|
||||
RPClient.OnOpen += (string eventName, object[] args) => {
|
||||
RPClient.UserInit("undefined", "godot chessboard", () => {
|
||||
return RPClient.RegionAdd("server");
|
||||
});
|
||||
};
|
||||
Viewport root = GetTree().Root;
|
||||
CurrentScene = root.GetChild(root.GetChildCount() - 1);
|
||||
SetProcess(false);
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
RPClient.PollEx(delta);
|
||||
}
|
||||
|
||||
public override void _Notification(int what)
|
||||
{
|
||||
if (what == NotificationWMCloseRequest) {
|
||||
RPClient.Close();
|
||||
GetTree().Quit(); // default behavior
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void ChangeSceneCallback(Node newSence);
|
||||
private static ChangeSceneCallback changeSceneCallback = null;
|
||||
public void GotoScene(string path, ChangeSceneCallback callback = null)
|
||||
{
|
||||
// This function will usually be called from a signal callback,
|
||||
// or some other function from the current scene.
|
||||
// Deleting the current scene at this point is
|
||||
// a bad idea, because it may still be executing code.
|
||||
// This will result in a crash or unexpected behavior.
|
||||
|
||||
// The solution is to defer the load to a later time, when
|
||||
// we can be sure that no code from the current scene is running:
|
||||
if (callback != null) {
|
||||
changeSceneCallback = callback;
|
||||
}
|
||||
Callable callbackWrapper = new(null, nameof(changeSceneCallback));
|
||||
|
||||
CallDeferred(MethodName.DeferredGotoScene, path, callbackWrapper);
|
||||
changeSceneCallback = null;
|
||||
}
|
||||
|
||||
public void DeferredGotoScene(string path, Callable onLoaded)
|
||||
{
|
||||
// It is now safe to remove the current scene.
|
||||
CurrentScene.Free();
|
||||
|
||||
// Load a new scene.
|
||||
var nextScene = GD.Load<PackedScene>(path);
|
||||
|
||||
// Instance the new scene.
|
||||
CurrentScene = nextScene.Instantiate();
|
||||
if (changeSceneCallback != null) {
|
||||
onLoaded.Call(CurrentScene);
|
||||
}
|
||||
|
||||
// Add it to the active scene, as child of root.
|
||||
GetTree().Root.AddChild(CurrentScene);
|
||||
|
||||
// Optionally, to make it compatible with the SceneTree.change_scene_to_file() API.
|
||||
GetTree().CurrentScene = CurrentScene;
|
||||
}
|
||||
}
|
@ -1,320 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace RPPackage {
|
||||
public partial class RPClientBaseEDWS : EventDrivenWebSocket {
|
||||
|
||||
public delegate void RPClientEventHandler(string cmd, Dictionary data);
|
||||
public delegate void RPClientErrorHandler(string errCode, string type, string cmd, string errMsg);
|
||||
|
||||
public event RPClientEventHandler OnRPCUser;
|
||||
public event RPClientEventHandler OnRPCRegion;
|
||||
public event RPClientEventHandler OnRPCSession;
|
||||
public event RPClientEventHandler OnRPCMsg;
|
||||
public event RPClientErrorHandler OnRPCError;
|
||||
|
||||
public RPClientBaseEDWS() : base() {
|
||||
OnText += (text) => {
|
||||
GD.Print($"response: {text}");
|
||||
RPMessage msg = RPHelper.HandleIncomingMessage(text);
|
||||
if (msg.Code != "0000") {
|
||||
OnRPCError?.Invoke(msg.Code, msg.Type, msg.Cmd, msg.Data.ToString());
|
||||
return;
|
||||
}
|
||||
switch (msg.Type) {
|
||||
case "user":
|
||||
OnRPCUser?.Invoke(msg.Cmd, msg.Data);
|
||||
break;
|
||||
case "region":
|
||||
OnRPCRegion?.Invoke(msg.Cmd, msg.Data);
|
||||
break;
|
||||
case "session":
|
||||
OnRPCSession?.Invoke(msg.Cmd, msg.Data);
|
||||
break;
|
||||
case "msg":
|
||||
OnRPCMsg?.Invoke(msg.Cmd, msg.Data);
|
||||
break;
|
||||
default:
|
||||
OnRPCError?.Invoke(msg.Code, "unknown", msg.Cmd, msg.Data.ToString());
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void MakeRPCError(string errCode, string type, string cmd, string errMsg) {
|
||||
this.OnRPCError?.Invoke(errCode, type, cmd, errMsg ?? "null");
|
||||
}
|
||||
}
|
||||
|
||||
public partial class RPClientEDWS : RPClientBaseEDWS {
|
||||
string userName;
|
||||
string userId;
|
||||
string userToken;
|
||||
string regionId;
|
||||
|
||||
public string GetUserId() { return userId; }
|
||||
|
||||
public delegate void SessionRecvHandle(Dictionary msg);
|
||||
public event SessionRecvHandle OnPRCSessionRecv;
|
||||
|
||||
public event RPClientEventHandler OnPRCSessionExit;
|
||||
|
||||
public RPClientEDWS() : base() {
|
||||
OnRPCUser += (cmd, msg) => {
|
||||
switch (cmd) {
|
||||
case "init":
|
||||
userId = msg["userId"].AsString();
|
||||
userToken = msg["token"].AsString();
|
||||
_userInitCallback?.Invoke();
|
||||
break;
|
||||
case "rename":
|
||||
userName = msg["_"].AsString();
|
||||
break;
|
||||
default:
|
||||
MakeRPCError("0000", "user", "unknown", msg?.ToString());
|
||||
break;
|
||||
}
|
||||
};
|
||||
OnRPCRegion += (cmd, msg) => {
|
||||
switch (cmd) {
|
||||
case "add":
|
||||
break;
|
||||
case "inspect":
|
||||
// var regions = msg["_"].AsGodotArray<Dictionary>();
|
||||
_regionRecvCallback?.Invoke(cmd, msg);
|
||||
break;
|
||||
case "list":
|
||||
// var users = msg["_"].AsGodotArray<Dictionary>();
|
||||
_regionRecvCallback?.Invoke(cmd, msg);
|
||||
break;
|
||||
default:
|
||||
MakeRPCError("0000", "region", "unknown", msg?.ToString());
|
||||
break;
|
||||
}
|
||||
};
|
||||
OnRPCSession += (cmd, msg) => {
|
||||
switch (cmd) {
|
||||
case "sendAll":
|
||||
OnPRCSessionRecv?.Invoke(msg);
|
||||
break;
|
||||
case "create":
|
||||
break;
|
||||
case "ackCreate":
|
||||
// GD.PrintErr($"{cmd} {msg} {__SessionAckCreateCallback__ == null}");
|
||||
_sessionAckCreateCallback?.Invoke(cmd, msg);
|
||||
break;
|
||||
case "exit":
|
||||
OnPRCSessionExit?.Invoke(cmd, msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
OnRPCMsg += (cmd, msg) => {
|
||||
switch(cmd) {
|
||||
case "echo":
|
||||
GD.Print(msg["_"].AsString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
OnRPCError += (code, type, cmd, msg) => {
|
||||
};
|
||||
}
|
||||
|
||||
public void ClearRPCClientFunc() {
|
||||
|
||||
}
|
||||
|
||||
public bool IsOnline() {
|
||||
return GetIsConnected() && userId != null;
|
||||
}
|
||||
|
||||
public void ConnectServer(string url) {
|
||||
|
||||
}
|
||||
|
||||
public void ExitServer() {
|
||||
this.SendRPMessage(new RPMessage {
|
||||
Type = "user",
|
||||
Cmd = "exit",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
});
|
||||
userId = null;
|
||||
userToken = null;
|
||||
this.Close();
|
||||
}
|
||||
|
||||
public delegate bool UserInitCallback();
|
||||
private UserInitCallback _userInitCallback;
|
||||
public bool UserInit(string userName, string fingerPrint, UserInitCallback callback) {
|
||||
if (this.GetIsConnected() == false) {
|
||||
return false;
|
||||
}
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "user",
|
||||
Cmd = "init",
|
||||
Data = new Dictionary {
|
||||
{ "userName", userName },
|
||||
{ "fingerPrint", fingerPrint }
|
||||
}
|
||||
});
|
||||
_userInitCallback = null;
|
||||
if (callback != null) _userInitCallback += callback;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UserRename(string newName) {
|
||||
if (this.GetIsConnected() == false) {
|
||||
return false;
|
||||
}
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "user",
|
||||
Cmd = "rename",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "_", newName }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RegionAdd(string regionId) {
|
||||
if (this.GetIsConnected() == false || this.userId == null) {
|
||||
return false;
|
||||
}
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "region",
|
||||
Cmd = "add",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "regionId", regionId }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public delegate bool RegionInspectCallback(
|
||||
Array<Dictionary<string, string>> _
|
||||
);
|
||||
private RPClientEventHandler _regionRecvCallback;
|
||||
public bool RegionInspect(string regionId, RegionInspectCallback callback) {
|
||||
if (this.GetIsConnected() == false || this.userId == null) {
|
||||
return false;
|
||||
}
|
||||
_regionRecvCallback = null;
|
||||
_regionRecvCallback += (cmd, msg) => {
|
||||
if (cmd != "inspect") {
|
||||
return;
|
||||
}
|
||||
callback(msg["_"].AsGodotArray<Dictionary<string, string>>());
|
||||
};
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "region",
|
||||
Cmd = "inspect",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "regionId", regionId }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public delegate bool SessionAckCreateCallback(
|
||||
string sessionId,
|
||||
bool res,
|
||||
string reqUserId,
|
||||
string reqUserName
|
||||
);
|
||||
private RPClientEventHandler _sessionAckCreateCallback;
|
||||
public void RegSessionAckCreateCallback(SessionAckCreateCallback recvCallback) {
|
||||
_sessionAckCreateCallback = null;
|
||||
_sessionAckCreateCallback += (cmd, msg) => {
|
||||
string sessionId = msg["sessionId"].AsString();
|
||||
bool res = msg.ContainsKey("res") && msg["res"].AsBool();
|
||||
string reqUserId = msg.ContainsKey("reqUserId") ? msg["reqUserId"].AsString() : null;
|
||||
string reqUserName = msg.ContainsKey("reqUserName") ? msg["reqUserName"].AsString() : null;
|
||||
recvCallback(sessionId, res, reqUserId, reqUserName);
|
||||
};
|
||||
}
|
||||
public bool SessionCreate(string[] usersId) {
|
||||
if (this.GetIsConnected() == false || this.userId == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.SendRPMessage(new RPMessage {
|
||||
Type = "session",
|
||||
Cmd = "create",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "_", usersId }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SessionAckCreate(string sessionId, bool response)
|
||||
{
|
||||
if (this.GetIsConnected() == false || this.userId == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 根据响应情况发送确认消息给服务器
|
||||
string code = response ? "0000" : "0001";
|
||||
this.SendRPMessage(new RPMessage {
|
||||
Type = "session",
|
||||
Cmd = "ackCreate",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Code = code,
|
||||
Data = new Dictionary {
|
||||
{ "sessionId", sessionId },
|
||||
{ "res", response }
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SendSessionToAll(string sessionId, Variant data) {
|
||||
if (this.GetIsConnected() == false || this.userId == null || sessionId == null) {
|
||||
return false;
|
||||
}
|
||||
this.SendRPMessage(new RPMessage{
|
||||
Type = "session",
|
||||
Cmd = "sendAll",
|
||||
Uid = userId,
|
||||
Token = userToken,
|
||||
Data = new Dictionary {
|
||||
{ "sessionId", sessionId },
|
||||
{ "msg", data },
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// ws.OnOpen += (eventName, args) => {
|
||||
// ws.SendRPMessage(new RPMessage{
|
||||
// Type = "user",
|
||||
// Cmd = "tmp",
|
||||
// });
|
||||
// };
|
||||
|
||||
// ws.OnError += (eventName, args) => {
|
||||
// GD.PrintErr(args);
|
||||
// // SetProcess(false);
|
||||
// };
|
||||
|
||||
// ws.OnClose += (eventName, args) => {
|
||||
// // GD.Print("close");
|
||||
// SetProcess(false);
|
||||
// };
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace RPPackage {
|
||||
public static class RPHelper
|
||||
{
|
||||
public static Dictionary SerializeRPMessage(RPMessage message)
|
||||
{
|
||||
return message.ToDictionary();
|
||||
}
|
||||
|
||||
public static RPMessage DeserializeRPMessage(Dictionary data)
|
||||
{
|
||||
return new RPMessage
|
||||
{
|
||||
Type = data.ContainsKey("type") ? (string)data["type"] : null,
|
||||
Cmd = data.ContainsKey("cmd") ? (string)data["cmd"] : null,
|
||||
Code = data.ContainsKey("code") ? (string)data["code"] : null,
|
||||
Uid = data.ContainsKey("uid") ? (string)data["uid"] : null,
|
||||
Token = data.ContainsKey("token") ? (string)data["token"] : null,
|
||||
Data = data.ContainsKey("data") ? data["data"].AsGodotDictionary() : null,
|
||||
};
|
||||
}
|
||||
|
||||
// 假设你有WebSocket通信的实现,这里仅展示如何使用上述方法
|
||||
public static void SendRPMessage(this EventDrivenWebSocket ws, RPMessage message)
|
||||
{
|
||||
ws.SendJsonEx(RPHelper.SerializeRPMessage(message));
|
||||
}
|
||||
|
||||
public static RPMessage HandleIncomingMessage(string jsonMessage)
|
||||
{
|
||||
var dataDict = Json.ParseString(jsonMessage).AsGodotDictionary();
|
||||
if (dataDict != null)
|
||||
{
|
||||
return RPHelper.DeserializeRPMessage(dataDict);
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PrintErr("Failed to parse incoming message.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
namespace RPPackage {
|
||||
public class RPMessage
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Cmd { get; set; }
|
||||
public Dictionary Data { get; set; }
|
||||
|
||||
public string Uid { get; set; }
|
||||
public string Token { get; set; }
|
||||
public string Code { get; set; }
|
||||
public Dictionary ToDictionary()
|
||||
{
|
||||
var dict = new Dictionary();
|
||||
if (Type != null)
|
||||
dict.Add("type", Type);
|
||||
if (Cmd != null)
|
||||
dict.Add("cmd", Cmd);
|
||||
if (Data != null)
|
||||
dict.Add("data", Data);
|
||||
|
||||
if (Uid != null)
|
||||
dict.Add("uid", Uid);
|
||||
if (Token != null)
|
||||
dict.Add("token", Token);
|
||||
if (Code != null)
|
||||
dict.Add("code", Code);
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class EventDrivenWebSocket : WebSocketPeer {
|
||||
public delegate void WebSocketEventHandler(string eventName, params object[] args);
|
||||
public delegate void WSBinMsgEventHandler(byte[] args);
|
||||
public delegate void WSMsgEventHandler(string args);
|
||||
|
||||
public event WebSocketEventHandler OnOpen;
|
||||
public event WSBinMsgEventHandler OnMessage;
|
||||
public event WSMsgEventHandler OnText;
|
||||
public event WSBinMsgEventHandler OnBinary;
|
||||
public event WebSocketEventHandler OnClose;
|
||||
public event WebSocketEventHandler OnError;
|
||||
|
||||
private bool isConnected = false;
|
||||
private bool isCloseEventFired = false;
|
||||
private double connectingTime = double.NegativeInfinity;
|
||||
|
||||
|
||||
public EventDrivenWebSocket() : base() {
|
||||
isConnected = false;
|
||||
}
|
||||
|
||||
public bool GetIsConnected() {
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
public void PollEx(double delta) {
|
||||
base.Poll();
|
||||
CheckAndDispatchEvents(delta);
|
||||
}
|
||||
|
||||
public void ConnectToUrlEx(string url, double delayTime = 3,
|
||||
TlsOptions tlsClientOptions = null) {
|
||||
if (connectingTime >= 0) {
|
||||
return;
|
||||
}
|
||||
Error err = ConnectToUrl(url, tlsClientOptions);
|
||||
if (err != Error.Ok) {
|
||||
OnError?.Invoke("error", err);
|
||||
}
|
||||
connectingTime = delayTime;
|
||||
}
|
||||
|
||||
protected void CheckAndDispatchEvents(double delta) {
|
||||
var state = GetReadyState();
|
||||
switch (state) {
|
||||
case State.Open when !isConnected:
|
||||
isConnected = true;
|
||||
OnOpen?.Invoke("open", null);
|
||||
break;
|
||||
case State.Open:
|
||||
while (GetAvailablePacketCount() > 0) {
|
||||
byte[] packet = GetPacket();
|
||||
OnMessage?.Invoke(packet);
|
||||
if (WasStringPacket()) {
|
||||
OnText?.Invoke(packet.GetStringFromUtf8());
|
||||
} else {
|
||||
OnBinary?.Invoke(packet);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case State.Closed:
|
||||
connectingTime = double.NegativeInfinity;
|
||||
OnClose?.Invoke("closed", GetCloseCode(), GetCloseReason());
|
||||
isConnected = false;
|
||||
break;
|
||||
case State.Closing:
|
||||
// OnClose?.Invoke("closing");
|
||||
break;
|
||||
case State.Connecting:
|
||||
if (connectingTime >= 0) {
|
||||
connectingTime -= delta;
|
||||
} else if (connectingTime != double.NegativeInfinity){
|
||||
connectingTime = double.NegativeInfinity;
|
||||
Close();
|
||||
OnError?.Invoke("connectTimeOut", Error.Timeout);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// 可以在这里处理其他状态或错误
|
||||
OnError?.Invoke("error", "Unknown WebSocket state.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SendBinaryEx(byte[] data) {
|
||||
SendEx(data);
|
||||
}
|
||||
|
||||
public void SendJsonEx(Dictionary msg) {
|
||||
SendTextEx(Json.Stringify(msg));
|
||||
}
|
||||
|
||||
public Error SendTextEx(string message) {
|
||||
if (isConnected) {
|
||||
return SendText(message);
|
||||
} else {
|
||||
OnError?.Invoke("error", "Attempt to send on a closed connection.");
|
||||
return Error.ConnectionError;
|
||||
}
|
||||
}
|
||||
|
||||
public Error SendEx(byte[] message, WriteMode writeMode = WriteMode.Binary) {
|
||||
if (isConnected) {
|
||||
return Send(message, writeMode);
|
||||
} else {
|
||||
OnError?.Invoke("error", "Attempt to send on a closed connection.");
|
||||
return Error.ConnectionError;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
// using System.Numerics;
|
||||
using Godot;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
public class MoveRecords<T> {
|
||||
private readonly LinkedList<MoveRecord> records = new LinkedList<MoveRecord>(); // 使用队列替换栈
|
||||
private readonly int maxRecords; // 记录上限
|
||||
private Action<T, T, Vector2, Vector2> onAddRecordCallback; // 添加记录时的回调
|
||||
private Action<T, T, Vector2, Vector2> onUndoRecordCallback; // 撤销记录时的回调
|
||||
|
||||
public MoveRecords(
|
||||
Action<T, T, Vector2, Vector2> onAddRecordCallback = null,
|
||||
Action<T, T, Vector2, Vector2> onUndoRecordCallback = null,
|
||||
int maxRecords = 32) {
|
||||
this.maxRecords = maxRecords;
|
||||
this.onAddRecordCallback = onAddRecordCallback;
|
||||
this.onUndoRecordCallback = onUndoRecordCallback;
|
||||
}
|
||||
|
||||
public void AddRecord(T newNode, T oldNode, Vector2 newPos, Vector2 oldPos) {
|
||||
// 达到记录上限时,移除最远的记录(队首元素)
|
||||
if (records.Count >= maxRecords) {
|
||||
records.RemoveFirst();
|
||||
}
|
||||
var record = new MoveRecord(newNode, oldNode, newPos, oldPos);
|
||||
// 触发添加记录的回调
|
||||
onAddRecordCallback?.Invoke(newNode, oldNode, newPos, oldPos);
|
||||
// GD.Print("In func Addrecord: ", record.NewNode, "->", record.OldNode, ":", record.NewPos, "->", record.OldPos);
|
||||
records.AddLast(record); // 将新记录加入队尾
|
||||
}
|
||||
|
||||
public void Undo() {
|
||||
if (records.Count == 0) return;
|
||||
MoveRecord record = records.Last.Value; // 移除并获取队首的记录以执行撤销操作
|
||||
records.RemoveLast();
|
||||
// 触发撤销记录的回调
|
||||
onUndoRecordCallback?.Invoke(record.NewNode, record.OldNode, record.NewPos, record.OldPos);
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
records.Clear();
|
||||
}
|
||||
|
||||
private class MoveRecord {
|
||||
public T NewNode { get; }
|
||||
public T OldNode { get; }
|
||||
public Vector2 NewPos { get; }
|
||||
public Vector2 OldPos { get; }
|
||||
|
||||
public MoveRecord(T newNode, T oldNode, Vector2 newPos, Vector2 oldPos) {
|
||||
NewNode = newNode;
|
||||
OldNode = oldNode;
|
||||
OldPos = oldPos;
|
||||
NewPos = newPos;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Godot;
|
||||
|
||||
public static class PosTrans {
|
||||
private static readonly int pixGripSize = 32;
|
||||
public static Transform2D transArrToPix = new(
|
||||
new Vector2(pixGripSize, 0),
|
||||
new Vector2(0, pixGripSize),
|
||||
new Vector2(-4, -4.5f) * pixGripSize
|
||||
);
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
// using System.Numerics;
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
public class VirtualBoard {
|
||||
private readonly int Rows;
|
||||
private readonly int Cols;
|
||||
private readonly VirtualPiece[,] pieces;
|
||||
|
||||
// <oldPiece, newPiece>
|
||||
public event Action<VirtualPiece, VirtualPiece> OnSetPiecePos;
|
||||
public event Action<VirtualPiece> OnInsert;
|
||||
public event Action<VirtualPiece> OnRemove;
|
||||
public event Action<Vector2, Vector2> OnMove;
|
||||
|
||||
public VirtualBoard(int Rows, int Cols) {
|
||||
this.Rows = Rows;
|
||||
this.Cols = Cols;
|
||||
pieces = new VirtualPiece[Rows, Cols];
|
||||
}
|
||||
|
||||
public bool ArrPosOutOfRange(Vector2 arrayPos) {
|
||||
return arrayPos.X < 0 || arrayPos.X >= Rows || arrayPos.Y < 0 || arrayPos.Y >= Cols;
|
||||
}
|
||||
|
||||
public VirtualPiece GetPiece(Vector2 arrayPos) {
|
||||
if (ArrPosOutOfRange(arrayPos)) return null;
|
||||
return pieces[(int)arrayPos.X, (int)arrayPos.Y];
|
||||
}
|
||||
|
||||
public VirtualPiece SetPiecePos(VirtualPiece piece, Vector2 arrayPos) {
|
||||
VirtualPiece ret = null;
|
||||
if (ArrPosOutOfRange(arrayPos)) return ret;
|
||||
ret = pieces[(int)arrayPos.X, (int)arrayPos.Y];
|
||||
pieces[(int)arrayPos.X, (int)arrayPos.Y] = piece;
|
||||
OnSetPiecePos?.Invoke(ret, piece);
|
||||
piece?.Move(arrayPos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool InsertPiece(VirtualPiece piece, Vector2 arrayPos) {
|
||||
if (GetPiece(arrayPos) != null) {
|
||||
return false;
|
||||
}
|
||||
OnInsert?.Invoke(piece);
|
||||
SetPiecePos(piece, arrayPos);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool MovePiece(Vector2 from, Vector2 to) {
|
||||
if (ArrPosOutOfRange(to) || ArrPosOutOfRange(from)) {
|
||||
return false;
|
||||
}
|
||||
if (GetPiece(to) != null) {
|
||||
return false;
|
||||
}
|
||||
OnMove?.Invoke(from, to);
|
||||
SetPiecePos(SetPiecePos(null, from), to);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RemovePiece(Vector2 pos) {
|
||||
OnRemove?.Invoke(GetPiece(pos));
|
||||
return SetPiecePos(null, pos) != null;
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
for (int i = 0; i < Rows; i++) {
|
||||
for (int j = 0; j < Cols; j++) {
|
||||
RemovePiece(new Vector2(i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// using System.Numerics;
|
||||
using Godot;
|
||||
|
||||
using System;
|
||||
|
||||
public class VirtualPiece {
|
||||
private Vector2 pos; // 注意这个坐标的非像素坐标而是棋盘坐标
|
||||
|
||||
private string name;
|
||||
private bool isSelected;
|
||||
public object data;
|
||||
|
||||
public event Action<Vector2> OnMove;
|
||||
public event Action<bool> OnSelected;
|
||||
|
||||
public void Move(Vector2 pos) {
|
||||
this.pos = pos;
|
||||
OnMove?.Invoke(pos);
|
||||
}
|
||||
|
||||
public Vector2 Pos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
public void Selected(bool isSelected) {
|
||||
if (this.isSelected != isSelected) {
|
||||
OnSelected?.Invoke(isSelected);
|
||||
this.isSelected = isSelected;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSelected() {
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
public VirtualPiece(string name = "", Vector2 pos = new Vector2()) {
|
||||
this.name = name;
|
||||
this.pos = pos;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user