diff options
Diffstat (limited to 'src/game.cpp')
-rw-r--r-- | src/game.cpp | 496 |
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(¤t_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(¤t_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(¤t_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(¤t_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) { |