No one is really playing the game because there’s no one to fight because no one is really playing the game … it’s a catch 22
I want to make the game fun even when people aren’t online. So I want to add enemies to the world!
The problem is all of the logic relating to the world is written in three.js on the client
I have no way to add logic relating to the world on the server side (which is also written in JS). Does anyone have any idea how I could possible “render” the world so to speak in my server and add enemies to it that can interact with the world as well?
How do you validate it then? For online games most is managed on server side, at minimum anything that requires to be validated and restricted to prevent obvious easy manipulations, a lot even just transfer the inputs to control the character remotely, depending on the game you can abstract this though. Before you even get to the AI, how is your client/server managed, which side validates the player collisions/motion and arrow shots?
Oh man, there’s a whole can of worms related to online multiplayer
Overall - I agree with @Fyrestar, you want to make sure that all of your gameplay-related simulation is being done on the server, clients submit commands to the server and receive world-state updates. Start from there maybe?
There are a lot of other problems to tackle, especially in fast-paced games such as shooters, things like client-side prediction, re-simulation, packet loss, entity interpolation. You’re in for an interesting journey if you decide to make it work in a decently laggy environment (~100ms + delay)
As others have mentioned - having logic server-side is more complex, but it is the right thing to do.
As far as enemies go, instead of setting up an AI (which can be very complicated) you could try something simpler.
For example, In Overwatch I’ve seen target dummies. They move in straight lines and fire projectiles in the direction of the player. It’s pretty basic, but allows at least practicing movement, dodging and aiming against a moving target
Two months ago I wrote this game, which I’m not particularly proud of.
Obviously it suffers from the same problem as yours : no opponent to play with. You can test it in two windows though.
I urge you to put all the logic on server… If I learnt one thing from this project, it’s that for fast-paced games it’s absolutely necessary, because of latency. Latency is on average 200ms depending on how far is the client from the server. If client A interact with client B, you want client A to send input to the server, server compute, then server send update to clients A and B, which amount for 400ms from client A’s point of view. If you did the computation on client B, the journey would take twice that time, and the lag would be aweful. And of course if you did the computation on client A and client B separately, you would have different results because of the latency, so it’s not an option.
In NodeJS you can import three.js as an npm package. That gives you all the possibilities that you have on the client. You can build your world, load models, apply physics - basically anything that you need to validate and control the world state (and preferably no more than that, in order to save performance).
For example:
The player sends a message that he wants to move forward
Server checks and checks whether or not bounding box collision occurs
If no, then allow the player to change his position
If yes, then prevent it
In some loop, the server will send the changed world state to all the players
So basically, you’re doing what you would be doing normally, except you skip the rendering step (obviously each player needs to render the world from his point of view).