summaryrefslogtreecommitdiff
path: root/src/game.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game.cpp')
-rw-r--r--src/game.cpp496
1 files changed, 276 insertions, 220 deletions
diff --git a/src/game.cpp b/src/game.cpp
index 43495e8a6..17ab68e7c 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -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)
{
- LocalPlayer *player = client->getEnv().getLocalPlayer();
-
- while (client->hasClientEvents()) {
- ClientEvent event = client->getClientEvent();
-
- switch (event.type) {
- case CE_PLAYER_DAMAGE:
- if (client->getHP() == 0)
- break;
- 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);
+ FATAL_ERROR("ClientEvent type None received");
+}
- player->hurt_tilt_timer = 1.5;
- player->hurt_tilt_strength =
- rangelim(event.player_damage.amount / 4, 1.0, 4.0);
+void Game::handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam)
+{
+ if (client->getHP() == 0)
+ return;
- client->event()->put(new SimpleTriggerEvent("PlayerDamage"));
- break;
+ if (client->moddingEnabled()) {
+ client->getScript()->on_damage_taken(event->player_damage.amount);
+ }
- case CE_PLAYER_FORCE_MOVE:
- cam->camera_yaw = event.player_force_move.yaw;
- cam->camera_pitch = event.player_force_move.pitch;
- break;
+ runData.damage_flash += 95.0 + 3.2 * event->player_damage.amount;
+ runData.damage_flash = MYMIN(runData.damage_flash, 127.0);
- case CE_DEATHSCREEN:
- // 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;
- break;
+ player->hurt_tilt_timer = 1.5;
+ player->hurt_tilt_strength =
+ rangelim(event->player_damage.amount / 4, 1.0, 4.0);
- 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;
+ client->event()->put(new SimpleTriggerEvent("PlayerDamage"));
+}
- 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;
+void Game::handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam)
+{
+ cam->camera_yaw = event->player_force_move.yaw;
+ cam->camera_pitch = event->player_force_move.pitch;
+}
- case CE_SPAWN_PARTICLE:
- case CE_ADD_PARTICLESPAWNER:
- case CE_DELETE_PARTICLESPAWNER:
- client->getParticleManager()->handleParticleEvent(&event, client, player);
- break;
+void Game::handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam)
+{
+ // This should be enabled for death formspec in builtin
+ client->getScript()->on_death();
- 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;
- }
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
- 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);
- }
+ /* Handle visualization */
+ runData.damage_flash = 0;
+ player->hurt_tilt_timer = 0;
+ player->hurt_tilt_strength = 0;
+}
- 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;
+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));
- case CE_HUDRM:
- {
- HudElement *e = player->removeHud(event.hudrm.id);
+ create_formspec_menu(&current_formspec, client, &input->joystick,
+ fs_src, txt_dst);
+ cur_formname = *(event->show_formspec.formname);
+ }
- delete e;
- }
- break;
+ delete event->show_formspec.formspec;
+ delete event->show_formspec.formname;
+}
- case CE_HUDCHANGE:
- {
- u32 id = event.hudchange.id;
- HudElement *e = player->getHud(id);
+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);
- if (e == NULL) {
- delete event.hudchange.v3fdata;
- delete event.hudchange.v2fdata;
- delete event.hudchange.sdata;
- delete event.hudchange.v2s32data;
- continue;
- }
+ delete event->show_formspec.formspec;
+ delete event->show_formspec.formname;
+}
- switch (event.hudchange.stat) {
- case HUD_STAT_POS:
- e->pos = *event.hudchange.v2fdata;
- break;
+void Game::handleClientEvent_HandleParticleEvent(ClientEvent *event,
+ CameraOrientation *cam)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ client->getParticleManager()->handleParticleEvent(event, client, player);
+}
- case HUD_STAT_NAME:
- e->name = *event.hudchange.sdata;
- break;
+void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
- case HUD_STAT_SCALE:
- e->scale = *event.hudchange.v2fdata;
- break;
+ u32 id = event->hudadd.id;
- case HUD_STAT_TEXT:
- e->text = *event.hudchange.sdata;
- break;
+ HudElement *e = player->getHud(id);
- case HUD_STAT_NUMBER:
- e->number = event.hudchange.data;
- 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;
+ }
- case HUD_STAT_ITEM:
- e->item = event.hudchange.data;
- break;
+ 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;
+}
- case HUD_STAT_DIR:
- e->dir = event.hudchange.data;
- break;
+void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+ HudElement *e = player->removeHud(event->hudrm.id);
+ delete e;
+}
- case HUD_STAT_ALIGN:
- e->align = *event.hudchange.v2fdata;
- break;
+void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
- case HUD_STAT_OFFSET:
- e->offset = *event.hudchange.v2fdata;
- break;
+ u32 id = event->hudchange.id;
+ HudElement *e = player->getHud(id);
- case HUD_STAT_WORLD_POS:
- e->world_pos = *event.hudchange.v3fdata;
- break;
+ if (e == NULL) {
+ delete event->hudchange.v3fdata;
+ delete event->hudchange.v2fdata;
+ delete event->hudchange.sdata;
+ delete event->hudchange.v2s32data;
+ return;
+ }
- case HUD_STAT_SIZE:
- e->size = *event.hudchange.v2s32data;
- break;
- }
- }
+ switch (event->hudchange.stat) {
+ case HUD_STAT_POS:
+ e->pos = *event->hudchange.v2fdata;
+ break;
- delete event.hudchange.v3fdata;
- delete event.hudchange.v2fdata;
- delete event.hudchange.sdata;
- delete event.hudchange.v2s32data;
+ case HUD_STAT_NAME:
+ e->name = *event->hudchange.sdata;
break;
- case CE_SET_SKY:
- sky->setVisible(false);
- // Whether clouds are visible in front of a custom skybox
- sky->setCloudsEnabled(event.set_sky.clouds);
+ case HUD_STAT_SCALE:
+ e->scale = *event->hudchange.v2fdata;
+ break;
- if (skybox) {
- skybox->remove();
- skybox = NULL;
- }
+ case HUD_STAT_TEXT:
+ e->text = *event->hudchange.sdata;
+ break;
- // 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;
+ case HUD_STAT_NUMBER:
+ e->number = event->hudchange.data;
+ break;
- sky->setFallbackBgColor(*event.set_sky.bgcolor);
- }
+ case HUD_STAT_ITEM:
+ e->item = event->hudchange.data;
+ break;
- delete event.set_sky.bgcolor;
- delete event.set_sky.type;
- delete event.set_sky.params;
+ case HUD_STAT_DIR:
+ e->dir = event->hudchange.data;
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);
+ case HUD_STAT_ALIGN:
+ e->align = *event->hudchange.v2fdata;
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));
- }
+ case HUD_STAT_OFFSET:
+ e->offset = *event->hudchange.v2fdata;
break;
- default:
- // unknown or unhandled type
+ 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)
{