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

@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "network/connection.h"
#include "network/networkpacket.h"
#include "threading/mutex_auto_lock.h"
#include "client/clientevent.h"
#include "client/renderingengine.h"
#include "util/auth.h"
#include "util/directiontables.h"
@ -425,9 +426,9 @@ void Client::step(float dtime)
sendDamage(damage);
// Add to ClientEvent queue
ClientEvent event;
event.type = CE_PLAYER_DAMAGE;
event.player_damage.amount = damage;
ClientEvent *event = new ClientEvent();
event->type = CE_PLAYER_DAMAGE;
event->player_damage.amount = damage;
m_client_event_queue.push(event);
}
}
@ -1661,12 +1662,12 @@ void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool ur
}
}
ClientEvent Client::getClientEvent()
ClientEvent *Client::getClientEvent()
{
FATAL_ERROR_IF(m_client_event_queue.empty(),
"Cannot getClientEvent, queue is empty.");
ClientEvent event = m_client_event_queue.front();
ClientEvent *event = m_client_event_queue.front();
m_client_event_queue.pop();
return event;
}
@ -1865,6 +1866,11 @@ bool Client::shouldShowMinimap() const
return !m_minimap_disabled_by_server;
}
void Client::pushToEventQueue(ClientEvent *event)
{
m_client_event_queue.push(event);
}
void Client::showGameChat(const bool show)
{
m_game_ui_flags->show_chat = show;

View File

@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f
struct ClientEvent;
struct MeshMakeData;
struct ChatMessage;
class MapBlockMesh;
@ -68,137 +69,6 @@ enum LocalClientState {
LC_Ready
};
enum ClientEventType
{
CE_NONE,
CE_PLAYER_DAMAGE,
CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN,
CE_SHOW_FORMSPEC,
CE_SHOW_LOCAL_FORMSPEC,
CE_SPAWN_PARTICLE,
CE_ADD_PARTICLESPAWNER,
CE_DELETE_PARTICLESPAWNER,
CE_HUDADD,
CE_HUDRM,
CE_HUDCHANGE,
CE_SET_SKY,
CE_OVERRIDE_DAY_NIGHT_RATIO,
CE_CLOUD_PARAMS,
};
struct ClientEvent
{
ClientEventType type;
union{
//struct{
//} none;
struct{
u8 amount;
} player_damage;
struct{
f32 pitch;
f32 yaw;
} player_force_move;
struct{
bool set_camera_point_target;
f32 camera_point_target_x;
f32 camera_point_target_y;
f32 camera_point_target_z;
} deathscreen;
struct{
std::string *formspec;
std::string *formname;
} show_formspec;
//struct{
//} textures_updated;
struct{
v3f *pos;
v3f *vel;
v3f *acc;
f32 expirationtime;
f32 size;
bool collisiondetection;
bool collision_removal;
bool vertical;
std::string *texture;
struct TileAnimationParams animation;
u8 glow;
} spawn_particle;
struct{
u16 amount;
f32 spawntime;
v3f *minpos;
v3f *maxpos;
v3f *minvel;
v3f *maxvel;
v3f *minacc;
v3f *maxacc;
f32 minexptime;
f32 maxexptime;
f32 minsize;
f32 maxsize;
bool collisiondetection;
bool collision_removal;
u16 attached_id;
bool vertical;
std::string *texture;
u32 id;
struct TileAnimationParams animation;
u8 glow;
} add_particlespawner;
struct{
u32 id;
} delete_particlespawner;
struct{
u32 id;
u8 type;
v2f *pos;
std::string *name;
v2f *scale;
std::string *text;
u32 number;
u32 item;
u32 dir;
v2f *align;
v2f *offset;
v3f *world_pos;
v2s32 * size;
} hudadd;
struct{
u32 id;
} hudrm;
struct{
u32 id;
HudElementStat stat;
v2f *v2fdata;
std::string *sdata;
u32 data;
v3f *v3fdata;
v2s32 * v2s32data;
} hudchange;
struct{
video::SColor *bgcolor;
std::string *type;
std::vector<std::string> *params;
bool clouds;
} set_sky;
struct{
bool do_override;
float ratio_f;
} override_day_night_ratio;
struct {
f32 density;
u32 color_bright;
u32 color_ambient;
f32 height;
f32 thickness;
f32 speed_x;
f32 speed_y;
} cloud_params;
};
};
/*
Packet counter
*/
@ -450,7 +320,7 @@ public:
bool hasClientEvents() const { return !m_client_event_queue.empty(); }
// Get event from queue. If queue is empty, it triggers an assertion failure.
ClientEvent getClientEvent();
ClientEvent * getClientEvent();
bool accessDenied() const { return m_access_denied; }
@ -530,10 +400,7 @@ public:
ClientScripting *getScript() { return m_script; }
const bool moddingEnabled() const { return m_modding_enabled; }
inline void pushToEventQueue(const ClientEvent &event)
{
m_client_event_queue.push(event);
}
void pushToEventQueue(ClientEvent *event);
void showGameChat(bool show = true);
void showGameHud(bool show = true);
@ -662,7 +529,7 @@ private:
bool m_access_denied = false;
bool m_access_denied_reconnect = false;
std::string m_access_denied_reason = "";
std::queue<ClientEvent> m_client_event_queue;
std::queue<ClientEvent *> m_client_event_queue;
bool m_itemdef_received = false;
bool m_nodedef_received = false;
ClientMediaDownloader *m_media_downloader;

170
src/client/clientevent.h Normal file
View File

@ -0,0 +1,170 @@
/*
Minetest
Copyright (C) 2017 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <string>
#include "irrlichttypes_bloated.h"
#include "hud.h"
enum ClientEventType : u8
{
CE_NONE,
CE_PLAYER_DAMAGE,
CE_PLAYER_FORCE_MOVE,
CE_DEATHSCREEN,
CE_SHOW_FORMSPEC,
CE_SHOW_LOCAL_FORMSPEC,
CE_SPAWN_PARTICLE,
CE_ADD_PARTICLESPAWNER,
CE_DELETE_PARTICLESPAWNER,
CE_HUDADD,
CE_HUDRM,
CE_HUDCHANGE,
CE_SET_SKY,
CE_OVERRIDE_DAY_NIGHT_RATIO,
CE_CLOUD_PARAMS,
CLIENTEVENT_MAX,
};
struct ClientEvent
{
ClientEventType type;
union
{
// struct{
//} none;
struct
{
u8 amount;
} player_damage;
struct
{
f32 pitch;
f32 yaw;
} player_force_move;
struct
{
bool set_camera_point_target;
f32 camera_point_target_x;
f32 camera_point_target_y;
f32 camera_point_target_z;
} deathscreen;
struct
{
std::string *formspec;
std::string *formname;
} show_formspec;
// struct{
//} textures_updated;
struct
{
v3f *pos;
v3f *vel;
v3f *acc;
f32 expirationtime;
f32 size;
bool collisiondetection;
bool collision_removal;
bool vertical;
std::string *texture;
struct TileAnimationParams animation;
u8 glow;
} spawn_particle;
struct
{
u16 amount;
f32 spawntime;
v3f *minpos;
v3f *maxpos;
v3f *minvel;
v3f *maxvel;
v3f *minacc;
v3f *maxacc;
f32 minexptime;
f32 maxexptime;
f32 minsize;
f32 maxsize;
bool collisiondetection;
bool collision_removal;
u16 attached_id;
bool vertical;
std::string *texture;
u32 id;
struct TileAnimationParams animation;
u8 glow;
} add_particlespawner;
struct
{
u32 id;
} delete_particlespawner;
struct
{
u32 id;
u8 type;
v2f *pos;
std::string *name;
v2f *scale;
std::string *text;
u32 number;
u32 item;
u32 dir;
v2f *align;
v2f *offset;
v3f *world_pos;
v2s32 *size;
} hudadd;
struct
{
u32 id;
} hudrm;
struct
{
u32 id;
HudElementStat stat;
v2f *v2fdata;
std::string *sdata;
u32 data;
v3f *v3fdata;
v2s32 *v2s32data;
} hudchange;
struct
{
video::SColor *bgcolor;
std::string *type;
std::vector<std::string> *params;
bool clouds;
} set_sky;
struct
{
bool do_override;
float ratio_f;
} override_day_night_ratio;
struct
{
f32 density;
u32 color_bright;
u32 color_ambient;
f32 height;
f32 thickness;
f32 speed_x;
f32 speed_y;
} cloud_params;
};
};

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)
{

View File

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h"
#include "server.h"
#include "util/strfnd.h"
#include "client/clientevent.h"
#include "network/clientopcodes.h"
#include "network/connection.h"
#include "script/scripting_client.h"
@ -577,9 +578,9 @@ void Client::handleCommand_HP(NetworkPacket* pkt)
if (hp < oldhp) {
// Add to ClientEvent queue
ClientEvent event;
event.type = CE_PLAYER_DAMAGE;
event.player_damage.amount = oldhp - hp;
ClientEvent *event = new ClientEvent();
event->type = CE_PLAYER_DAMAGE;
event->player_damage.amount = oldhp - hp;
m_client_event_queue.push(event);
}
}
@ -620,10 +621,10 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
it would just force the pitch and yaw values to whatever
the camera points to.
*/
ClientEvent event;
event.type = CE_PLAYER_FORCE_MOVE;
event.player_force_move.pitch = pitch;
event.player_force_move.yaw = yaw;
ClientEvent *event = new ClientEvent();
event->type = CE_PLAYER_FORCE_MOVE;
event->player_force_move.pitch = pitch;
event->player_force_move.yaw = yaw;
m_client_event_queue.push(event);
// Ignore damage for a few seconds, so that the player doesn't
@ -639,12 +640,12 @@ void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
*pkt >> set_camera_point_target;
*pkt >> camera_point_target;
ClientEvent event;
event.type = CE_DEATHSCREEN;
event.deathscreen.set_camera_point_target = set_camera_point_target;
event.deathscreen.camera_point_target_x = camera_point_target.X;
event.deathscreen.camera_point_target_y = camera_point_target.Y;
event.deathscreen.camera_point_target_z = camera_point_target.Z;
ClientEvent *event = new ClientEvent();
event->type = CE_DEATHSCREEN;
event->deathscreen.set_camera_point_target = set_camera_point_target;
event->deathscreen.camera_point_target_x = camera_point_target.X;
event->deathscreen.camera_point_target_y = camera_point_target.Y;
event->deathscreen.camera_point_target_z = camera_point_target.Z;
m_client_event_queue.push(event);
}
@ -942,12 +943,12 @@ void Client::handleCommand_ShowFormSpec(NetworkPacket* pkt)
*pkt >> formname;
ClientEvent event;
event.type = CE_SHOW_FORMSPEC;
ClientEvent *event = new ClientEvent();
event->type = CE_SHOW_FORMSPEC;
// pointer is required as event is a struct only!
// adding a std:string to a struct isn't possible
event.show_formspec.formspec = new std::string(formspec);
event.show_formspec.formname = new std::string(formname);
event->show_formspec.formspec = new std::string(formspec);
event->show_formspec.formname = new std::string(formname);
m_client_event_queue.push(event);
}
@ -975,19 +976,19 @@ void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
glow = readU8(is);
} catch (...) {}
ClientEvent event;
event.type = CE_SPAWN_PARTICLE;
event.spawn_particle.pos = new v3f (pos);
event.spawn_particle.vel = new v3f (vel);
event.spawn_particle.acc = new v3f (acc);
event.spawn_particle.expirationtime = expirationtime;
event.spawn_particle.size = size;
event.spawn_particle.collisiondetection = collisiondetection;
event.spawn_particle.collision_removal = collision_removal;
event.spawn_particle.vertical = vertical;
event.spawn_particle.texture = new std::string(texture);
event.spawn_particle.animation = animation;
event.spawn_particle.glow = glow;
ClientEvent *event = new ClientEvent();
event->type = CE_SPAWN_PARTICLE;
event->spawn_particle.pos = new v3f (pos);
event->spawn_particle.vel = new v3f (vel);
event->spawn_particle.acc = new v3f (acc);
event->spawn_particle.expirationtime = expirationtime;
event->spawn_particle.size = size;
event->spawn_particle.collisiondetection = collisiondetection;
event->spawn_particle.collision_removal = collision_removal;
event->spawn_particle.vertical = vertical;
event->spawn_particle.texture = new std::string(texture);
event->spawn_particle.animation = animation;
event->spawn_particle.glow = glow;
m_client_event_queue.push(event);
}
@ -1035,28 +1036,28 @@ void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
glow = readU8(is);
} catch (...) {}
ClientEvent event;
event.type = CE_ADD_PARTICLESPAWNER;
event.add_particlespawner.amount = amount;
event.add_particlespawner.spawntime = spawntime;
event.add_particlespawner.minpos = new v3f (minpos);
event.add_particlespawner.maxpos = new v3f (maxpos);
event.add_particlespawner.minvel = new v3f (minvel);
event.add_particlespawner.maxvel = new v3f (maxvel);
event.add_particlespawner.minacc = new v3f (minacc);
event.add_particlespawner.maxacc = new v3f (maxacc);
event.add_particlespawner.minexptime = minexptime;
event.add_particlespawner.maxexptime = maxexptime;
event.add_particlespawner.minsize = minsize;
event.add_particlespawner.maxsize = maxsize;
event.add_particlespawner.collisiondetection = collisiondetection;
event.add_particlespawner.collision_removal = collision_removal;
event.add_particlespawner.attached_id = attached_id;
event.add_particlespawner.vertical = vertical;
event.add_particlespawner.texture = new std::string(texture);
event.add_particlespawner.id = id;
event.add_particlespawner.animation = animation;
event.add_particlespawner.glow = glow;
ClientEvent *event = new ClientEvent();
event->type = CE_ADD_PARTICLESPAWNER;
event->add_particlespawner.amount = amount;
event->add_particlespawner.spawntime = spawntime;
event->add_particlespawner.minpos = new v3f (minpos);
event->add_particlespawner.maxpos = new v3f (maxpos);
event->add_particlespawner.minvel = new v3f (minvel);
event->add_particlespawner.maxvel = new v3f (maxvel);
event->add_particlespawner.minacc = new v3f (minacc);
event->add_particlespawner.maxacc = new v3f (maxacc);
event->add_particlespawner.minexptime = minexptime;
event->add_particlespawner.maxexptime = maxexptime;
event->add_particlespawner.minsize = minsize;
event->add_particlespawner.maxsize = maxsize;
event->add_particlespawner.collisiondetection = collisiondetection;
event->add_particlespawner.collision_removal = collision_removal;
event->add_particlespawner.attached_id = attached_id;
event->add_particlespawner.vertical = vertical;
event->add_particlespawner.texture = new std::string(texture);
event->add_particlespawner.id = id;
event->add_particlespawner.animation = animation;
event->add_particlespawner.glow = glow;
m_client_event_queue.push(event);
}
@ -1076,10 +1077,11 @@ void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt)
}
ClientEvent event;
event.type = CE_DELETE_PARTICLESPAWNER;
event.delete_particlespawner.id =
(pkt->getCommand() == TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY ? (u32) legacy_id : id);
ClientEvent *event = new ClientEvent();
event->type = CE_DELETE_PARTICLESPAWNER;
event->delete_particlespawner.id =
(pkt->getCommand() == TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY ?
(u32) legacy_id : id);
m_client_event_queue.push(event);
}
@ -1114,21 +1116,21 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
*pkt >> size;
} catch(SerializationError &e) {};
ClientEvent event;
event.type = CE_HUDADD;
event.hudadd.id = id;
event.hudadd.type = type;
event.hudadd.pos = new v2f(pos);
event.hudadd.name = new std::string(name);
event.hudadd.scale = new v2f(scale);
event.hudadd.text = new std::string(text);
event.hudadd.number = number;
event.hudadd.item = item;
event.hudadd.dir = dir;
event.hudadd.align = new v2f(align);
event.hudadd.offset = new v2f(offset);
event.hudadd.world_pos = new v3f(world_pos);
event.hudadd.size = new v2s32(size);
ClientEvent *event = new ClientEvent();
event->type = CE_HUDADD;
event->hudadd.id = id;
event->hudadd.type = type;
event->hudadd.pos = new v2f(pos);
event->hudadd.name = new std::string(name);
event->hudadd.scale = new v2f(scale);
event->hudadd.text = new std::string(text);
event->hudadd.number = number;
event->hudadd.item = item;
event->hudadd.dir = dir;
event->hudadd.align = new v2f(align);
event->hudadd.offset = new v2f(offset);
event->hudadd.world_pos = new v3f(world_pos);
event->hudadd.size = new v2s32(size);
m_client_event_queue.push(event);
}
@ -1138,9 +1140,9 @@ void Client::handleCommand_HudRemove(NetworkPacket* pkt)
*pkt >> id;
ClientEvent event;
event.type = CE_HUDRM;
event.hudrm.id = id;
ClientEvent *event = new ClientEvent();
event->type = CE_HUDRM;
event->hudrm.id = id;
m_client_event_queue.push(event);
}
@ -1168,15 +1170,15 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
else
*pkt >> intdata;
ClientEvent event;
event.type = CE_HUDCHANGE;
event.hudchange.id = id;
event.hudchange.stat = (HudElementStat)stat;
event.hudchange.v2fdata = new v2f(v2fdata);
event.hudchange.v3fdata = new v3f(v3fdata);
event.hudchange.sdata = new std::string(sdata);
event.hudchange.data = intdata;
event.hudchange.v2s32data = new v2s32(v2s32data);
ClientEvent *event = new ClientEvent();
event->type = CE_HUDCHANGE;
event->hudchange.id = id;
event->hudchange.stat = (HudElementStat)stat;
event->hudchange.v2fdata = new v2f(v2fdata);
event->hudchange.v3fdata = new v3f(v3fdata);
event->hudchange.sdata = new std::string(sdata);
event->hudchange.data = intdata;
event->hudchange.v2s32data = new v2s32(v2s32data);
m_client_event_queue.push(event);
}
@ -1261,12 +1263,12 @@ void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
clouds = readU8(is);
} catch (...) {}
ClientEvent event;
event.type = CE_SET_SKY;
event.set_sky.bgcolor = bgcolor;
event.set_sky.type = type;
event.set_sky.params = params;
event.set_sky.clouds = clouds;
ClientEvent *event = new ClientEvent();
event->type = CE_SET_SKY;
event->set_sky.bgcolor = bgcolor;
event->set_sky.type = type;
event->set_sky.params = params;
event->set_sky.clouds = clouds;
m_client_event_queue.push(event);
}
@ -1282,19 +1284,19 @@ void Client::handleCommand_CloudParams(NetworkPacket* pkt)
*pkt >> density >> color_bright >> color_ambient
>> height >> thickness >> speed;
ClientEvent event;
event.type = CE_CLOUD_PARAMS;
event.cloud_params.density = density;
ClientEvent *event = new ClientEvent();
event->type = CE_CLOUD_PARAMS;
event->cloud_params.density = density;
// use the underlying u32 representation, because we can't
// use struct members with constructors here, and this way
// we avoid using new() and delete() for no good reason
event.cloud_params.color_bright = color_bright.color;
event.cloud_params.color_ambient = color_ambient.color;
event.cloud_params.height = height;
event.cloud_params.thickness = thickness;
event->cloud_params.color_bright = color_bright.color;
event->cloud_params.color_ambient = color_ambient.color;
event->cloud_params.height = height;
event->cloud_params.thickness = thickness;
// same here: deconstruct to skip constructor
event.cloud_params.speed_x = speed.X;
event.cloud_params.speed_y = speed.Y;
event->cloud_params.speed_x = speed.X;
event->cloud_params.speed_y = speed.Y;
m_client_event_queue.push(event);
}
@ -1307,10 +1309,10 @@ void Client::handleCommand_OverrideDayNightRatio(NetworkPacket* pkt)
float day_night_ratio_f = (float)day_night_ratio_u / 65536;
ClientEvent event;
event.type = CE_OVERRIDE_DAY_NIGHT_RATIO;
event.override_day_night_ratio.do_override = do_override;
event.override_day_night_ratio.ratio_f = day_night_ratio_f;
ClientEvent *event = new ClientEvent();
event->type = CE_OVERRIDE_DAY_NIGHT_RATIO;
event->override_day_night_ratio.do_override = do_override;
event->override_day_night_ratio.ratio_f = day_night_ratio_f;
m_client_event_queue.push(event);
}

View File

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "particles.h"
#include "client.h"
#include "collision.h"
#include "client/clientevent.h"
#include "client/renderingengine.h"
#include "util/numeric.h"
#include "light.h"

View File

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "l_client.h"
#include "chatmessage.h"
#include "client.h"
#include "client/clientevent.h"
#include "clientenvironment.h"
#include "common/c_content.h"
#include "common/c_converter.h"
@ -129,10 +130,10 @@ int ModApiClient::l_show_formspec(lua_State *L)
if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
return 0;
ClientEvent event;
event.type = CE_SHOW_LOCAL_FORMSPEC;
event.show_formspec.formname = new std::string(luaL_checkstring(L, 1));
event.show_formspec.formspec = new std::string(luaL_checkstring(L, 2));
ClientEvent *event = new ClientEvent();
event->type = CE_SHOW_LOCAL_FORMSPEC;
event->show_formspec.formname = new std::string(luaL_checkstring(L, 1));
event->show_formspec.formspec = new std::string(luaL_checkstring(L, 2));
getClient(L)->pushToEventQueue(event);
lua_pushboolean(L, true);
return 1;