Suppose there are browsers in the form of clients and there is a server. And they communicate with each other using WebSocket.

As a rule, a simple version of coordination in this version looks like a pack of Iphs both on the client side and on the server side. Customer example:

ws = new WebSocket("wss://site.com:8888/"); ws.onopen = function() { ws.send({'e':"new", 'x':lPlayer.getX(), 'y':lPlayer.getY()}); }; ws.onmessage = function(event){ var msg = JSON.parse(event.data); if(msg.e == 'new'){ var newPlayer = new Player(scene, {x,y,z}, msg.x, msg.y); newPlayer.id = msg.id; newPlayer.init(msg.id); remotePlayers.push(newPlayer); }else if(msg.e == 'move' ){ var movePlayer = playerById(msg.id); movePlayer.set(msg.x, msg.y, msg.z); }else if(msg.e == 'rotate' ){ var rotPlayer = playerById(msg.id); rotPlayer.setA(msg.a); rotPlayer.setB(msg.b); } } 

Sample server:

 var WebSocketServer = require('ws').Server; var wss = new WebSocketServer({port: 8888}); wss.on('connection', function(ws) { clients[max_id] = ws; this.id = max_id; ws.on('message', function(e) { if(ee == 'new'){ var p = new Player(max_id, ex, ey); this.player = p; clients.send_all({'e':"new", 'id':p.id, 'x':px(), 'y':py,'z':pz}); players.push(p); }else if (ee == 'move') { var p = this.player; p.set(ex, ey, ez); clients.send_all({'e':"move", 'id':p.id, 'x':p.getX(), 'y':p.getY(), 'z':p.getZ(), 'msg':'move'}) } 

Well, in all this, the most important nuance is that any activity of the player always comes from the client, from which a message is sent to the server with sockets, and then the server is transmitted to all other players for coordination.

A bot activity should always produce a server and broadcast to everyone else. And this is just the main dilemma. So far, the idea comes to mind that it is necessary to register in each activity of the players, that is, for each if (ee == 'move') or for each if (ee == 'shot') some kind of bot action.

It might look something like this:

  }else if (ee == 'move') { var p = this.player; p.set(ex, ey, ez); clients.send_all({'e':"move", 'id':p.id, 'x':px, 'y':py, 'z':pz}) var bot = this.player.bot; clients.send_all({'e':"move", 'id':bot.id, 'x':bot.x, 'y':bot.y, 'z':bot.z}) } 

But further on this fantasy ends. The question is how best to organize the movement of the bot and in the architecture of the game?

Perhaps there are already in other languages ​​similar libraries in Python or any other PHP .

  • one
    Or it may not overload the server code with the actions of the bot. It can make the bot separately in the form of a client that connects to the server almost like a regular user. - Mike
  • In princep, too, an option, but I do not quite know how to implement it. Because clients seem to be connected with a browser 1 browser 1 client. Where does the bot come from? - alex10
  • Well, we need a completely non-standard client, because he doesn’t have to do what the rest of them do — display in the browser what happened in the game. Those. You can write it in any language. It is desirable that for this language there was a client library for WebSocket, although as I understand the protocol there is not difficult, it will take a while to implement it - Mike
  • Well, and yet I do not quite understand how to implement it in this case? Should it be another process running on the server and issuing a browser? Or should the browser of the first client connect this? - alex10
  • Yes, the process is on the server. browser emulation can be called a stretch. The browser usually does a lot of what the bot doesn't need at all. Yes, it must respond to the server using the same protocol that a regular client is using. Well, send requests to perform their actions as a player - Mike

2 answers 2

It would be better if the core of your application / game did not depend on the type of transport.

 /** Объект вашей игры */ var Game = { /** ф-ция принимает команду и данные, а потом уже выполняет ее */ command: function (cmd, data, id) { /** здесь уже можно делать что угодно, как с командой, так и с данными */ } } 

The scheme is such

  • The player committed the action
  • According to websocket data transferred to the server
  • The server passed the data to the engine / core game
  • The game processed the data, made the necessary updates.
  • The game returns a new state of itself to the server
  • The server sends all updated status.

From this it turns out that the server is only an intermediary between the game and the client.

In the example, it looks like this:

 var WebSocketServer = require('ws').Server; var wss = new WebSocketServer({port: 8888}); wss.on('connection', function(ws) { clients[max_id] = ws; this.id = max_id; ws.on('message', function(e) { var cmd = ee; Game.command(cmd, e, this.id); } } /** * @param {string} cmd - команда, которую отослал клиент * @param {Object} data - данные команды * @param {number} id - id клиента, который послал команду */ Game.command = function (cmd, data, id) { /** * тут вся логика игры, команд и так далее */ // результат выполнения отправляйте всем клиентам return cmdResult; } 

How does this help with the bot?

Just give him the opportunity to directly send commands to the game, because we already have a Game.command function that we can use. Create a copy of the bot, and either pass the link to the game, or let the bot have the game already in scope. You can even create a separate interface for the bot, which at the end still goes into Game.command .

When the bot executes the command, tell the server to send the data, you can add to the ws object functions or a custom event that will be responsible for this. We'll have to really rewrite the logic of the game, because now the players will be stored in the Game object, but you will not have problems in the future, since you have separated the transport module from the game.

    I also think that the bot should be a separate client. Not a browser, but simply a client to which the server will be treated the same as any other client. That is, the server generally will not know who it is, a bot or not

     //some_bot.js var WebSocket = require('ws'); var ws = new WebSocket('ws://www.host.com/path'); var botsLogic = { CRAZY: crazyBot } function botInit(x, y, z, type){ return botsLogic[type](z, y, z); } function crazyBot(x, y, z) { ws.onopen = function() { ws.send({'e':"new", 'x':x, 'y':y, 'z': z}); }; //do some actions } 

    The question is who will initialize the bot? Need some sort of factory or dip. Dumb example:

     function startGame(){ var newServer = new Server(); newServer.start(); require("bot-init").initBot(1, 2, 3, "CRAZY") } 

    And yet, try not to write so many iphas. Because every new act amazes a new IF. This is bad code. Read about the design pattern Strategy, I think this pattern is well suited for such a case.)

    • Well, myths are given as an example for simplicity, so as not to explain for a long time what I want. I just do not quite understand how to make it a separate client? If he is a client, either he needs to be launched as another process, the client process, so to speak, or it’s necessary to insert the client’s code into the client’s part of the game and it’s possible that the browser of one of the real players will execute the bot’s code and everything else will be translated for synchronization what makes the bot of one of the players that in general it is not quite right. - alex10
    • And why you actually do not like a separate process. The server process is run like that. Here is how something by analogy to start the second process. They even wrote how it will work as a WebSocks client. It feels like starting a process is a problem. Google on request node.js запуск скрипта immediately gives out a bunch of ways. - Mike
    • Well, firstly, because I'm not doing it for myself and I want everything to work out of the box. Launched a server script and that's it. And secondly, now everything is done so that all the information is stored in memory. For example, all the incoming players are divided into rooms, the bot is initialized in each room. All this is neatly kept in jason. And if now there will be a separate process that most likely knows nothing about rooms, players, and so on. then it will turn out that everything needs to be rewritten again and a lot of everything duplicated. - alex10
    • No, IMHO, the logic of the bot must be executed on the server. At least for the sake of safety. I tried to show in code, but apparently not very clear. Look, your system is event based. That is, the newUser event poked - the scene was updated, the move event - the scene was updated, and so on. you make a liner initializer and, depending on the logic of the game, you initialize the bot, not in a separate process, everything is done with the server. One script that loses the server and initializes the licenser client who can create bots, that's all. - Vitalik Teremasov