1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Clientevent refactor (#6320)

* Refactor clientevent structure

* Move structure outside of client header

* Create client events on heap not stack, this remove the ClientEvent object copy

* Use clientEventHandler to route events
This commit is contained in:
Loïc Blot 2017-08-28 20:02:23 +02:00 committed by GitHub
parent 6fd8a27c91
commit 5f38fe33f8
7 changed files with 608 additions and 505 deletions

View file

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "client/renderingengine.h"
#include "camera.h"
#include "client.h"
#include "client/clientevent.h"
#include "client/inputhandler.h"
#include "client/tile.h" // For TextureSource
#include "client/keys.h"
@ -1181,6 +1182,13 @@ struct RunStats {
Jitter dtime_jitter, busy_time_jitter;
};
class Game;
struct ClientEventHandler
{
void (Game::*handler)(ClientEvent *, CameraOrientation *);
};
/****************************************************************************
THE GAME
****************************************************************************/
@ -1361,6 +1369,25 @@ protected:
private:
void showPauseMenu();
// ClientEvent handlers
void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HandleParticleEvent(ClientEvent *event,
CameraOrientation *cam);
void handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
CameraOrientation *cam);
void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
InputHandler *input;
Client *client;
@ -3125,272 +3152,301 @@ inline void Game::step(f32 *dtime)
}
}
const ClientEventHandler Game::clientEventHandler[CLIENTEVENT_MAX] = {
{&Game::handleClientEvent_None},
{&Game::handleClientEvent_PlayerDamage},
{&Game::handleClientEvent_PlayerForceMove},
{&Game::handleClientEvent_Deathscreen},
{&Game::handleClientEvent_ShowFormSpec},
{&Game::handleClientEvent_ShowLocalFormSpec},
{&Game::handleClientEvent_HandleParticleEvent},
{&Game::handleClientEvent_HandleParticleEvent},
{&Game::handleClientEvent_HandleParticleEvent},
{&Game::handleClientEvent_HudAdd},
{&Game::handleClientEvent_HudRemove},
{&Game::handleClientEvent_HudChange},
{&Game::handleClientEvent_SetSky},
{&Game::handleClientEvent_OverrideDayNigthRatio},
{&Game::handleClientEvent_CloudParams},
};
void Game::processClientEvents(CameraOrientation *cam)
void Game::handleClientEvent_None(ClientEvent *event, CameraOrientation *cam)
{
FATAL_ERROR("ClientEvent type None received");
}
void Game::handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam)
{
if (client->getHP() == 0)
return;
if (client->moddingEnabled()) {
client->getScript()->on_damage_taken(event->player_damage.amount);
}
runData.damage_flash += 95.0 + 3.2 * event->player_damage.amount;
runData.damage_flash = MYMIN(runData.damage_flash, 127.0);
LocalPlayer *player = client->getEnv().getLocalPlayer();
player->hurt_tilt_timer = 1.5;
player->hurt_tilt_strength =
rangelim(event->player_damage.amount / 4, 1.0, 4.0);
client->event()->put(new SimpleTriggerEvent("PlayerDamage"));
}
void Game::handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam)
{
cam->camera_yaw = event->player_force_move.yaw;
cam->camera_pitch = event->player_force_move.pitch;
}
void Game::handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam)
{
// This should be enabled for death formspec in builtin
client->getScript()->on_death();
LocalPlayer *player = client->getEnv().getLocalPlayer();
/* Handle visualization */
runData.damage_flash = 0;
player->hurt_tilt_timer = 0;
player->hurt_tilt_strength = 0;
}
void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam)
{
if (event->show_formspec.formspec->empty()) {
if (current_formspec && (event->show_formspec.formname->empty()
|| *(event->show_formspec.formname) == cur_formname)) {
current_formspec->quitMenu();
}
} else {
FormspecFormSource *fs_src =
new FormspecFormSource(*(event->show_formspec.formspec));
TextDestPlayerInventory *txt_dst =
new TextDestPlayerInventory(client, *(event->show_formspec.formname));
create_formspec_menu(&current_formspec, client, &input->joystick,
fs_src, txt_dst);
cur_formname = *(event->show_formspec.formname);
}
delete event->show_formspec.formspec;
delete event->show_formspec.formname;
}
void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam)
{
FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec);
LocalFormspecHandler *txt_dst =
new LocalFormspecHandler(*event->show_formspec.formname, client);
create_formspec_menu(&current_formspec, client, &input->joystick, fs_src, txt_dst);
delete event->show_formspec.formspec;
delete event->show_formspec.formname;
}
void Game::handleClientEvent_HandleParticleEvent(ClientEvent *event,
CameraOrientation *cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
client->getParticleManager()->handleParticleEvent(event, client, player);
}
void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
while (client->hasClientEvents()) {
ClientEvent event = client->getClientEvent();
u32 id = event->hudadd.id;
switch (event.type) {
case CE_PLAYER_DAMAGE:
if (client->getHP() == 0)
break;
if (client->moddingEnabled()) {
client->getScript()->on_damage_taken(event.player_damage.amount);
}
HudElement *e = player->getHud(id);
runData.damage_flash += 95.0 + 3.2 * event.player_damage.amount;
runData.damage_flash = MYMIN(runData.damage_flash, 127.0);
player->hurt_tilt_timer = 1.5;
player->hurt_tilt_strength =
rangelim(event.player_damage.amount / 4, 1.0, 4.0);
client->event()->put(new SimpleTriggerEvent("PlayerDamage"));
break;
case CE_PLAYER_FORCE_MOVE:
cam->camera_yaw = event.player_force_move.yaw;
cam->camera_pitch = event.player_force_move.pitch;
break;
case CE_DEATHSCREEN:
// This should be enabled for death formspec in builtin
client->getScript()->on_death();
/* Handle visualization */
runData.damage_flash = 0;
player->hurt_tilt_timer = 0;
player->hurt_tilt_strength = 0;
break;
case CE_SHOW_FORMSPEC:
if (event.show_formspec.formspec->empty()) {
if (current_formspec && (event.show_formspec.formname->empty()
|| *(event.show_formspec.formname) == cur_formname)) {
current_formspec->quitMenu();
}
} else {
FormspecFormSource *fs_src =
new FormspecFormSource(*(event.show_formspec.formspec));
TextDestPlayerInventory *txt_dst =
new TextDestPlayerInventory(client, *(event.show_formspec.formname));
create_formspec_menu(&current_formspec, client, &input->joystick,
fs_src, txt_dst);
cur_formname = *(event.show_formspec.formname);
}
delete event.show_formspec.formspec;
delete event.show_formspec.formname;
break;
case CE_SHOW_LOCAL_FORMSPEC:
{
FormspecFormSource *fs_src = new FormspecFormSource(*event.show_formspec.formspec);
LocalFormspecHandler *txt_dst = new LocalFormspecHandler(*event.show_formspec.formname, client);
create_formspec_menu(&current_formspec, client, &input->joystick,
fs_src, txt_dst);
}
delete event.show_formspec.formspec;
delete event.show_formspec.formname;
break;
case CE_SPAWN_PARTICLE:
case CE_ADD_PARTICLESPAWNER:
case CE_DELETE_PARTICLESPAWNER:
client->getParticleManager()->handleParticleEvent(&event, client, player);
break;
case CE_HUDADD:
{
u32 id = event.hudadd.id;
HudElement *e = player->getHud(id);
if (e != NULL) {
delete event.hudadd.pos;
delete event.hudadd.name;
delete event.hudadd.scale;
delete event.hudadd.text;
delete event.hudadd.align;
delete event.hudadd.offset;
delete event.hudadd.world_pos;
delete event.hudadd.size;
continue;
}
e = new HudElement;
e->type = (HudElementType)event.hudadd.type;
e->pos = *event.hudadd.pos;
e->name = *event.hudadd.name;
e->scale = *event.hudadd.scale;
e->text = *event.hudadd.text;
e->number = event.hudadd.number;
e->item = event.hudadd.item;
e->dir = event.hudadd.dir;
e->align = *event.hudadd.align;
e->offset = *event.hudadd.offset;
e->world_pos = *event.hudadd.world_pos;
e->size = *event.hudadd.size;
u32 new_id = player->addHud(e);
//if this isn't true our huds aren't consistent
sanity_check(new_id == id);
}
delete event.hudadd.pos;
delete event.hudadd.name;
delete event.hudadd.scale;
delete event.hudadd.text;
delete event.hudadd.align;
delete event.hudadd.offset;
delete event.hudadd.world_pos;
delete event.hudadd.size;
break;
case CE_HUDRM:
{
HudElement *e = player->removeHud(event.hudrm.id);
delete e;
}
break;
case CE_HUDCHANGE:
{
u32 id = event.hudchange.id;
HudElement *e = player->getHud(id);
if (e == NULL) {
delete event.hudchange.v3fdata;
delete event.hudchange.v2fdata;
delete event.hudchange.sdata;
delete event.hudchange.v2s32data;
continue;
}
switch (event.hudchange.stat) {
case HUD_STAT_POS:
e->pos = *event.hudchange.v2fdata;
break;
case HUD_STAT_NAME:
e->name = *event.hudchange.sdata;
break;
case HUD_STAT_SCALE:
e->scale = *event.hudchange.v2fdata;
break;
case HUD_STAT_TEXT:
e->text = *event.hudchange.sdata;
break;
case HUD_STAT_NUMBER:
e->number = event.hudchange.data;
break;
case HUD_STAT_ITEM:
e->item = event.hudchange.data;
break;
case HUD_STAT_DIR:
e->dir = event.hudchange.data;
break;
case HUD_STAT_ALIGN:
e->align = *event.hudchange.v2fdata;
break;
case HUD_STAT_OFFSET:
e->offset = *event.hudchange.v2fdata;
break;
case HUD_STAT_WORLD_POS:
e->world_pos = *event.hudchange.v3fdata;
break;
case HUD_STAT_SIZE:
e->size = *event.hudchange.v2s32data;
break;
}
}
delete event.hudchange.v3fdata;
delete event.hudchange.v2fdata;
delete event.hudchange.sdata;
delete event.hudchange.v2s32data;
break;
case CE_SET_SKY:
sky->setVisible(false);
// Whether clouds are visible in front of a custom skybox
sky->setCloudsEnabled(event.set_sky.clouds);
if (skybox) {
skybox->remove();
skybox = NULL;
}
// Handle according to type
if (*event.set_sky.type == "regular") {
sky->setVisible(true);
sky->setCloudsEnabled(true);
} else if (*event.set_sky.type == "skybox" &&
event.set_sky.params->size() == 6) {
sky->setFallbackBgColor(*event.set_sky.bgcolor);
skybox = RenderingEngine::get_scene_manager()->addSkyBoxSceneNode(
texture_src->getTextureForMesh((*event.set_sky.params)[0]),
texture_src->getTextureForMesh((*event.set_sky.params)[1]),
texture_src->getTextureForMesh((*event.set_sky.params)[2]),
texture_src->getTextureForMesh((*event.set_sky.params)[3]),
texture_src->getTextureForMesh((*event.set_sky.params)[4]),
texture_src->getTextureForMesh((*event.set_sky.params)[5]));
}
// Handle everything else as plain color
else {
if (*event.set_sky.type != "plain")
infostream << "Unknown sky type: "
<< (*event.set_sky.type) << std::endl;
sky->setFallbackBgColor(*event.set_sky.bgcolor);
}
delete event.set_sky.bgcolor;
delete event.set_sky.type;
delete event.set_sky.params;
break;
case CE_OVERRIDE_DAY_NIGHT_RATIO:
client->getEnv().setDayNightRatioOverride(
event.override_day_night_ratio.do_override,
event.override_day_night_ratio.ratio_f * 1000);
break;
case CE_CLOUD_PARAMS:
if (clouds) {
clouds->setDensity(event.cloud_params.density);
clouds->setColorBright(video::SColor(event.cloud_params.color_bright));
clouds->setColorAmbient(video::SColor(event.cloud_params.color_ambient));
clouds->setHeight(event.cloud_params.height);
clouds->setThickness(event.cloud_params.thickness);
clouds->setSpeed(v2f(
event.cloud_params.speed_x,
event.cloud_params.speed_y));
}
break;
default:
// unknown or unhandled type
break;
}
if (e != NULL) {
delete event->hudadd.pos;
delete event->hudadd.name;
delete event->hudadd.scale;
delete event->hudadd.text;
delete event->hudadd.align;
delete event->hudadd.offset;
delete event->hudadd.world_pos;
delete event->hudadd.size;
return;
}
e = new HudElement;
e->type = (HudElementType)event->hudadd.type;
e->pos = *event->hudadd.pos;
e->name = *event->hudadd.name;
e->scale = *event->hudadd.scale;
e->text = *event->hudadd.text;
e->number = event->hudadd.number;
e->item = event->hudadd.item;
e->dir = event->hudadd.dir;
e->align = *event->hudadd.align;
e->offset = *event->hudadd.offset;
e->world_pos = *event->hudadd.world_pos;
e->size = *event->hudadd.size;
u32 new_id = player->addHud(e);
//if this isn't true our huds aren't consistent
sanity_check(new_id == id);
delete event->hudadd.pos;
delete event->hudadd.name;
delete event->hudadd.scale;
delete event->hudadd.text;
delete event->hudadd.align;
delete event->hudadd.offset;
delete event->hudadd.world_pos;
delete event->hudadd.size;
}
void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
HudElement *e = player->removeHud(event->hudrm.id);
delete e;
}
void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam)
{
LocalPlayer *player = client->getEnv().getLocalPlayer();
u32 id = event->hudchange.id;
HudElement *e = player->getHud(id);
if (e == NULL) {
delete event->hudchange.v3fdata;
delete event->hudchange.v2fdata;
delete event->hudchange.sdata;
delete event->hudchange.v2s32data;
return;
}
switch (event->hudchange.stat) {
case HUD_STAT_POS:
e->pos = *event->hudchange.v2fdata;
break;
case HUD_STAT_NAME:
e->name = *event->hudchange.sdata;
break;
case HUD_STAT_SCALE:
e->scale = *event->hudchange.v2fdata;
break;
case HUD_STAT_TEXT:
e->text = *event->hudchange.sdata;
break;
case HUD_STAT_NUMBER:
e->number = event->hudchange.data;
break;
case HUD_STAT_ITEM:
e->item = event->hudchange.data;
break;
case HUD_STAT_DIR:
e->dir = event->hudchange.data;
break;
case HUD_STAT_ALIGN:
e->align = *event->hudchange.v2fdata;
break;
case HUD_STAT_OFFSET:
e->offset = *event->hudchange.v2fdata;
break;
case HUD_STAT_WORLD_POS:
e->world_pos = *event->hudchange.v3fdata;
break;
case HUD_STAT_SIZE:
e->size = *event->hudchange.v2s32data;
break;
}
delete event->hudchange.v3fdata;
delete event->hudchange.v2fdata;
delete event->hudchange.sdata;
delete event->hudchange.v2s32data;
}
void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam)
{
sky->setVisible(false);
// Whether clouds are visible in front of a custom skybox
sky->setCloudsEnabled(event->set_sky.clouds);
if (skybox) {
skybox->remove();
skybox = NULL;
}
// Handle according to type
if (*event->set_sky.type == "regular") {
sky->setVisible(true);
sky->setCloudsEnabled(true);
} else if (*event->set_sky.type == "skybox" &&
event->set_sky.params->size() == 6) {
sky->setFallbackBgColor(*event->set_sky.bgcolor);
skybox = RenderingEngine::get_scene_manager()->addSkyBoxSceneNode(
texture_src->getTextureForMesh((*event->set_sky.params)[0]),
texture_src->getTextureForMesh((*event->set_sky.params)[1]),
texture_src->getTextureForMesh((*event->set_sky.params)[2]),
texture_src->getTextureForMesh((*event->set_sky.params)[3]),
texture_src->getTextureForMesh((*event->set_sky.params)[4]),
texture_src->getTextureForMesh((*event->set_sky.params)[5]));
}
// Handle everything else as plain color
else {
if (*event->set_sky.type != "plain")
infostream << "Unknown sky type: "
<< (*event->set_sky.type) << std::endl;
sky->setFallbackBgColor(*event->set_sky.bgcolor);
}
delete event->set_sky.bgcolor;
delete event->set_sky.type;
delete event->set_sky.params;
}
void Game::handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
CameraOrientation *cam)
{
client->getEnv().setDayNightRatioOverride(
event->override_day_night_ratio.do_override,
event->override_day_night_ratio.ratio_f * 1000.0f);
}
void Game::handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam)
{
if (!clouds)
return;
clouds->setDensity(event->cloud_params.density);
clouds->setColorBright(video::SColor(event->cloud_params.color_bright));
clouds->setColorAmbient(video::SColor(event->cloud_params.color_ambient));
clouds->setHeight(event->cloud_params.height);
clouds->setThickness(event->cloud_params.thickness);
clouds->setSpeed(v2f(event->cloud_params.speed_x, event->cloud_params.speed_y));
}
void Game::processClientEvents(CameraOrientation *cam)
{
while (client->hasClientEvents()) {
std::unique_ptr<ClientEvent> event(client->getClientEvent());
FATAL_ERROR_IF(event->type >= CLIENTEVENT_MAX, "Invalid clientevent type");
const ClientEventHandler& evHandler = clientEventHandler[event->type];
(this->*evHandler.handler)(event.get(), cam);
}
}
void Game::updateCamera(u32 busy_time, f32 dtime)
{