1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214 |
- /*
- Minetest-c55
- Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
- 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.
- */
- #include "game.h"
- #include "irrlichttypes_extrabloated.h"
- #include <IGUICheckBox.h>
- #include <IGUIEditBox.h>
- #include <IGUIButton.h>
- #include <IGUIStaticText.h>
- #include <IGUIFont.h>
- #include <IMaterialRendererServices.h>
- #include "client.h"
- #include "server.h"
- #include "guiPauseMenu.h"
- #include "guiPasswordChange.h"
- #include "guiFormSpecMenu.h"
- #include "guiTextInputMenu.h"
- #include "guiDeathScreen.h"
- #include "tool.h"
- #include "guiChatConsole.h"
- #include "config.h"
- #include "clouds.h"
- #include "camera.h"
- #include "farmesh.h"
- #include "mapblock.h"
- #include "settings.h"
- #include "profiler.h"
- #include "mainmenumanager.h"
- #include "gettext.h"
- #include "log.h"
- #include "filesys.h"
- // Needed for determining pointing to nodes
- #include "nodedef.h"
- #include "nodemetadata.h"
- #include "main.h" // For g_settings
- #include "itemdef.h"
- #include "tile.h" // For TextureSource
- #include "shader.h" // For ShaderSource
- #include "logoutputbuffer.h"
- #include "subgame.h"
- #include "quicktune_shortcutter.h"
- #include "clientmap.h"
- #include "sky.h"
- #include "sound.h"
- #if USE_SOUND
- #include "sound_openal.h"
- #endif
- #include "event_manager.h"
- #include <list>
- #include "util/directiontables.h"
- /*
- Text input system
- */
- struct TextDestChat : public TextDest
- {
- TextDestChat(Client *client)
- {
- m_client = client;
- }
- void gotText(std::wstring text)
- {
- m_client->typeChatMessage(text);
- }
- void gotText(std::map<std::string, std::string> fields)
- {
- m_client->typeChatMessage(narrow_to_wide(fields["text"]));
- }
- Client *m_client;
- };
- struct TextDestNodeMetadata : public TextDest
- {
- TextDestNodeMetadata(v3s16 p, Client *client)
- {
- m_p = p;
- m_client = client;
- }
- // This is deprecated I guess? -celeron55
- void gotText(std::wstring text)
- {
- std::string ntext = wide_to_narrow(text);
- infostream<<"Submitting 'text' field of node at ("<<m_p.X<<","
- <<m_p.Y<<","<<m_p.Z<<"): "<<ntext<<std::endl;
- std::map<std::string, std::string> fields;
- fields["text"] = ntext;
- m_client->sendNodemetaFields(m_p, "", fields);
- }
- void gotText(std::map<std::string, std::string> fields)
- {
- m_client->sendNodemetaFields(m_p, "", fields);
- }
- v3s16 m_p;
- Client *m_client;
- };
- struct TextDestPlayerInventory : public TextDest
- {
- TextDestPlayerInventory(Client *client)
- {
- m_client = client;
- }
- void gotText(std::map<std::string, std::string> fields)
- {
- m_client->sendInventoryFields("", fields);
- }
- Client *m_client;
- };
- /* Respawn menu callback */
- class MainRespawnInitiator: public IRespawnInitiator
- {
- public:
- MainRespawnInitiator(bool *active, Client *client):
- m_active(active), m_client(client)
- {
- *m_active = true;
- }
- void respawn()
- {
- *m_active = false;
- m_client->sendRespawn();
- }
- private:
- bool *m_active;
- Client *m_client;
- };
- /* Form update callback */
- class NodeMetadataFormSource: public IFormSource
- {
- public:
- NodeMetadataFormSource(ClientMap *map, v3s16 p):
- m_map(map),
- m_p(p)
- {
- }
- std::string getForm()
- {
- NodeMetadata *meta = m_map->getNodeMetadata(m_p);
- if(!meta)
- return "";
- return meta->getString("formspec");
- }
- std::string resolveText(std::string str)
- {
- NodeMetadata *meta = m_map->getNodeMetadata(m_p);
- if(!meta)
- return str;
- return meta->resolveString(str);
- }
- ClientMap *m_map;
- v3s16 m_p;
- };
- class PlayerInventoryFormSource: public IFormSource
- {
- public:
- PlayerInventoryFormSource(Client *client):
- m_client(client)
- {
- }
- std::string getForm()
- {
- LocalPlayer* player = m_client->getEnv().getLocalPlayer();
- return player->inventory_formspec;
- }
- Client *m_client;
- };
- class FormspecFormSource: public IFormSource
- {
- public:
- FormspecFormSource(std::string formspec,FormspecFormSource** game_formspec)
- {
- m_formspec = formspec;
- m_game_formspec = game_formspec;
- }
- ~FormspecFormSource()
- {
- *m_game_formspec = 0;
- }
- void setForm(std::string formspec) {
- m_formspec = formspec;
- }
- std::string getForm()
- {
- return m_formspec;
- }
- std::string m_formspec;
- FormspecFormSource** m_game_formspec;
- };
- /*
- Hotbar draw routine
- */
- void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
- IGameDef *gamedef,
- v2s32 centerlowerpos, s32 imgsize, s32 itemcount,
- Inventory *inventory, s32 halfheartcount, u16 playeritem)
- {
- InventoryList *mainlist = inventory->getList("main");
- if(mainlist == NULL)
- {
- errorstream<<"draw_hotbar(): mainlist == NULL"<<std::endl;
- return;
- }
-
- s32 padding = imgsize/12;
- //s32 height = imgsize + padding*2;
- s32 width = itemcount*(imgsize+padding*2);
-
- // Position of upper left corner of bar
- v2s32 pos = centerlowerpos - v2s32(width/2, imgsize+padding*2);
-
- // Draw background color
- /*core::rect<s32> barrect(0,0,width,height);
- barrect += pos;
- video::SColor bgcolor(255,128,128,128);
- driver->draw2DRectangle(bgcolor, barrect, NULL);*/
- core::rect<s32> imgrect(0,0,imgsize,imgsize);
- for(s32 i=0; i<itemcount; i++)
- {
- const ItemStack &item = mainlist->getItem(i);
-
- core::rect<s32> rect = imgrect + pos
- + v2s32(padding+i*(imgsize+padding*2), padding);
-
- if(playeritem == i)
- {
- video::SColor c_outside(255,255,0,0);
- //video::SColor c_outside(255,0,0,0);
- //video::SColor c_inside(255,192,192,192);
- s32 x1 = rect.UpperLeftCorner.X;
- s32 y1 = rect.UpperLeftCorner.Y;
- s32 x2 = rect.LowerRightCorner.X;
- s32 y2 = rect.LowerRightCorner.Y;
- // Black base borders
- driver->draw2DRectangle(c_outside,
- core::rect<s32>(
- v2s32(x1 - padding, y1 - padding),
- v2s32(x2 + padding, y1)
- ), NULL);
- driver->draw2DRectangle(c_outside,
- core::rect<s32>(
- v2s32(x1 - padding, y2),
- v2s32(x2 + padding, y2 + padding)
- ), NULL);
- driver->draw2DRectangle(c_outside,
- core::rect<s32>(
- v2s32(x1 - padding, y1),
- v2s32(x1, y2)
- ), NULL);
- driver->draw2DRectangle(c_outside,
- core::rect<s32>(
- v2s32(x2, y1),
- v2s32(x2 + padding, y2)
- ), NULL);
- /*// Light inside borders
- driver->draw2DRectangle(c_inside,
- core::rect<s32>(
- v2s32(x1 - padding/2, y1 - padding/2),
- v2s32(x2 + padding/2, y1)
- ), NULL);
- driver->draw2DRectangle(c_inside,
- core::rect<s32>(
- v2s32(x1 - padding/2, y2),
- v2s32(x2 + padding/2, y2 + padding/2)
- ), NULL);
- driver->draw2DRectangle(c_inside,
- core::rect<s32>(
- v2s32(x1 - padding/2, y1),
- v2s32(x1, y2)
- ), NULL);
- driver->draw2DRectangle(c_inside,
- core::rect<s32>(
- v2s32(x2, y1),
- v2s32(x2 + padding/2, y2)
- ), NULL);
- */
- }
- video::SColor bgcolor2(128,0,0,0);
- driver->draw2DRectangle(bgcolor2, rect, NULL);
- drawItemStack(driver, font, item, rect, NULL, gamedef);
- }
-
- /*
- Draw hearts
- */
- video::ITexture *heart_texture =
- gamedef->getTextureSource()->getTextureRaw("heart.png");
- if(heart_texture)
- {
- v2s32 p = pos + v2s32(0, -20);
- for(s32 i=0; i<halfheartcount/2; i++)
- {
- const video::SColor color(255,255,255,255);
- const video::SColor colors[] = {color,color,color,color};
- core::rect<s32> rect(0,0,16,16);
- rect += p;
- driver->draw2DImage(heart_texture, rect,
- core::rect<s32>(core::position2d<s32>(0,0),
- core::dimension2di(heart_texture->getOriginalSize())),
- NULL, colors, true);
- p += v2s32(16,0);
- }
- if(halfheartcount % 2 == 1)
- {
- const video::SColor color(255,255,255,255);
- const video::SColor colors[] = {color,color,color,color};
- core::rect<s32> rect(0,0,16/2,16);
- rect += p;
- core::dimension2di srcd(heart_texture->getOriginalSize());
- srcd.Width /= 2;
- driver->draw2DImage(heart_texture, rect,
- core::rect<s32>(core::position2d<s32>(0,0), srcd),
- NULL, colors, true);
- p += v2s32(16,0);
- }
- }
- }
- /*
- Check if a node is pointable
- */
- inline bool isPointableNode(const MapNode& n,
- Client *client, bool liquids_pointable)
- {
- const ContentFeatures &features = client->getNodeDefManager()->get(n);
- return features.pointable ||
- (liquids_pointable && features.isLiquid());
- }
- /*
- Find what the player is pointing at
- */
- PointedThing getPointedThing(Client *client, v3f player_position,
- v3f camera_direction, v3f camera_position,
- core::line3d<f32> shootline, f32 d,
- bool liquids_pointable,
- bool look_for_object,
- std::vector<aabb3f> &hilightboxes,
- ClientActiveObject *&selected_object)
- {
- PointedThing result;
- hilightboxes.clear();
- selected_object = NULL;
- INodeDefManager *nodedef = client->getNodeDefManager();
- ClientMap &map = client->getEnv().getClientMap();
- // First try to find a pointed at active object
- if(look_for_object)
- {
- selected_object = client->getSelectedActiveObject(d*BS,
- camera_position, shootline);
- if(selected_object != NULL)
- {
- if(selected_object->doShowSelectionBox())
- {
- aabb3f *selection_box = selected_object->getSelectionBox();
- // Box should exist because object was
- // returned in the first place
- assert(selection_box);
- v3f pos = selected_object->getPosition();
- hilightboxes.push_back(aabb3f(
- selection_box->MinEdge + pos,
- selection_box->MaxEdge + pos));
- }
- result.type = POINTEDTHING_OBJECT;
- result.object_id = selected_object->getId();
- return result;
- }
- }
- // That didn't work, try to find a pointed at node
- f32 mindistance = BS * 1001;
-
- v3s16 pos_i = floatToInt(player_position, BS);
- /*infostream<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
- <<std::endl;*/
- s16 a = d;
- s16 ystart = pos_i.Y + 0 - (camera_direction.Y<0 ? a : 1);
- s16 zstart = pos_i.Z - (camera_direction.Z<0 ? a : 1);
- s16 xstart = pos_i.X - (camera_direction.X<0 ? a : 1);
- s16 yend = pos_i.Y + 1 + (camera_direction.Y>0 ? a : 1);
- s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1);
- s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1);
-
- // Prevent signed number overflow
- if(yend==32767)
- yend=32766;
- if(zend==32767)
- zend=32766;
- if(xend==32767)
- xend=32766;
- for(s16 y = ystart; y <= yend; y++)
- for(s16 z = zstart; z <= zend; z++)
- for(s16 x = xstart; x <= xend; x++)
- {
- MapNode n;
- try
- {
- n = map.getNode(v3s16(x,y,z));
- }
- catch(InvalidPositionException &e)
- {
- continue;
- }
- if(!isPointableNode(n, client, liquids_pointable))
- continue;
- std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
- v3s16 np(x,y,z);
- v3f npf = intToFloat(np, BS);
- for(std::vector<aabb3f>::const_iterator
- i = boxes.begin();
- i != boxes.end(); i++)
- {
- aabb3f box = *i;
- box.MinEdge += npf;
- box.MaxEdge += npf;
- for(u16 j=0; j<6; j++)
- {
- v3s16 facedir = g_6dirs[j];
- aabb3f facebox = box;
- f32 d = 0.001*BS;
- if(facedir.X > 0)
- facebox.MinEdge.X = facebox.MaxEdge.X-d;
- else if(facedir.X < 0)
- facebox.MaxEdge.X = facebox.MinEdge.X+d;
- else if(facedir.Y > 0)
- facebox.MinEdge.Y = facebox.MaxEdge.Y-d;
- else if(facedir.Y < 0)
- facebox.MaxEdge.Y = facebox.MinEdge.Y+d;
- else if(facedir.Z > 0)
- facebox.MinEdge.Z = facebox.MaxEdge.Z-d;
- else if(facedir.Z < 0)
- facebox.MaxEdge.Z = facebox.MinEdge.Z+d;
- v3f centerpoint = facebox.getCenter();
- f32 distance = (centerpoint - camera_position).getLength();
- if(distance >= mindistance)
- continue;
- if(!facebox.intersectsWithLine(shootline))
- continue;
- v3s16 np_above = np + facedir;
- result.type = POINTEDTHING_NODE;
- result.node_undersurface = np;
- result.node_abovesurface = np_above;
- mindistance = distance;
- hilightboxes.clear();
- for(std::vector<aabb3f>::const_iterator
- i2 = boxes.begin();
- i2 != boxes.end(); i2++)
- {
- aabb3f box = *i2;
- box.MinEdge += npf + v3f(-d,-d,-d);
- box.MaxEdge += npf + v3f(d,d,d);
- hilightboxes.push_back(box);
- }
- }
- }
- } // for coords
- return result;
- }
- /*
- Draws a screen with a single text on it.
- Text will be removed when the screen is drawn the next time.
- */
- /*gui::IGUIStaticText **/
- void draw_load_screen(const std::wstring &text,
- video::IVideoDriver* driver, gui::IGUIFont* font)
- {
- v2u32 screensize = driver->getScreenSize();
- const wchar_t *loadingtext = text.c_str();
- core::vector2d<u32> textsize_u = font->getDimension(loadingtext);
- core::vector2d<s32> textsize(textsize_u.X,textsize_u.Y);
- core::vector2d<s32> center(screensize.X/2, screensize.Y/2);
- core::rect<s32> textrect(center - textsize/2, center + textsize/2);
- gui::IGUIStaticText *guitext = guienv->addStaticText(
- loadingtext, textrect, false, false);
- guitext->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
- driver->beginScene(true, true, video::SColor(255,0,0,0));
- guienv->drawAll();
- driver->endScene();
-
- guitext->remove();
-
- //return guitext;
- }
- /* Profiler display */
- void update_profiler_gui(gui::IGUIStaticText *guitext_profiler,
- gui::IGUIFont *font, u32 text_height,
- u32 show_profiler, u32 show_profiler_max)
- {
- if(show_profiler == 0)
- {
- guitext_profiler->setVisible(false);
- }
- else
- {
- std::ostringstream os(std::ios_base::binary);
- g_profiler->printPage(os, show_profiler, show_profiler_max);
- std::wstring text = narrow_to_wide(os.str());
- guitext_profiler->setText(text.c_str());
- guitext_profiler->setVisible(true);
- s32 w = font->getDimension(text.c_str()).Width;
- if(w < 400)
- w = 400;
- core::rect<s32> rect(6, 4+(text_height+5)*2, 12+w,
- 8+(text_height+5)*2 +
- font->getDimension(text.c_str()).Height);
- guitext_profiler->setRelativePosition(rect);
- guitext_profiler->setVisible(true);
- }
- }
- class ProfilerGraph
- {
- private:
- struct Piece{
- Profiler::GraphValues values;
- };
- struct Meta{
- float min;
- float max;
- video::SColor color;
- Meta(float initial=0, video::SColor color=
- video::SColor(255,255,255,255)):
- min(initial),
- max(initial),
- color(color)
- {}
- };
- std::list<Piece> m_log;
- public:
- u32 m_log_max_size;
- ProfilerGraph():
- m_log_max_size(200)
- {}
- void put(const Profiler::GraphValues &values)
- {
- Piece piece;
- piece.values = values;
- m_log.push_back(piece);
- while(m_log.size() > m_log_max_size)
- m_log.erase(m_log.begin());
- }
-
- void draw(s32 x_left, s32 y_bottom, video::IVideoDriver *driver,
- gui::IGUIFont* font) const
- {
- std::map<std::string, Meta> m_meta;
- for(std::list<Piece>::const_iterator k = m_log.begin();
- k != m_log.end(); k++)
- {
- const Piece &piece = *k;
- for(Profiler::GraphValues::const_iterator i = piece.values.begin();
- i != piece.values.end(); i++){
- const std::string &id = i->first;
- const float &value = i->second;
- std::map<std::string, Meta>::iterator j =
- m_meta.find(id);
- if(j == m_meta.end()){
- m_meta[id] = Meta(value);
- continue;
- }
- if(value < j->second.min)
- j->second.min = value;
- if(value > j->second.max)
- j->second.max = value;
- }
- }
- // Assign colors
- static const video::SColor usable_colors[] = {
- video::SColor(255,255,100,100),
- video::SColor(255,90,225,90),
- video::SColor(255,100,100,255),
- video::SColor(255,255,150,50),
- video::SColor(255,220,220,100)
- };
- static const u32 usable_colors_count =
- sizeof(usable_colors) / sizeof(*usable_colors);
- u32 next_color_i = 0;
- for(std::map<std::string, Meta>::iterator i = m_meta.begin();
- i != m_meta.end(); i++){
- Meta &meta = i->second;
- video::SColor color(255,200,200,200);
- if(next_color_i < usable_colors_count)
- color = usable_colors[next_color_i++];
- meta.color = color;
- }
- s32 graphh = 50;
- s32 textx = x_left + m_log_max_size + 15;
- s32 textx2 = textx + 200 - 15;
-
- // Draw background
- /*{
- u32 num_graphs = m_meta.size();
- core::rect<s32> rect(x_left, y_bottom - num_graphs*graphh,
- textx2, y_bottom);
- video::SColor bgcolor(120,0,0,0);
- driver->draw2DRectangle(bgcolor, rect, NULL);
- }*/
-
- s32 meta_i = 0;
- for(std::map<std::string, Meta>::const_iterator i = m_meta.begin();
- i != m_meta.end(); i++){
- const std::string &id = i->first;
- const Meta &meta = i->second;
- s32 x = x_left;
- s32 y = y_bottom - meta_i * 50;
- float show_min = meta.min;
- float show_max = meta.max;
- if(show_min >= -0.0001 && show_max >= -0.0001){
- if(show_min <= show_max * 0.5)
- show_min = 0;
- }
- s32 texth = 15;
- char buf[10];
- snprintf(buf, 10, "%.3g", show_max);
- font->draw(narrow_to_wide(buf).c_str(),
- core::rect<s32>(textx, y - graphh,
- textx2, y - graphh + texth),
- meta.color);
- snprintf(buf, 10, "%.3g", show_min);
- font->draw(narrow_to_wide(buf).c_str(),
- core::rect<s32>(textx, y - texth,
- textx2, y),
- meta.color);
- font->draw(narrow_to_wide(id).c_str(),
- core::rect<s32>(textx, y - graphh/2 - texth/2,
- textx2, y - graphh/2 + texth/2),
- meta.color);
- s32 graph1y = y;
- s32 graph1h = graphh;
- bool relativegraph = (show_min != 0 && show_min != show_max);
- float lastscaledvalue = 0.0;
- bool lastscaledvalue_exists = false;
- for(std::list<Piece>::const_iterator j = m_log.begin();
- j != m_log.end(); j++)
- {
- const Piece &piece = *j;
- float value = 0;
- bool value_exists = false;
- Profiler::GraphValues::const_iterator k =
- piece.values.find(id);
- if(k != piece.values.end()){
- value = k->second;
- value_exists = true;
- }
- if(!value_exists){
- x++;
- lastscaledvalue_exists = false;
- continue;
- }
- float scaledvalue = 1.0;
- if(show_max != show_min)
- scaledvalue = (value - show_min) / (show_max - show_min);
- if(scaledvalue == 1.0 && value == 0){
- x++;
- lastscaledvalue_exists = false;
- continue;
- }
- if(relativegraph){
- if(lastscaledvalue_exists){
- s32 ivalue1 = lastscaledvalue * graph1h;
- s32 ivalue2 = scaledvalue * graph1h;
- driver->draw2DLine(v2s32(x-1, graph1y - ivalue1),
- v2s32(x, graph1y - ivalue2), meta.color);
- }
- lastscaledvalue = scaledvalue;
- lastscaledvalue_exists = true;
- } else{
- s32 ivalue = scaledvalue * graph1h;
- driver->draw2DLine(v2s32(x, graph1y),
- v2s32(x, graph1y - ivalue), meta.color);
- }
- x++;
- }
- meta_i++;
- }
- }
- };
- class NodeDugEvent: public MtEvent
- {
- public:
- v3s16 p;
- MapNode n;
-
- NodeDugEvent(v3s16 p, MapNode n):
- p(p),
- n(n)
- {}
- const char* getType() const
- {return "NodeDug";}
- };
- class SoundMaker
- {
- ISoundManager *m_sound;
- INodeDefManager *m_ndef;
- public:
- float m_player_step_timer;
- SimpleSoundSpec m_player_step_sound;
- SimpleSoundSpec m_player_leftpunch_sound;
- SimpleSoundSpec m_player_rightpunch_sound;
- SoundMaker(ISoundManager *sound, INodeDefManager *ndef):
- m_sound(sound),
- m_ndef(ndef),
- m_player_step_timer(0)
- {
- }
- void playPlayerStep()
- {
- if(m_player_step_timer <= 0 && m_player_step_sound.exists()){
- m_player_step_timer = 0.03;
- m_sound->playSound(m_player_step_sound, false);
- }
- }
- static void viewBobbingStep(MtEvent *e, void *data)
- {
- SoundMaker *sm = (SoundMaker*)data;
- sm->playPlayerStep();
- }
- static void playerRegainGround(MtEvent *e, void *data)
- {
- SoundMaker *sm = (SoundMaker*)data;
- sm->playPlayerStep();
- }
- static void playerJump(MtEvent *e, void *data)
- {
- //SoundMaker *sm = (SoundMaker*)data;
- }
- static void cameraPunchLeft(MtEvent *e, void *data)
- {
- SoundMaker *sm = (SoundMaker*)data;
- sm->m_sound->playSound(sm->m_player_leftpunch_sound, false);
- }
- static void cameraPunchRight(MtEvent *e, void *data)
- {
- SoundMaker *sm = (SoundMaker*)data;
- sm->m_sound->playSound(sm->m_player_rightpunch_sound, false);
- }
- static void nodeDug(MtEvent *e, void *data)
- {
- SoundMaker *sm = (SoundMaker*)data;
- NodeDugEvent *nde = (NodeDugEvent*)e;
- sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false);
- }
- void registerReceiver(MtEventManager *mgr)
- {
- mgr->reg("ViewBobbingStep", SoundMaker::viewBobbingStep, this);
- mgr->reg("PlayerRegainGround", SoundMaker::playerRegainGround, this);
- mgr->reg("PlayerJump", SoundMaker::playerJump, this);
- mgr->reg("CameraPunchLeft", SoundMaker::cameraPunchLeft, this);
- mgr->reg("CameraPunchRight", SoundMaker::cameraPunchRight, this);
- mgr->reg("NodeDug", SoundMaker::nodeDug, this);
- }
- void step(float dtime)
- {
- m_player_step_timer -= dtime;
- }
- };
- // Locally stored sounds don't need to be preloaded because of this
- class GameOnDemandSoundFetcher: public OnDemandSoundFetcher
- {
- std::set<std::string> m_fetched;
- public:
- void fetchSounds(const std::string &name,
- std::set<std::string> &dst_paths,
- std::set<std::string> &dst_datas)
- {
- if(m_fetched.count(name))
- return;
- m_fetched.insert(name);
- std::string base = porting::path_share + DIR_DELIM + "testsounds";
- dst_paths.insert(base + DIR_DELIM + name + ".ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".0.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".1.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".2.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".3.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".4.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".5.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".6.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".7.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".8.ogg");
- dst_paths.insert(base + DIR_DELIM + name + ".9.ogg");
- }
- };
- class GameGlobalShaderConstantSetter : public IShaderConstantSetter
- {
- Sky *m_sky;
- bool *m_force_fog_off;
- f32 *m_fog_range;
- Client *m_client;
- public:
- GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
- f32 *fog_range, Client *client):
- m_sky(sky),
- m_force_fog_off(force_fog_off),
- m_fog_range(fog_range),
- m_client(client)
- {}
- ~GameGlobalShaderConstantSetter() {}
- virtual void onSetConstants(video::IMaterialRendererServices *services,
- bool is_highlevel)
- {
- if(!is_highlevel)
- return;
- // Background color
- video::SColor bgcolor = m_sky->getBgColor();
- video::SColorf bgcolorf(bgcolor);
- float bgcolorfa[4] = {
- bgcolorf.r,
- bgcolorf.g,
- bgcolorf.b,
- bgcolorf.a,
- };
- services->setPixelShaderConstant("skyBgColor", bgcolorfa, 4);
- // Fog distance
- float fog_distance = *m_fog_range;
- if(*m_force_fog_off)
- fog_distance = 10000*BS;
- services->setPixelShaderConstant("fogDistance", &fog_distance, 1);
- // Day-night ratio
- u32 daynight_ratio = m_client->getEnv().getDayNightRatio();
- float daynight_ratio_f = (float)daynight_ratio / 1000.0;
- services->setPixelShaderConstant("dayNightRatio", &daynight_ratio_f, 1);
- }
- };
- void the_game(
- bool &kill,
- bool random_input,
- InputHandler *input,
- IrrlichtDevice *device,
- gui::IGUIFont* font,
- std::string map_dir,
- std::string playername,
- std::string password,
- std::string address, // If "", local server is used
- u16 port,
- std::wstring &error_message,
- std::string configpath,
- ChatBackend &chat_backend,
- const SubgameSpec &gamespec, // Used for local game,
- bool simple_singleplayer_mode
- )
- {
- FormspecFormSource* current_formspec = 0;
- video::IVideoDriver* driver = device->getVideoDriver();
- scene::ISceneManager* smgr = device->getSceneManager();
-
- // Calculate text height using the font
- u32 text_height = font->getDimension(L"Random test string").Height;
- v2u32 screensize(0,0);
- v2u32 last_screensize(0,0);
- screensize = driver->getScreenSize();
- const s32 hotbar_itemcount = 8;
- //const s32 hotbar_imagesize = 36;
- //const s32 hotbar_imagesize = 64;
- s32 hotbar_imagesize = 48;
-
- /*
- Draw "Loading" screen
- */
- draw_load_screen(L"Loading...", driver, font);
-
- // Create texture source
- IWritableTextureSource *tsrc = createTextureSource(device);
-
- // Create shader source
- IWritableShaderSource *shsrc = createShaderSource(device);
-
- // These will be filled by data received from the server
- // Create item definition manager
- IWritableItemDefManager *itemdef = createItemDefManager();
- // Create node definition manager
- IWritableNodeDefManager *nodedef = createNodeDefManager();
-
- // Sound fetcher (useful when testing)
- GameOnDemandSoundFetcher soundfetcher;
- // Sound manager
- ISoundManager *sound = NULL;
- bool sound_is_dummy = false;
- #if USE_SOUND
- if(g_settings->getBool("enable_sound")){
- infostream<<"Attempting to use OpenAL audio"<<std::endl;
- sound = createOpenALSoundManager(&soundfetcher);
- if(!sound)
- infostream<<"Failed to initialize OpenAL audio"<<std::endl;
- } else {
- infostream<<"Sound disabled."<<std::endl;
- }
- #endif
- if(!sound){
- infostream<<"Using dummy audio."<<std::endl;
- sound = &dummySoundManager;
- sound_is_dummy = true;
- }
- // Event manager
- EventManager eventmgr;
- // Sound maker
- SoundMaker soundmaker(sound, nodedef);
- soundmaker.registerReceiver(&eventmgr);
-
- // Add chat log output for errors to be shown in chat
- LogOutputBuffer chat_log_error_buf(LMT_ERROR);
- // Create UI for modifying quicktune values
- QuicktuneShortcutter quicktune;
- /*
- Create server.
- SharedPtr will delete it when it goes out of scope.
- */
- SharedPtr<Server> server;
- if(address == ""){
- draw_load_screen(L"Creating server...", driver, font);
- infostream<<"Creating server"<<std::endl;
- server = new Server(map_dir, configpath, gamespec,
- simple_singleplayer_mode);
- server->start(port);
- }
- try{
- do{ // Client scope (breakable do-while(0))
-
- /*
- Create client
- */
- draw_load_screen(L"Creating client...", driver, font);
- infostream<<"Creating client"<<std::endl;
-
- MapDrawControl draw_control;
- Client client(device, playername.c_str(), password, draw_control,
- tsrc, shsrc, itemdef, nodedef, sound, &eventmgr);
-
- // Client acts as our GameDef
- IGameDef *gamedef = &client;
-
- draw_load_screen(L"Resolving address...", driver, font);
- Address connect_address(0,0,0,0, port);
- try{
- if(address == "")
- //connect_address.Resolve("localhost");
- connect_address.setAddress(127,0,0,1);
- else
- connect_address.Resolve(address.c_str());
- }
- catch(ResolveError &e)
- {
- error_message = L"Couldn't resolve address";
- errorstream<<wide_to_narrow(error_message)<<std::endl;
- // Break out of client scope
- break;
- }
- /*
- Attempt to connect to the server
- */
-
- infostream<<"Connecting to server at ";
- connect_address.print(&infostream);
- infostream<<std::endl;
- client.connect(connect_address);
-
- /*
- Wait for server to accept connection
- */
- bool could_connect = false;
- bool connect_aborted = false;
- try{
- float frametime = 0.033;
- float time_counter = 0.0;
- input->clear();
- while(device->run())
- {
- // Update client and server
- client.step(frametime);
- if(server != NULL)
- server->step(frametime);
-
- // End condition
- if(client.connectedAndInitialized()){
- could_connect = true;
- break;
- }
- // Break conditions
- if(client.accessDenied()){
- error_message = L"Access denied. Reason: "
- +client.accessDeniedReason();
- errorstream<<wide_to_narrow(error_message)<<std::endl;
- break;
- }
- if(input->wasKeyDown(EscapeKey)){
- connect_aborted = true;
- infostream<<"Connect aborted [Escape]"<<std::endl;
- break;
- }
-
- // Display status
- std::wostringstream ss;
- ss<<L"Connecting to server... (press Escape to cancel)\n";
- std::wstring animation = L"/-\\|";
- ss<<animation[(int)(time_counter/0.2)%4];
- draw_load_screen(ss.str(), driver, font);
-
- // Delay a bit
- sleep_ms(1000*frametime);
- time_counter += frametime;
- }
- }
- catch(con::PeerNotFoundException &e)
- {}
-
- /*
- Handle failure to connect
- */
- if(!could_connect){
- if(error_message == L"" && !connect_aborted){
- error_message = L"Connection failed";
- errorstream<<wide_to_narrow(error_message)<<std::endl;
- }
- // Break out of client scope
- break;
- }
-
- /*
- Wait until content has been received
- */
- bool got_content = false;
- bool content_aborted = false;
- {
- float frametime = 0.033;
- float time_counter = 0.0;
- input->clear();
- while(device->run())
- {
- // Update client and server
- client.step(frametime);
- if(server != NULL)
- server->step(frametime);
-
- // End condition
- if(client.texturesReceived() &&
- client.itemdefReceived() &&
- client.nodedefReceived()){
- got_content = true;
- break;
- }
- // Break conditions
- if(!client.connectedAndInitialized()){
- error_message = L"Client disconnected";
- errorstream<<wide_to_narrow(error_message)<<std::endl;
- break;
- }
- if(input->wasKeyDown(EscapeKey)){
- content_aborted = true;
- infostream<<"Connect aborted [Escape]"<<std::endl;
- break;
- }
-
- // Display status
- std::wostringstream ss;
- ss<<L"Waiting content... (press Escape to cancel)\n";
- ss<<(client.itemdefReceived()?L"[X]":L"[ ]");
- ss<<L" Item definitions\n";
- ss<<(client.nodedefReceived()?L"[X]":L"[ ]");
- ss<<L" Node definitions\n";
- ss<<L"["<<(int)(client.mediaReceiveProgress()*100+0.5)<<L"%] ";
- ss<<L" Media\n";
- draw_load_screen(ss.str(), driver, font);
-
- // Delay a bit
- sleep_ms(1000*frametime);
- time_counter += frametime;
- }
- }
- if(!got_content){
- if(error_message == L"" && !content_aborted){
- error_message = L"Something failed";
- errorstream<<wide_to_narrow(error_message)<<std::endl;
- }
- // Break out of client scope
- break;
- }
- /*
- After all content has been received:
- Update cached textures, meshes and materials
- */
- client.afterContentReceived();
- /*
- Create the camera node
- */
- Camera camera(smgr, draw_control, gamedef);
- if (!camera.successfullyCreated(error_message))
- return;
- f32 camera_yaw = 0; // "right/left"
- f32 camera_pitch = 0; // "up/down"
- /*
- Clouds
- */
-
- Clouds *clouds = NULL;
- if(g_settings->getBool("enable_clouds"))
- {
- clouds = new Clouds(smgr->getRootSceneNode(), smgr, -1, time(0));
- }
- /*
- Skybox thingy
- */
- Sky *sky = NULL;
- sky = new Sky(smgr->getRootSceneNode(), smgr, -1);
-
- /*
- FarMesh
- */
- FarMesh *farmesh = NULL;
- if(g_settings->getBool("enable_farmesh"))
- {
- farmesh = new FarMesh(smgr->getRootSceneNode(), smgr, -1, client.getMapSeed(), &client);
- }
- /*
- A copy of the local inventory
- */
- Inventory local_inventory(itemdef);
- /*
- Find out size of crack animation
- */
- int crack_animation_length = 5;
- {
- video::ITexture *t = tsrc->getTextureRaw("crack_anylength.png");
- v2u32 size = t->getOriginalSize();
- crack_animation_length = size.Y / size.X;
- }
- /*
- Add some gui stuff
- */
- // First line of debug text
- gui::IGUIStaticText *guitext = guienv->addStaticText(
- L"Minetest",
- core::rect<s32>(5, 5, 795, 5+text_height),
- false, false);
- // Second line of debug text
- gui::IGUIStaticText *guitext2 = guienv->addStaticText(
- L"",
- core::rect<s32>(5, 5+(text_height+5)*1, 795, (5+text_height)*2),
- false, false);
- // At the middle of the screen
- // Object infos are shown in this
- gui::IGUIStaticText *guitext_info = guienv->addStaticText(
- L"",
- core::rect<s32>(0,0,400,text_height*5+5) + v2s32(100,200),
- false, false);
-
- // Status text (displays info when showing and hiding GUI stuff, etc.)
- gui::IGUIStaticText *guitext_status = guienv->addStaticText(
- L"<Status>",
- core::rect<s32>(0,0,0,0),
- false, false);
- guitext_status->setVisible(false);
-
- std::wstring statustext;
- float statustext_time = 0;
-
- // Chat text
- gui::IGUIStaticText *guitext_chat = guienv->addStaticText(
- L"",
- core::rect<s32>(0,0,0,0),
- //false, false); // Disable word wrap as of now
- false, true);
- // Remove stale "recent" chat messages from previous connections
- chat_backend.clearRecentChat();
- // Chat backend and console
- GUIChatConsole *gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(), -1, &chat_backend, &client);
-
- // Profiler text (size is updated when text is updated)
- gui::IGUIStaticText *guitext_profiler = guienv->addStaticText(
- L"<Profiler>",
- core::rect<s32>(0,0,0,0),
- false, false);
- guitext_profiler->setBackgroundColor(video::SColor(120,0,0,0));
- guitext_profiler->setVisible(false);
-
- /*
- Some statistics are collected in these
- */
- u32 drawtime = 0;
- u32 beginscenetime = 0;
- u32 scenetime = 0;
- u32 endscenetime = 0;
-
- float recent_turn_speed = 0.0;
-
- ProfilerGraph graph;
- // Initially clear the profiler
- Profiler::GraphValues dummyvalues;
- g_profiler->graphGet(dummyvalues);
- float nodig_delay_timer = 0.0;
- float dig_time = 0.0;
- u16 dig_index = 0;
- PointedThing pointed_old;
- bool digging = false;
- bool ldown_for_dig = false;
- float damage_flash = 0;
- s16 farmesh_range = 20*MAP_BLOCKSIZE;
- float jump_timer = 0;
- bool reset_jump_timer = false;
- const float object_hit_delay = 0.2;
- float object_hit_delay_timer = 0.0;
- float time_from_last_punch = 10;
- float update_draw_list_timer = 0.0;
- v3f update_draw_list_last_cam_dir;
- bool invert_mouse = g_settings->getBool("invert_mouse");
- bool respawn_menu_active = false;
- bool update_wielded_item_trigger = false;
- bool show_hud = true;
- bool show_chat = true;
- bool force_fog_off = false;
- f32 fog_range = 100*BS;
- bool disable_camera_update = false;
- bool show_debug = g_settings->getBool("show_debug");
- bool show_profiler_graph = false;
- u32 show_profiler = 0;
- u32 show_profiler_max = 3; // Number of pages
- float time_of_day = 0;
- float time_of_day_smooth = 0;
- float repeat_rightclick_timer = 0;
- /*
- Shader constants
- */
- shsrc->addGlobalConstantSetter(new GameGlobalShaderConstantSetter(
- sky, &force_fog_off, &fog_range, &client));
- /*
- Main loop
- */
- bool first_loop_after_window_activation = true;
- // TODO: Convert the static interval timers to these
- // Interval limiter for profiler
- IntervalLimiter m_profiler_interval;
- // Time is in milliseconds
- // NOTE: getRealTime() causes strange problems in wine (imprecision?)
- // NOTE: So we have to use getTime() and call run()s between them
- u32 lasttime = device->getTimer()->getTime();
- LocalPlayer* player = client.getEnv().getLocalPlayer();
- player->hurt_tilt_timer = 0;
- player->hurt_tilt_strength = 0;
- for(;;)
- {
- if(device->run() == false || kill == true)
- break;
- // Time of frame without fps limit
- float busytime;
- u32 busytime_u32;
- {
- // not using getRealTime is necessary for wine
- u32 time = device->getTimer()->getTime();
- if(time > lasttime)
- busytime_u32 = time - lasttime;
- else
- busytime_u32 = 0;
- busytime = busytime_u32 / 1000.0;
- }
-
- g_profiler->graphAdd("mainloop_other", busytime - (float)drawtime/1000.0f);
- // Necessary for device->getTimer()->getTime()
- device->run();
- /*
- FPS limiter
- */
- {
- float fps_max = g_settings->getFloat("fps_max");
- u32 frametime_min = 1000./fps_max;
-
- if(busytime_u32 < frametime_min)
- {
- u32 sleeptime = frametime_min - busytime_u32;
- device->sleep(sleeptime);
- g_profiler->graphAdd("mainloop_sleep", (float)sleeptime/1000.0f);
- }
- }
- // Necessary for device->getTimer()->getTime()
- device->run();
- /*
- Time difference calculation
- */
- f32 dtime; // in seconds
-
- u32 time = device->getTimer()->getTime();
- if(time > lasttime)
- dtime = (time - lasttime) / 1000.0;
- else
- dtime = 0;
- lasttime = time;
- g_profiler->graphAdd("mainloop_dtime", dtime);
- /* Run timers */
- if(nodig_delay_timer >= 0)
- nodig_delay_timer -= dtime;
- if(object_hit_delay_timer >= 0)
- object_hit_delay_timer -= dtime;
- time_from_last_punch += dtime;
-
- g_profiler->add("Elapsed time", dtime);
- g_profiler->avg("FPS", 1./dtime);
- /*
- Time average and jitter calculation
- */
- static f32 dtime_avg1 = 0.0;
- dtime_avg1 = dtime_avg1 * 0.96 + dtime * 0.04;
- f32 dtime_jitter1 = dtime - dtime_avg1;
- static f32 dtime_jitter1_max_sample = 0.0;
- static f32 dtime_jitter1_max_fraction = 0.0;
- {
- static f32 jitter1_max = 0.0;
- static f32 counter = 0.0;
- if(dtime_jitter1 > jitter1_max)
- jitter1_max = dtime_jitter1;
- counter += dtime;
- if(counter > 0.0)
- {
- counter -= 3.0;
- dtime_jitter1_max_sample = jitter1_max;
- dtime_jitter1_max_fraction
- = dtime_jitter1_max_sample / (dtime_avg1+0.001);
- jitter1_max = 0.0;
- }
- }
-
- /*
- Busytime average and jitter calculation
- */
- static f32 busytime_avg1 = 0.0;
- busytime_avg1 = busytime_avg1 * 0.98 + busytime * 0.02;
- f32 busytime_jitter1 = busytime - busytime_avg1;
-
- static f32 busytime_jitter1_max_sample = 0.0;
- static f32 busytime_jitter1_min_sample = 0.0;
- {
- static f32 jitter1_max = 0.0;
- static f32 jitter1_min = 0.0;
- static f32 counter = 0.0;
- if(busytime_jitter1 > jitter1_max)
- jitter1_max = busytime_jitter1;
- if(busytime_jitter1 < jitter1_min)
- jitter1_min = busytime_jitter1;
- counter += dtime;
- if(counter > 0.0){
- counter -= 3.0;
- busytime_jitter1_max_sample = jitter1_max;
- busytime_jitter1_min_sample = jitter1_min;
- jitter1_max = 0.0;
- jitter1_min = 0.0;
- }
- }
- /*
- Handle miscellaneous stuff
- */
-
- if(client.accessDenied())
- {
- error_message = L"Access denied. Reason: "
- +client.accessDeniedReason();
- errorstream<<wide_to_narrow(error_message)<<std::endl;
- break;
- }
- if(g_gamecallback->disconnect_requested)
- {
- g_gamecallback->disconnect_requested = false;
- break;
- }
- if(g_gamecallback->changepassword_requested)
- {
- (new GUIPasswordChange(guienv, guiroot, -1,
- &g_menumgr, &client))->drop();
- g_gamecallback->changepassword_requested = false;
- }
- /* Process TextureSource's queue */
- tsrc->processQueue();
- /* Process ItemDefManager's queue */
- itemdef->processQueue(gamedef);
- /*
- Process ShaderSource's queue
- */
- shsrc->processQueue();
- /*
- Random calculations
- */
- last_screensize = screensize;
- screensize = driver->getScreenSize();
- v2s32 displaycenter(screensize.X/2,screensize.Y/2);
- //bool screensize_changed = screensize != last_screensize;
- // Resize hotbar
- if(screensize.Y <= 800)
- hotbar_imagesize = 32;
- else if(screensize.Y <= 1280)
- hotbar_imagesize = 48;
- else
- hotbar_imagesize = 64;
-
- // Hilight boxes collected during the loop and displayed
- std::vector<aabb3f> hilightboxes;
-
- // Info text
- std::wstring infotext;
- /*
- Debug info for client
- */
- {
- static float counter = 0.0;
- counter -= dtime;
- if(counter < 0)
- {
- counter = 30.0;
- client.printDebugInfo(infostream);
- }
- }
- /*
- Profiler
- */
- float profiler_print_interval =
- g_settings->getFloat("profiler_print_interval");
- bool print_to_log = true;
- if(profiler_print_interval == 0){
- print_to_log = false;
- profiler_print_interval = 5;
- }
- if(m_profiler_interval.step(dtime, profiler_print_interval))
- {
- if(print_to_log){
- infostream<<"Profiler:"<<std::endl;
- g_profiler->print(infostream);
- }
- update_profiler_gui(guitext_profiler, font, text_height,
- show_profiler, show_profiler_max);
- g_profiler->clear();
- }
- /*
- Direct handling of user input
- */
-
- // Reset input if window not active or some menu is active
- if(device->isWindowActive() == false
- || noMenuActive() == false
- || guienv->hasFocus(gui_chat_console))
- {
- input->clear();
- }
- // Input handler step() (used by the random input generator)
- input->step(dtime);
- // Increase timer for doubleclick of "jump"
- if(g_settings->getBool("doubletap_jump") && jump_timer <= 0.2)
- jump_timer += dtime;
- /*
- Launch menus and trigger stuff according to keys
- */
- if(input->wasKeyDown(getKeySetting("keymap_drop")))
- {
- // drop selected item
- IDropAction *a = new IDropAction();
- a->count = 0;
- a->from_inv.setCurrentPlayer();
- a->from_list = "main";
- a->from_i = client.getPlayerItem();
- client.inventoryAction(a);
- }
- else if(input->wasKeyDown(getKeySetting("keymap_inventory")))
- {
- infostream<<"the_game: "
- <<"Launching inventory"<<std::endl;
-
- GUIFormSpecMenu *menu =
- new GUIFormSpecMenu(device, guiroot, -1,
- &g_menumgr,
- &client, gamedef);
- InventoryLocation inventoryloc;
- inventoryloc.setCurrentPlayer();
- PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client);
- assert(src);
- menu->setFormSpec(src->getForm(), inventoryloc);
- menu->setFormSource(src);
- menu->setTextDest(new TextDestPlayerInventory(&client));
- menu->drop();
- }
- else if(input->wasKeyDown(EscapeKey))
- {
- infostream<<"the_game: "
- <<"Launching pause menu"<<std::endl;
- // It will delete itself by itself
- (new GUIPauseMenu(guienv, guiroot, -1, g_gamecallback,
- &g_menumgr, simple_singleplayer_mode))->drop();
- // Move mouse cursor on top of the disconnect button
- if(simple_singleplayer_mode)
- input->setMousePos(displaycenter.X, displaycenter.Y+0);
- else
- input->setMousePos(displaycenter.X, displaycenter.Y+25);
- }
- else if(input->wasKeyDown(getKeySetting("keymap_chat")))
- {
- TextDest *dest = new TextDestChat(&client);
- (new GUITextInputMenu(guienv, guiroot, -1,
- &g_menumgr, dest,
- L""))->drop();
- }
- else if(input->wasKeyDown(getKeySetting("keymap_cmd")))
- {
- TextDest *dest = new TextDestChat(&client);
- (new GUITextInputMenu(guienv, guiroot, -1,
- &g_menumgr, dest,
- L"/"))->drop();
- }
- else if(input->wasKeyDown(getKeySetting("keymap_console")))
- {
- if (!gui_chat_console->isOpenInhibited())
- {
- // Open up to over half of the screen
- gui_chat_console->openConsole(0.6);
- guienv->setFocus(gui_chat_console);
- }
- }
- else if(input->wasKeyDown(getKeySetting("keymap_freemove")))
- {
- if(g_settings->getBool("free_move"))
- {
- g_settings->set("free_move","false");
- statustext = L"free_move disabled";
- statustext_time = 0;
- }
- else
- {
- g_settings->set("free_move","true");
- statustext = L"free_move enabled";
- statustext_time = 0;
- if(!client.checkPrivilege("fly"))
- statustext += L" (note: no 'fly' privilege)";
- }
- }
- else if(input->wasKeyDown(getKeySetting("keymap_jump")))
- {
- if(g_settings->getBool("doubletap_jump") && jump_timer < 0.2)
- {
- if(g_settings->getBool("free_move"))
- {
- g_settings->set("free_move","false");
- statustext = L"free_move disabled";
- statustext_time = 0;
- }
- else
- {
- g_settings->set("free_move","true");
- statustext = L"free_move enabled";
- statustext_time = 0;
- if(!client.checkPrivilege("fly"))
- statustext += L" (note: no 'fly' privilege)";
- }
- }
- reset_jump_timer = true;
- }
- else if(input->wasKeyDown(getKeySetting("keymap_fastmove")))
- {
- if(g_settings->getBool("fast_move"))
- {
- g_settings->set("fast_move","false");
- statustext = L"fast_move disabled";
- statustext_time = 0;
- }
- else
- {
- g_settings->set("fast_move","true");
- statustext = L"fast_move enabled";
- statustext_time = 0;
- if(!client.checkPrivilege("fast"))
- statustext += L" (note: no 'fast' privilege)";
- }
- }
- else if(input->wasKeyDown(getKeySetting("keymap_noclip")))
- {
- if(g_settings->getBool("noclip"))
- {
- g_settings->set("noclip","false");
- statustext = L"noclip disabled";
- statustext_time = 0;
- }
- else
- {
- g_settings->set("noclip","true");
- statustext = L"noclip enabled";
- statustext_time = 0;
- if(!client.checkPrivilege("noclip"))
- statustext += L" (note: no 'noclip' privilege)";
- }
- }
- else if(input->wasKeyDown(getKeySetting("keymap_screenshot")))
- {
- irr::video::IImage* const image = driver->createScreenShot();
- if (image) {
- irr::c8 filename[256];
- snprintf(filename, 256, "%s" DIR_DELIM "screenshot_%u.png",
- g_settings->get("screenshot_path").c_str(),
- device->getTimer()->getRealTime());
- if (driver->writeImageToFile(image, filename)) {
- std::wstringstream sstr;
- sstr<<"Saved screenshot to '"<<filename<<"'";
- infostream<<"Saved screenshot to '"<<filename<<"'"<<std::endl;
- statustext = sstr.str();
- statustext_time = 0;
- } else{
- infostream<<"Failed to save screenshot '"<<filename<<"'"<<std::endl;
- }
- image->drop();
- }
- }
- else if(input->wasKeyDown(getKeySetting("keymap_toggle_hud")))
- {
- show_hud = !show_hud;
- if(show_hud)
- statustext = L"HUD shown";
- else
- statustext = L"HUD hidden";
- statustext_time = 0;
- }
- else if(input->wasKeyDown(getKeySetting("keymap_toggle_chat")))
- {
- show_chat = !show_chat;
- if(show_chat)
- statustext = L"Chat shown";
- else
- statustext = L"Chat hidden";
- statustext_time = 0;
- }
- else if(input->wasKeyDown(getKeySetting("keymap_toggle_force_fog_off")))
- {
- force_fog_off = !force_fog_off;
- if(force_fog_off)
- statustext = L"Fog disabled";
- else
- statustext = L"Fog enabled";
- statustext_time = 0;
- }
- else if(input->wasKeyDown(getKeySetting("keymap_toggle_update_camera")))
- {
- disable_camera_update = !disable_camera_update;
- if(disable_camera_update)
- statustext = L"Camera update disabled";
- else
- statustext = L"Camera update enabled";
- statustext_time = 0;
- }
- else if(input->wasKeyDown(getKeySetting("keymap_toggle_debug")))
- {
- // Initial / 3x toggle: Chat only
- // 1x toggle: Debug text with chat
- // 2x toggle: Debug text with profiler graph
- if(!show_debug)
- {
- show_debug = true;
- show_profiler_graph = false;
- statustext = L"Debug info shown";
- statustext_time = 0;
- }
- else if(show_profiler_graph)
- {
- show_debug = false;
- show_profiler_graph = false;
- statustext = L"Debug info and profiler graph hidden";
- statustext_time = 0;
- }
- else
- {
- show_profiler_graph = true;
- statustext = L"Profiler graph shown";
- statustext_time = 0;
- }
- }
- else if(input->wasKeyDown(getKeySetting("keymap_toggle_profiler")))
- {
- show_profiler = (show_profiler + 1) % (show_profiler_max + 1);
- // FIXME: This updates the profiler with incomplete values
- update_profiler_gui(guitext_profiler, font, text_height,
- show_profiler, show_profiler_max);
- if(show_profiler != 0)
- {
- std::wstringstream sstr;
- sstr<<"Profiler shown (page "<<show_profiler
- <<" of "<<show_profiler_max<<")";
- statustext = sstr.str();
- statustext_time = 0;
- }
- else
- {
- statustext = L"Profiler hidden";
- statustext_time = 0;
- }
- }
- else if(input->wasKeyDown(getKeySetting("keymap_increase_viewing_range_min")))
- {
- s16 range = g_settings->getS16("viewing_range_nodes_min");
- s16 range_new = range + 10;
- g_settings->set("viewing_range_nodes_min", itos(range_new));
- statustext = narrow_to_wide(
- "Minimum viewing range changed to "
- + itos(range_new));
- statustext_time = 0;
- }
- else if(input->wasKeyDown(getKeySetting("keymap_decrease_viewing_range_min")))
- {
- s16 range = g_settings->getS16("viewing_range_nodes_min");
- s16 range_new = range - 10;
- if(range_new < 0)
- range_new = range;
- g_settings->set("viewing_range_nodes_min",
- itos(range_new));
- statustext = narrow_to_wide(
- "Minimum viewing range changed to "
- + itos(range_new));
- statustext_time = 0;
- }
-
- // Reset jump_timer
- if(!input->isKeyDown(getKeySetting("keymap_jump")) && reset_jump_timer)
- {
- reset_jump_timer = false;
- jump_timer = 0.0;
- }
- // Handle QuicktuneShortcutter
- if(input->wasKeyDown(getKeySetting("keymap_quicktune_next")))
- quicktune.next();
- if(input->wasKeyDown(getKeySetting("keymap_quicktune_prev")))
- quicktune.prev();
- if(input->wasKeyDown(getKeySetting("keymap_quicktune_inc")))
- quicktune.inc();
- if(input->wasKeyDown(getKeySetting("keymap_quicktune_dec")))
- quicktune.dec();
- {
- std::string msg = quicktune.getMessage();
- if(msg != ""){
- statustext = narrow_to_wide(msg);
- statustext_time = 0;
- }
- }
- // Item selection with mouse wheel
- u16 new_playeritem = client.getPlayerItem();
- {
- s32 wheel = input->getMouseWheel();
- u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE-1,
- hotbar_itemcount-1);
- if(wheel < 0)
- {
- if(new_playeritem < max_item)
- new_playeritem++;
- else
- new_playeritem = 0;
- }
- else if(wheel > 0)
- {
- if(new_playeritem > 0)
- new_playeritem--;
- else
- new_playeritem = max_item;
- }
- }
-
- // Item selection
- for(u16 i=0; i<10; i++)
- {
- const KeyPress *kp = NumberKey + (i + 1) % 10;
- if(input->wasKeyDown(*kp))
- {
- if(i < PLAYER_INVENTORY_SIZE && i < hotbar_itemcount)
- {
- new_playeritem = i;
- infostream<<"Selected item: "
- <<new_playeritem<<std::endl;
- }
- }
- }
- // Viewing range selection
- if(input->wasKeyDown(getKeySetting("keymap_rangeselect")))
- {
- draw_control.range_all = !draw_control.range_all;
- if(draw_control.range_all)
- {
- infostream<<"Enabled full viewing range"<<std::endl;
- statustext = L"Enabled full viewing range";
- statustext_time = 0;
- }
- else
- {
- infostream<<"Disabled full viewing range"<<std::endl;
- statustext = L"Disabled full viewing range";
- statustext_time = 0;
- }
- }
- // Print debug stacks
- if(input->wasKeyDown(getKeySetting("keymap_print_debug_stacks")))
- {
- dstream<<"-----------------------------------------"
- <<std::endl;
- dstream<<DTIME<<"Printing debug stacks:"<<std::endl;
- dstream<<"-----------------------------------------"
- <<std::endl;
- debug_stacks_print();
- }
- /*
- Mouse and camera control
- NOTE: Do this before client.setPlayerControl() to not cause a camera lag of one frame
- */
-
- float turn_amount = 0;
- if((device->isWindowActive() && noMenuActive()) || random_input)
- {
- if(!random_input)
- {
- // Mac OSX gets upset if this is set every frame
- if(device->getCursorControl()->isVisible())
- device->getCursorControl()->setVisible(false);
- }
- if(first_loop_after_window_activation){
- //infostream<<"window active, first loop"<<std::endl;
- first_loop_after_window_activation = false;
- }
- else{
- s32 dx = input->getMousePos().X - displaycenter.X;
- s32 dy = input->getMousePos().Y - displaycenter.Y;
- if(invert_mouse)
- dy = -dy;
- //infostream<<"window active, pos difference "<<dx<<","<<dy<<std::endl;
-
- /*const float keyspeed = 500;
- if(input->isKeyDown(irr::KEY_UP))
- dy -= dtime * keyspeed;
- if(input->isKeyDown(irr::KEY_DOWN))
- dy += dtime * keyspeed;
- if(input->isKeyDown(irr::KEY_LEFT))
- dx -= dtime * keyspeed;
- if(input->isKeyDown(irr::KEY_RIGHT))
- dx += dtime * keyspeed;*/
-
- float d = 0.2;
- camera_yaw -= dx*d;
- camera_pitch += dy*d;
- if(camera_pitch < -89.5) camera_pitch = -89.5;
- if(camera_pitch > 89.5) camera_pitch = 89.5;
-
- turn_amount = v2f(dx, dy).getLength() * d;
- }
- input->setMousePos(displaycenter.X, displaycenter.Y);
- }
- else{
- // Mac OSX gets upset if this is set every frame
- if(device->getCursorControl()->isVisible() == false)
- device->getCursorControl()->setVisible(true);
- //infostream<<"window inactive"<<std::endl;
- first_loop_after_window_activation = true;
- }
- recent_turn_speed = recent_turn_speed * 0.9 + turn_amount * 0.1;
- //std::cerr<<"recent_turn_speed = "<<recent_turn_speed<<std::endl;
- /*
- Player speed control
- */
- {
- /*bool a_up,
- bool a_down,
- bool a_left,
- bool a_right,
- bool a_jump,
- bool a_superspeed,
- bool a_sneak,
- bool a_LMB,
- bool a_RMB,
- float a_pitch,
- float a_yaw*/
- PlayerControl control(
- input->isKeyDown(getKeySetting("keymap_forward")),
- input->isKeyDown(getKeySetting("keymap_backward")),
- input->isKeyDown(getKeySetting("keymap_left")),
- input->isKeyDown(getKeySetting("keymap_right")),
- input->isKeyDown(getKeySetting("keymap_jump")),
- input->isKeyDown(getKeySetting("keymap_special1")),
- input->isKeyDown(getKeySetting("keymap_sneak")),
- input->getLeftState(),
- input->getRightState(),
- camera_pitch,
- camera_yaw
- );
- client.setPlayerControl(control);
- u32 keyPressed=
- 1*(int)input->isKeyDown(getKeySetting("keymap_forward"))+
- 2*(int)input->isKeyDown(getKeySetting("keymap_backward"))+
- 4*(int)input->isKeyDown(getKeySetting("keymap_left"))+
- 8*(int)input->isKeyDown(getKeySetting("keymap_right"))+
- 16*(int)input->isKeyDown(getKeySetting("keymap_jump"))+
- 32*(int)input->isKeyDown(getKeySetting("keymap_special1"))+
- 64*(int)input->isKeyDown(getKeySetting("keymap_sneak"))+
- 128*(int)input->getLeftState()+
- 256*(int)input->getRightState();
- LocalPlayer* player = client.getEnv().getLocalPlayer();
- player->keyPressed=keyPressed;
- }
-
- /*
- Run server
- */
- if(server != NULL)
- {
- //TimeTaker timer("server->step(dtime)");
- server->step(dtime);
- }
- /*
- Process environment
- */
-
- {
- //TimeTaker timer("client.step(dtime)");
- client.step(dtime);
- //client.step(dtime_avg1);
- }
- {
- // Read client events
- for(;;)
- {
- ClientEvent event = client.getClientEvent();
- if(event.type == CE_NONE)
- {
- break;
- }
- else if(event.type == CE_PLAYER_DAMAGE)
- {
- //u16 damage = event.player_damage.amount;
- //infostream<<"Player damage: "<<damage<<std::endl;
- damage_flash += 100.0;
- damage_flash += 8.0 * event.player_damage.amount;
- player->hurt_tilt_timer = 1.5;
- player->hurt_tilt_strength = event.player_damage.amount/2;
- player->hurt_tilt_strength = rangelim(player->hurt_tilt_strength, 2.0, 10.0);
- }
- else if(event.type == CE_PLAYER_FORCE_MOVE)
- {
- camera_yaw = event.player_force_move.yaw;
- camera_pitch = event.player_force_move.pitch;
- }
- else if(event.type == CE_DEATHSCREEN)
- {
- if(respawn_menu_active)
- continue;
- /*bool set_camera_point_target =
- event.deathscreen.set_camera_point_target;
- v3f camera_point_target;
- camera_point_target.X = event.deathscreen.camera_point_target_x;
- camera_point_target.Y = event.deathscreen.camera_point_target_y;
- camera_point_target.Z = event.deathscreen.camera_point_target_z;*/
- MainRespawnInitiator *respawner =
- new MainRespawnInitiator(
- &respawn_menu_active, &client);
- GUIDeathScreen *menu =
- new GUIDeathScreen(guienv, guiroot, -1,
- &g_menumgr, respawner);
- menu->drop();
-
- chat_backend.addMessage(L"", L"You died.");
- /* Handle visualization */
- damage_flash = 0;
- LocalPlayer* player = client.getEnv().getLocalPlayer();
- player->hurt_tilt_timer = 0;
- player->hurt_tilt_strength = 0;
- /*LocalPlayer* player = client.getLocalPlayer();
- player->setPosition(player->getPosition() + v3f(0,-BS,0));
- camera.update(player, busytime, screensize);*/
- }
- else if (event.type == CE_SHOW_FORMSPEC)
- {
- if (current_formspec == 0)
- {
- /* Create menu */
- current_formspec = new FormspecFormSource(*(event.show_formspec.formspec),¤t_formspec);
- GUIFormSpecMenu *menu =
- new GUIFormSpecMenu(device, guiroot, -1,
- &g_menumgr,
- &client, gamedef);
- menu->setFormSource(current_formspec);
- menu->drop();
- }
- else
- {
- /* update menu */
- current_formspec->setForm(*(event.show_formspec.formspec));
- }
- delete(event.show_formspec.formspec);
- }
- else if(event.type == CE_TEXTURES_UPDATED)
- {
- update_wielded_item_trigger = true;
- }
- }
- }
-
- //TimeTaker //timer2("//timer2");
- /*
- For interaction purposes, get info about the held item
- - What item is it?
- - Is it a usable item?
- - Can it point to liquids?
- */
- ItemStack playeritem;
- bool playeritem_usable = false;
- bool playeritem_liquids_pointable = false;
- {
- InventoryList *mlist = local_inventory.getList("main");
- if(mlist != NULL)
- {
- playeritem = mlist->getItem(client.getPlayerItem());
- playeritem_usable = playeritem.getDefinition(itemdef).usable;
- playeritem_liquids_pointable = playeritem.getDefinition(itemdef).liquids_pointable;
- }
- }
- ToolCapabilities playeritem_toolcap =
- playeritem.getToolCapabilities(itemdef);
-
- /*
- Update camera
- */
- LocalPlayer* player = client.getEnv().getLocalPlayer();
- float full_punch_interval = playeritem_toolcap.full_punch_interval;
- float tool_reload_ratio = time_from_last_punch / full_punch_interval;
- tool_reload_ratio = MYMIN(tool_reload_ratio, 1.0);
- camera.update(player, busytime, screensize, tool_reload_ratio);
- camera.step(dtime);
- v3f player_position = player->getPosition();
- v3f camera_position = camera.getPosition();
- v3f camera_direction = camera.getDirection();
- f32 camera_fov = camera.getFovMax();
-
- if(!disable_camera_update){
- client.getEnv().getClientMap().updateCamera(camera_position,
- camera_direction, camera_fov);
- }
-
- // Update sound listener
- sound->updateListener(camera.getCameraNode()->getPosition(),
- v3f(0,0,0), // velocity
- camera.getDirection(),
- camera.getCameraNode()->getUpVector());
- sound->setListenerGain(g_settings->getFloat("sound_volume"));
- /*
- Update sound maker
- */
- {
- soundmaker.step(dtime);
-
- ClientMap &map = client.getEnv().getClientMap();
- MapNode n = map.getNodeNoEx(player->getStandingNodePos());
- soundmaker.m_player_step_sound = nodedef->get(n).sound_footstep;
- }
- /*
- Calculate what block is the crosshair pointing to
- */
-
- //u32 t1 = device->getTimer()->getRealTime();
-
- f32 d = 4; // max. distance
- core::line3d<f32> shootline(camera_position,
- camera_position + camera_direction * BS * (d+1));
- ClientActiveObject *selected_object = NULL;
- PointedThing pointed = getPointedThing(
- // input
- &client, player_position, camera_direction,
- camera_position, shootline, d,
- playeritem_liquids_pointable, !ldown_for_dig,
- // output
- hilightboxes,
- selected_object);
- if(pointed != pointed_old)
- {
- infostream<<"Pointing at "<<pointed.dump()<<std::endl;
- //dstream<<"Pointing at "<<pointed.dump()<<std::endl;
- }
- /*
- Stop digging when
- - releasing left mouse button
- - pointing away from node
- */
- if(digging)
- {
- if(input->getLeftReleased())
- {
- infostream<<"Left button released"
- <<" (stopped digging)"<<std::endl;
- digging = false;
- }
- else if(pointed != pointed_old)
- {
- if (pointed.type == POINTEDTHING_NODE
- && pointed_old.type == POINTEDTHING_NODE
- && pointed.node_undersurface == pointed_old.node_undersurface)
- {
- // Still pointing to the same node,
- // but a different face. Don't reset.
- }
- else
- {
- infostream<<"Pointing away from node"
- <<" (stopped digging)"<<std::endl;
- digging = false;
- }
- }
- if(!digging)
- {
- client.interact(1, pointed_old);
- client.setCrack(-1, v3s16(0,0,0));
- dig_time = 0.0;
- }
- }
- if(!digging && ldown_for_dig && !input->getLeftState())
- {
- ldown_for_dig = false;
- }
- bool left_punch = false;
- soundmaker.m_player_leftpunch_sound.name = "";
- if(input->getRightState())
- repeat_rightclick_timer += dtime;
- if(playeritem_usable && input->getLeftState())
- {
- if(input->getLeftClicked())
- client.interact(4, pointed);
- }
- else if(pointed.type == POINTEDTHING_NODE)
- {
- v3s16 nodepos = pointed.node_undersurface;
- v3s16 neighbourpos = pointed.node_abovesurface;
- /*
- Check information text of node
- */
-
- ClientMap &map = client.getEnv().getClientMap();
- NodeMetadata *meta = map.getNodeMetadata(nodepos);
- if(meta){
- infotext = narrow_to_wide(meta->getString("infotext"));
- } else {
- MapNode n = map.getNode(nodepos);
- if(nodedef->get(n).tiledef[0].name == "unknown_block.png"){
- infotext = L"Unknown node: ";
- infotext += narrow_to_wide(nodedef->get(n).name);
- }
- }
-
- // We can't actually know, but assume the sound of right-clicking
- // to be the sound of placing a node
- soundmaker.m_player_rightpunch_sound.gain = 0.5;
- soundmaker.m_player_rightpunch_sound.name = "default_place_node";
-
- /*
- Handle digging
- */
-
- if(nodig_delay_timer <= 0.0 && input->getLeftState())
- {
- if(!digging)
- {
- infostream<<"Started digging"<<std::endl;
- client.interact(0, pointed);
- digging = true;
- ldown_for_dig = true;
- }
- MapNode n = client.getEnv().getClientMap().getNode(nodepos);
-
- // NOTE: Similar piece of code exists on the server side for
- // cheat detection.
- // Get digging parameters
- DigParams params = getDigParams(nodedef->get(n).groups,
- &playeritem_toolcap);
- // If can't dig, try hand
- if(!params.diggable){
- const ItemDefinition &hand = itemdef->get("");
- const ToolCapabilities *tp = hand.tool_capabilities;
- if(tp)
- params = getDigParams(nodedef->get(n).groups, tp);
- }
-
- SimpleSoundSpec sound_dig = nodedef->get(n).sound_dig;
- if(sound_dig.exists()){
- if(sound_dig.name == "__group"){
- if(params.main_group != ""){
- soundmaker.m_player_leftpunch_sound.gain = 0.5;
- soundmaker.m_player_leftpunch_sound.name =
- std::string("default_dig_") +
- params.main_group;
- }
- } else{
- soundmaker.m_player_leftpunch_sound = sound_dig;
- }
- }
- float dig_time_complete = 0.0;
- if(params.diggable == false)
- {
- // I guess nobody will wait for this long
- dig_time_complete = 10000000.0;
- }
- else
- {
- dig_time_complete = params.time;
- }
- if(dig_time_complete >= 0.001)
- {
- dig_index = (u16)((float)crack_animation_length
- * dig_time/dig_time_complete);
- }
- // This is for torches
- else
- {
- dig_index = crack_animation_length;
- }
- // Don't show cracks if not diggable
- if(dig_time_complete >= 100000.0)
- {
- }
- else if(dig_index < crack_animation_length)
- {
- //TimeTaker timer("client.setTempMod");
- //infostream<<"dig_index="<<dig_index<<std::endl;
- client.setCrack(dig_index, nodepos);
- }
- else
- {
- infostream<<"Digging completed"<<std::endl;
- client.interact(2, pointed);
- client.setCrack(-1, v3s16(0,0,0));
- MapNode wasnode = map.getNode(nodepos);
- client.removeNode(nodepos);
- dig_time = 0;
- digging = false;
- nodig_delay_timer = dig_time_complete
- / (float)crack_animation_length;
- // We don't want a corresponding delay to
- // very time consuming nodes
- if(nodig_delay_timer > 0.3)
- nodig_delay_timer = 0.3;
- // We want a slight delay to very little
- // time consuming nodes
- float mindelay = 0.15;
- if(nodig_delay_timer < mindelay)
- nodig_delay_timer = mindelay;
-
- // Send event to trigger sound
- MtEvent *e = new NodeDugEvent(nodepos, wasnode);
- gamedef->event()->put(e);
- }
- dig_time += dtime;
- camera.setDigging(0); // left click animation
- }
- if(input->getRightClicked() ||
- repeat_rightclick_timer >= g_settings->getFloat("repeat_rightclick_time"))
- {
- repeat_rightclick_timer = 0;
- infostream<<"Ground right-clicked"<<std::endl;
-
- // Sign special case, at least until formspec is properly implemented.
- // Deprecated?
- if(meta && meta->getString("formspec") == "hack:sign_text_input" && !random_input)
- {
- infostream<<"Launching metadata text input"<<std::endl;
-
- // Get a new text for it
- TextDest *dest = new TextDestNodeMetadata(nodepos, &client);
- std::wstring wtext = narrow_to_wide(meta->getString("text"));
- (new GUITextInputMenu(guienv, guiroot, -1,
- &g_menumgr, dest,
- wtext))->drop();
- }
- // If metadata provides an inventory view, activate it
- else if(meta && meta->getString("formspec") != "" && !random_input)
- {
- infostream<<"Launching custom inventory view"<<std::endl;
- InventoryLocation inventoryloc;
- inventoryloc.setNodeMeta(nodepos);
-
- /* Create menu */
- GUIFormSpecMenu *menu =
- new GUIFormSpecMenu(device, guiroot, -1,
- &g_menumgr,
- &client, gamedef);
- menu->setFormSpec(meta->getString("formspec"),
- inventoryloc);
- menu->setFormSource(new NodeMetadataFormSource(
- &client.getEnv().getClientMap(), nodepos));
- menu->setTextDest(new TextDestNodeMetadata(nodepos, &client));
- menu->drop();
- }
- // Otherwise report right click to server
- else
- {
- // Report to server
- client.interact(3, pointed);
- camera.setDigging(1); // right click animation
-
- // If the wielded item has node placement prediction,
- // make that happen
- const ItemDefinition &def =
- playeritem.getDefinition(itemdef);
- if(def.node_placement_prediction != "")
- do{ // breakable
- verbosestream<<"Node placement prediction for "
- <<playeritem.name<<" is "
- <<def.node_placement_prediction<<std::endl;
- v3s16 p = neighbourpos;
- // Place inside node itself if buildable_to
- try{
- MapNode n_under = map.getNode(nodepos);
- if(nodedef->get(n_under).buildable_to)
- p = nodepos;
- }catch(InvalidPositionException &e){}
- // Find id of predicted node
- content_t id;
- bool found =
- nodedef->getId(def.node_placement_prediction, id);
- if(!found){
- errorstream<<"Node placement prediction failed for "
- <<playeritem.name<<" (places "
- <<def.node_placement_prediction
- <<") - Name not known"<<std::endl;
- break;
- }
- MapNode n(id);
- try{
- // This triggers the required mesh update too
- client.addNode(p, n);
- }catch(InvalidPositionException &e){
- errorstream<<"Node placement prediction failed for "
- <<playeritem.name<<" (places "
- <<def.node_placement_prediction
- <<") - Position not loaded"<<std::endl;
- }
- }while(0);
- }
- }
- }
- else if(pointed.type == POINTEDTHING_OBJECT)
- {
- infotext = narrow_to_wide(selected_object->infoText());
- if(infotext == L"" && show_debug){
- infotext = narrow_to_wide(selected_object->debugInfoText());
- }
- //if(input->getLeftClicked())
- if(input->getLeftState())
- {
- bool do_punch = false;
- bool do_punch_damage = false;
- if(object_hit_delay_timer <= 0.0){
- do_punch = true;
- do_punch_damage = true;
- object_hit_delay_timer = object_hit_delay;
- }
- if(input->getLeftClicked()){
- do_punch = true;
- }
- if(do_punch){
- infostream<<"Left-clicked object"<<std::endl;
- left_punch = true;
- }
- if(do_punch_damage){
- // Report direct punch
- v3f objpos = selected_object->getPosition();
- v3f dir = (objpos - player_position).normalize();
-
- bool disable_send = selected_object->directReportPunch(
- dir, &playeritem, time_from_last_punch);
- time_from_last_punch = 0;
- if(!disable_send)
- client.interact(0, pointed);
- }
- }
- else if(input->getRightClicked())
- {
- infostream<<"Right-clicked object"<<std::endl;
- client.interact(3, pointed); // place
- }
- }
- else if(input->getLeftState())
- {
- // When button is held down in air, show continuous animation
- left_punch = true;
- }
- pointed_old = pointed;
-
- if(left_punch || input->getLeftClicked())
- {
- camera.setDigging(0); // left click animation
- }
- input->resetLeftClicked();
- input->resetRightClicked();
- input->resetLeftReleased();
- input->resetRightReleased();
-
- /*
- Calculate stuff for drawing
- */
- /*
- Fog range
- */
-
- if(farmesh)
- {
- fog_range = BS*farmesh_range;
- }
- else
- {
- fog_range = draw_control.wanted_range*BS + 0.0*MAP_BLOCKSIZE*BS;
- fog_range *= 0.9;
- if(draw_control.range_all)
- fog_range = 100000*BS;
- }
- /*
- Calculate general brightness
- */
- u32 daynight_ratio = client.getEnv().getDayNightRatio();
- float time_brightness = decode_light_f((float)daynight_ratio/1000.0);
- float direct_brightness = 0;
- bool sunlight_seen = false;
- if(g_settings->getBool("free_move")){
- direct_brightness = time_brightness;
- sunlight_seen = true;
- } else {
- ScopeProfiler sp(g_profiler, "Detecting background light", SPT_AVG);
- float old_brightness = sky->getBrightness();
- direct_brightness = (float)client.getEnv().getClientMap()
- .getBackgroundBrightness(MYMIN(fog_range*1.2, 60*BS),
- daynight_ratio, (int)(old_brightness*255.5), &sunlight_seen)
- / 255.0;
- }
-
- time_of_day = client.getEnv().getTimeOfDayF();
- float maxsm = 0.05;
- if(fabs(time_of_day - time_of_day_smooth) > maxsm &&
- fabs(time_of_day - time_of_day_smooth + 1.0) > maxsm &&
- fabs(time_of_day - time_of_day_smooth - 1.0) > maxsm)
- time_of_day_smooth = time_of_day;
- float todsm = 0.05;
- if(time_of_day_smooth > 0.8 && time_of_day < 0.2)
- time_of_day_smooth = time_of_day_smooth * (1.0-todsm)
- + (time_of_day+1.0) * todsm;
- else
- time_of_day_smooth = time_of_day_smooth * (1.0-todsm)
- + time_of_day * todsm;
-
- sky->update(time_of_day_smooth, time_brightness, direct_brightness,
- sunlight_seen);
-
- float brightness = sky->getBrightness();
- video::SColor bgcolor = sky->getBgColor();
- video::SColor skycolor = sky->getSkyColor();
- /*
- Update clouds
- */
- if(clouds){
- if(sky->getCloudsVisible()){
- clouds->setVisible(true);
- clouds->step(dtime);
- clouds->update(v2f(player_position.X, player_position.Z),
- sky->getCloudColor());
- } else{
- clouds->setVisible(false);
- }
- }
-
- /*
- Update farmesh
- */
- if(farmesh)
- {
- farmesh_range = draw_control.wanted_range * 10;
- if(draw_control.range_all && farmesh_range < 500)
- farmesh_range = 500;
- if(farmesh_range > 1000)
- farmesh_range = 1000;
- farmesh->step(dtime);
- farmesh->update(v2f(player_position.X, player_position.Z),
- brightness, farmesh_range);
- }
-
- /*
- Fog
- */
-
- if(g_settings->getBool("enable_fog") == true && !force_fog_off)
- {
- driver->setFog(
- bgcolor,
- video::EFT_FOG_LINEAR,
- fog_range*0.4,
- fog_range*1.0,
- 0.01,
- false, // pixel fog
- false // range fog
- );
- }
- else
- {
- driver->setFog(
- bgcolor,
- video::EFT_FOG_LINEAR,
- 100000*BS,
- 110000*BS,
- 0.01,
- false, // pixel fog
- false // range fog
- );
- }
- /*
- Update gui stuff (0ms)
- */
- //TimeTaker guiupdatetimer("Gui updating");
-
- const char program_name_and_version[] =
- "Minetest " VERSION_STRING;
- if(show_debug)
- {
- static float drawtime_avg = 0;
- drawtime_avg = drawtime_avg * 0.95 + (float)drawtime*0.05;
- /*static float beginscenetime_avg = 0;
- beginscenetime_avg = beginscenetime_avg * 0.95 + (float)beginscenetime*0.05;
- static float scenetime_avg = 0;
- scenetime_avg = scenetime_avg * 0.95 + (float)scenetime*0.05;
- static float endscenetime_avg = 0;
- endscenetime_avg = endscenetime_avg * 0.95 + (float)endscenetime*0.05;*/
-
- char temptext[300];
- snprintf(temptext, 300, "%s ("
- "R: range_all=%i"
- ")"
- " drawtime=%.0f, dtime_jitter = % .1f %%"
- ", v_range = %.1f, RTT = %.3f",
- program_name_and_version,
- draw_control.range_all,
- drawtime_avg,
- dtime_jitter1_max_fraction * 100.0,
- draw_control.wanted_range,
- client.getRTT()
- );
-
- guitext->setText(narrow_to_wide(temptext).c_str());
- guitext->setVisible(true);
- }
- else if(show_hud || show_chat)
- {
- guitext->setText(narrow_to_wide(program_name_and_version).c_str());
- guitext->setVisible(true);
- }
- else
- {
- guitext->setVisible(false);
- }
-
- if(show_debug)
- {
- char temptext[300];
- snprintf(temptext, 300,
- "(% .1f, % .1f, % .1f)"
- " (yaw = %.1f) (seed = %lli)",
- player_position.X/BS,
- player_position.Y/BS,
- player_position.Z/BS,
- wrapDegrees_0_360(camera_yaw),
- client.getMapSeed());
- guitext2->setText(narrow_to_wide(temptext).c_str());
- guitext2->setVisible(true);
- }
- else
- {
- guitext2->setVisible(false);
- }
-
- {
- guitext_info->setText(infotext.c_str());
- guitext_info->setVisible(show_hud && g_menumgr.menuCount() == 0);
- }
- {
- float statustext_time_max = 1.5;
- if(!statustext.empty())
- {
- statustext_time += dtime;
- if(statustext_time >= statustext_time_max)
- {
- statustext = L"";
- statustext_time = 0;
- }
- }
- guitext_status->setText(statustext.c_str());
- guitext_status->setVisible(!statustext.empty());
- if(!statustext.empty())
- {
- s32 status_y = screensize.Y - 130;
- core::rect<s32> rect(
- 10,
- status_y - guitext_status->getTextHeight(),
- screensize.X - 10,
- status_y
- );
- guitext_status->setRelativePosition(rect);
- // Fade out
- video::SColor initial_color(255,0,0,0);
- if(guienv->getSkin())
- initial_color = guienv->getSkin()->getColor(gui::EGDC_BUTTON_TEXT);
- video::SColor final_color = initial_color;
- final_color.setAlpha(0);
- video::SColor fade_color =
- initial_color.getInterpolated_quadratic(
- initial_color,
- final_color,
- pow(statustext_time / (float)statustext_time_max, 2.0f));
- guitext_status->setOverrideColor(fade_color);
- guitext_status->enableOverrideColor(true);
- }
- }
-
- /*
- Get chat messages from client
- */
- {
- // Get new messages from error log buffer
- while(!chat_log_error_buf.empty())
- {
- chat_backend.addMessage(L"", narrow_to_wide(
- chat_log_error_buf.get()));
- }
- // Get new messages from client
- std::wstring message;
- while(client.getChatMessage(message))
- {
- chat_backend.addUnparsedMessage(message);
- }
- // Remove old messages
- chat_backend.step(dtime);
- // Display all messages in a static text element
- u32 recent_chat_count = chat_backend.getRecentBuffer().getLineCount();
- std::wstring recent_chat = chat_backend.getRecentChat();
- guitext_chat->setText(recent_chat.c_str());
- // Update gui element size and position
- s32 chat_y = 5+(text_height+5);
- if(show_debug)
- chat_y += (text_height+5);
- core::rect<s32> rect(
- 10,
- chat_y,
- screensize.X - 10,
- chat_y + guitext_chat->getTextHeight()
- );
- guitext_chat->setRelativePosition(rect);
- // Don't show chat if disabled or empty or profiler is enabled
- guitext_chat->setVisible(show_chat && recent_chat_count != 0
- && !show_profiler);
- }
- /*
- Inventory
- */
-
- if(client.getPlayerItem() != new_playeritem)
- {
- client.selectPlayerItem(new_playeritem);
- }
- if(client.getLocalInventoryUpdated())
- {
- //infostream<<"Updating local inventory"<<std::endl;
- client.getLocalInventory(local_inventory);
-
- update_wielded_item_trigger = true;
- }
- if(update_wielded_item_trigger)
- {
- update_wielded_item_trigger = false;
- // Update wielded tool
- InventoryList *mlist = local_inventory.getList("main");
- ItemStack item;
- if(mlist != NULL)
- item = mlist->getItem(client.getPlayerItem());
- camera.wield(item);
- }
- /*
- Update block draw list every 200ms or when camera direction has
- changed much
- */
- update_draw_list_timer += dtime;
- if(update_draw_list_timer >= 0.2 ||
- update_draw_list_last_cam_dir.getDistanceFrom(camera_direction) > 0.2){
- update_draw_list_timer = 0;
- client.getEnv().getClientMap().updateDrawList(driver);
- update_draw_list_last_cam_dir = camera_direction;
- }
- /*
- Drawing begins
- */
- TimeTaker tt_draw("mainloop: draw");
-
- {
- TimeTaker timer("beginScene");
- //driver->beginScene(false, true, bgcolor);
- //driver->beginScene(true, true, bgcolor);
- driver->beginScene(true, true, skycolor);
- beginscenetime = timer.stop(true);
- }
-
- //timer3.stop();
-
- //infostream<<"smgr->drawAll()"<<std::endl;
- {
- TimeTaker timer("smgr");
- smgr->drawAll();
-
- if(g_settings->getBool("anaglyph"))
- {
- irr::core::vector3df oldPosition = camera.getCameraNode()->getPosition();
- irr::core::vector3df oldTarget = camera.getCameraNode()->getTarget();
- irr::core::matrix4 startMatrix = camera.getCameraNode()->getAbsoluteTransformation();
- irr::core::vector3df focusPoint = (camera.getCameraNode()->getTarget() -
- camera.getCameraNode()->getAbsolutePosition()).setLength(1) +
- camera.getCameraNode()->getAbsolutePosition() ;
- //Left eye...
- irr::core::vector3df leftEye;
- irr::core::matrix4 leftMove;
- leftMove.setTranslation( irr::core::vector3df(-g_settings->getFloat("anaglyph_strength"),0.0f,0.0f) );
- leftEye=(startMatrix*leftMove).getTranslation();
- //clear the depth buffer, and color
- driver->beginScene( true, true, irr::video::SColor(0,200,200,255) );
- driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_RED;
- driver->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
- driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX +
- irr::scene::ESNRP_SOLID +
- irr::scene::ESNRP_TRANSPARENT +
- irr::scene::ESNRP_TRANSPARENT_EFFECT +
- irr::scene::ESNRP_SHADOW;
- camera.getCameraNode()->setPosition( leftEye );
- camera.getCameraNode()->setTarget( focusPoint );
- smgr->drawAll(); // 'smgr->drawAll();' may go here
- //Right eye...
- irr::core::vector3df rightEye;
- irr::core::matrix4 rightMove;
- rightMove.setTranslation( irr::core::vector3df(g_settings->getFloat("anaglyph_strength"),0.0f,0.0f) );
- rightEye=(startMatrix*rightMove).getTranslation();
- //clear the depth buffer
- driver->clearZBuffer();
- driver->getOverrideMaterial().Material.ColorMask = irr::video::ECP_GREEN + irr::video::ECP_BLUE;
- driver->getOverrideMaterial().EnableFlags = irr::video::EMF_COLOR_MASK;
- driver->getOverrideMaterial().EnablePasses = irr::scene::ESNRP_SKY_BOX +
- irr::scene::ESNRP_SOLID +
- irr::scene::ESNRP_TRANSPARENT +
- irr::scene::ESNRP_TRANSPARENT_EFFECT +
- irr::scene::ESNRP_SHADOW;
- camera.getCameraNode()->setPosition( rightEye );
- camera.getCameraNode()->setTarget( focusPoint );
- smgr->drawAll(); // 'smgr->drawAll();' may go here
- //driver->endScene();
- driver->getOverrideMaterial().Material.ColorMask=irr::video::ECP_ALL;
- driver->getOverrideMaterial().EnableFlags=0;
- driver->getOverrideMaterial().EnablePasses=0;
- camera.getCameraNode()->setPosition( oldPosition );
- camera.getCameraNode()->setTarget( oldTarget );
- }
- scenetime = timer.stop(true);
- }
-
- {
- //TimeTaker timer9("auxiliary drawings");
- // 0ms
-
- //timer9.stop();
- //TimeTaker //timer10("//timer10");
-
- video::SMaterial m;
- //m.Thickness = 10;
- m.Thickness = 3;
- m.Lighting = false;
- driver->setMaterial(m);
- driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
- if(show_hud)
- {
- v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
- u32 selectionbox_color_r = rangelim(myround(selectionbox_color.X), 0, 255);
- u32 selectionbox_color_g = rangelim(myround(selectionbox_color.Y), 0, 255);
- u32 selectionbox_color_b = rangelim(myround(selectionbox_color.Z), 0, 255);
- for(std::vector<aabb3f>::const_iterator
- i = hilightboxes.begin();
- i != hilightboxes.end(); i++)
- {
- /*infostream<<"hilightbox min="
- <<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")"
- <<" max="
- <<"("<<i->MaxEdge.X<<","<<i->MaxEdge.Y<<","<<i->MaxEdge.Z<<")"
- <<std::endl;*/
- driver->draw3DBox(*i, video::SColor(255,selectionbox_color_r,selectionbox_color_g,selectionbox_color_b));
- }
- }
- /*
- Wielded tool
- */
- if(show_hud)
- {
- // Warning: This clears the Z buffer.
- camera.drawWieldedTool();
- }
- /*
- Post effects
- */
- {
- client.getEnv().getClientMap().renderPostFx();
- }
- /*
- Profiler graph
- */
- if(show_profiler_graph)
- {
- graph.draw(10, screensize.Y - 10, driver, font);
- }
- /*
- Draw crosshair
- */
- if(show_hud)
- {
- v3f crosshair_color = g_settings->getV3F("crosshair_color");
- u32 crosshair_color_r = rangelim(myround(crosshair_color.X), 0, 255);
- u32 crosshair_color_g = rangelim(myround(crosshair_color.Y), 0, 255);
- u32 crosshair_color_b = rangelim(myround(crosshair_color.Z), 0, 255);
- u32 crosshair_alpha = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
- driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0),
- displaycenter + core::vector2d<s32>(10,0),
- video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b));
- driver->draw2DLine(displaycenter - core::vector2d<s32>(0,10),
- displaycenter + core::vector2d<s32>(0,10),
- video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b));
- }
- } // timer
- //timer10.stop();
- //TimeTaker //timer11("//timer11");
- /*
- Draw hotbar
- */
- if(show_hud)
- {
- draw_hotbar(driver, font, gamedef,
- v2s32(displaycenter.X, screensize.Y),
- hotbar_imagesize, hotbar_itemcount, &local_inventory,
- client.getHP(), client.getPlayerItem());
- }
- /*
- Damage flash
- */
- if(damage_flash > 0.0)
- {
- video::SColor color(std::min(damage_flash, 180.0f),180,0,0);
- driver->draw2DRectangle(color,
- core::rect<s32>(0,0,screensize.X,screensize.Y),
- NULL);
-
- damage_flash -= 100.0*dtime;
- }
- /*
- Damage camera tilt
- */
- if(player->hurt_tilt_timer > 0.0)
- {
- player->hurt_tilt_timer -= dtime*5;
- if(player->hurt_tilt_timer < 0)
- player->hurt_tilt_strength = 0;
- }
- /*
- Draw gui
- */
- // 0-1ms
- guienv->drawAll();
- /*
- End scene
- */
- {
- TimeTaker timer("endScene");
- endSceneX(driver);
- endscenetime = timer.stop(true);
- }
- drawtime = tt_draw.stop(true);
- g_profiler->graphAdd("mainloop_draw", (float)drawtime/1000.0f);
- /*
- End of drawing
- */
- static s16 lastFPS = 0;
- //u16 fps = driver->getFPS();
- u16 fps = (1.0/dtime_avg1);
- if (lastFPS != fps)
- {
- core::stringw str = L"Minetest [";
- str += driver->getName();
- str += "] FPS=";
- str += fps;
- device->setWindowCaption(str.c_str());
- lastFPS = fps;
- }
- /*
- Log times and stuff for visualization
- */
- Profiler::GraphValues values;
- g_profiler->graphGet(values);
- graph.put(values);
- }
- /*
- Drop stuff
- */
- if(clouds)
- clouds->drop();
- if(gui_chat_console)
- gui_chat_console->drop();
-
- /*
- Draw a "shutting down" screen, which will be shown while the map
- generator and other stuff quits
- */
- {
- /*gui::IGUIStaticText *gui_shuttingdowntext = */
- draw_load_screen(L"Shutting down stuff...", driver, font);
- /*driver->beginScene(true, true, video::SColor(255,0,0,0));
- guienv->drawAll();
- driver->endScene();
- gui_shuttingdowntext->remove();*/
- }
- chat_backend.addMessage(L"", L"# Disconnected.");
- chat_backend.addMessage(L"", L"");
- // Client scope (client is destructed before destructing *def and tsrc)
- }while(0);
- } // try-catch
- catch(SerializationError &e)
- {
- error_message = L"A serialization error occurred:\n"
- + narrow_to_wide(e.what()) + L"\n\nThe server is probably "
- L" running a different version of Minetest.";
- errorstream<<wide_to_narrow(error_message)<<std::endl;
- }
-
- if(!sound_is_dummy)
- delete sound;
- delete tsrc;
- delete shsrc;
- delete nodedef;
- delete itemdef;
- }
|