haxball / haxball-issues

116 stars 43 forks source link

Possibility to implement plugins for Haxball #257

Open FrescoPL opened 6 years ago

FrescoPL commented 6 years ago

Hey. I have an idea, it consists in implementing plugins for Haxball. What is it actually about? I would like it to be possible to add plug-ins can be turned on during the game. With its help, you can make additional option, which is useful for a dedicated map, game style.

Example:

I think that the above-mentioned examples should be enough to convince many players how powerful this idea. I know you can do it from the technical side. Really, this idea is worth pursuing, because it would greatly develop this game.

Regards, Fresco

basro commented 6 years ago

You might want to check out the new headless host api additions, you can probably implement a referee bot with it.

FrescoPL commented 6 years ago

ok, my friend i have to say with pleasure that u made such a great amounts of work, but there is only one thing which u have to do to be my God. Please implement this on non-headless hosts too.

8xsdjvm

Ur biggest fan, Fresco.

morko commented 6 years ago

Hello. Me and one other player are currently thinking about implementing a similar plugin system. Do you think u would be implementing this kind of thing yourself @basro?

U would need some function to attach multiple events to the roomObject or a JavaScript Proxy object to intercept the function of = operator and instead add the event handler to a map. My map would have event names as keys with binary search tree or similar data structure as values to keep the order of the events as the scripts are ordered and the roomObject would search from this map to execute each handler instead.

Ofcourse my implementation is just a suggestion and there might be better ways.

basro commented 6 years ago

This is fairly more complicated than the headless host since it requires some way to start and stop the plugins, ensuring they don't leak is probably something most people wont even do.

It also requires storing files locally and permanently, which is not easy and is also the reason why the /store command doesn't exist yet.

Also encouraging users to run third party javascript might not be a good idea.

I can see the potential of such a feature so I'll still consider it in the future, but for now such a thing wont be implemented.

@morko, I'd ask you not to try implementing this yourself since there's no stable api to do this in the non headless version. Even if you manage to implement it, it would break every time I release a new version of haxball. Things like this can become a real problem if they proliferate since it puts pressure against making new updates.

morko commented 6 years ago

I'm talking about implementing this with the headless api you have provided by just extending its functionality. I think only thing that would break it is you would stop using the convention of 'onBla' camelCase style for your event handler functions or if you would implement your own way to attach multiple event handlers for the roomObject and remove the option to assign them with the = operator.

My idea would also be to provide some set of modular scripts to control the room like shown in the screenshot by @FrescoPL so imo it would in fact encourage users to not use third party javascript which is the case now, because ppl with not so much experience in programming are relying on other ppls scripts that they just paste into the dev console without knowing exactly what they do.

basro commented 6 years ago

I see, in that case feel free to implement it!

I actually expect people to do things like that on top of the exposed api and I know of a few who are already implementing wrappers that allow multiple subscribers to the events.

olehmisar commented 6 years ago

I implemented wrapper for easier headless host managing. Code samples:

// You can use camelCase, PascalCase, snake_case or kebab-case
room.on('player-join', function (player) {
  this.sendChat(player.name + ' joined')
})
room.on('playerJoin', function (player) {
  // This will be executed after above callback
  this.kickPlayer(player.id)
})

Also, you can extend room object:

room.extend('kickPlayers', function (playerCount) {
  this.getPlayerList()
    .slice(0, playerCount)
    .forEach(p => this.kickPlayer(p.id))
})

// And then somewhere in the code
room.kickPlayers(2) // kick 2 first players

Also you can bind callbacks to new events:

// Second argument — callback name
room.extend('kickPlayers', 'playersKicked', function (playerCount) {
  this.getPlayerList()
    .slice(0, playerCount)
    .forEach(p => this.kickPlayer(p.id))
})

room.on('players-kicked', function () {
  console.log('players are kicked')
})

Also I have easy commands management and player object extension