]> git.lizzy.rs Git - dragonfireclient.git/blob - src/environment.cpp
Added tag working for changeset c37bcfd89dd6
[dragonfireclient.git] / src / environment.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "environment.h"
21 #include "main.h" // g_device for timing debug
22
23 Environment::Environment(Map *map, std::ostream &dout):
24                 m_dout(dout)
25 {
26         m_map = map;
27 }
28
29 Environment::~Environment()
30 {
31         // Deallocate players
32         for(core::list<Player*>::Iterator i = m_players.begin();
33                         i != m_players.end(); i++)
34         {
35                 delete (*i);
36         }
37         
38         delete m_map;
39 }
40
41 void Environment::step(float dtime)
42 {
43         DSTACK(__FUNCTION_NAME);
44         /*
45                 Run Map's timers
46         */
47         //TimeTaker maptimerupdatetimer("m_map->timerUpdate()", g_device);
48         // 0ms
49         m_map->timerUpdate(dtime);
50         //maptimerupdatetimer.stop();
51
52         /*
53                 Get the highest speed some player is going
54         */
55         //TimeTaker playerspeed("playerspeed", g_device);
56         // 0ms
57         f32 maximum_player_speed = 0.001; // just some small value
58         for(core::list<Player*>::Iterator i = m_players.begin();
59                         i != m_players.end(); i++)
60         {
61                 f32 speed = (*i)->getSpeed().getLength();
62                 if(speed > maximum_player_speed)
63                         maximum_player_speed = speed;
64         }
65         //playerspeed.stop();
66         
67         // Maximum time increment (for collision detection etc)
68         // Allow 0.1 blocks per increment
69         // time = distance / speed
70         f32 dtime_max_increment = 0.1*BS / maximum_player_speed;
71         // Maximum time increment is 10ms or lower
72         if(dtime_max_increment > 0.01)
73                 dtime_max_increment = 0.01;
74         
75         //TimeTaker playerupdate("playerupdate", g_device);
76         
77         /*
78                 Stuff that has a maximum time increment
79         */
80         // Don't allow overly huge dtime
81         if(dtime > 0.5)
82                 dtime = 0.5;
83
84         u32 loopcount = 0;
85         do
86         {
87                 loopcount++;
88
89                 f32 dtime_part;
90                 if(dtime > dtime_max_increment)
91                         dtime_part = dtime_max_increment;
92                 else
93                         dtime_part = dtime;
94                 dtime -= dtime_part;
95                 
96                 /*
97                         Handle players
98                 */
99                 for(core::list<Player*>::Iterator i = m_players.begin();
100                                 i != m_players.end(); i++)
101                 {
102                         Player *player = *i;
103                         
104                         // Apply physics to local player
105                         if(player->isLocal())
106                         {
107                                 // Apply gravity to local player
108                                 v3f speed = player->getSpeed();
109                                 speed.Y -= 9.81 * BS * dtime_part * 2;
110
111                                 /*
112                                         Apply water resistance
113                                 */
114                                 if(player->in_water)
115                                 {
116                                         f32 max_down = 1.0*BS;
117                                         if(speed.Y < -max_down) speed.Y = -max_down;
118
119                                         f32 max = 2.0*BS;
120                                         if(speed.getLength() > max)
121                                         {
122                                                 speed = speed / speed.getLength() * max;
123                                         }
124                                 }
125
126                                 player->setSpeed(speed);
127                         }
128
129                         /*
130                                 Move the player.
131                                 For local player, this also calculates collision detection.
132                         */
133                         player->move(dtime_part, *m_map);
134                         
135                         /*
136                                 Add footsteps to grass
137                         */
138                         //TimeTaker footsteptimer("footstep", g_device);
139                         // 0ms
140                         v3f playerpos = player->getPosition();
141                         // Get node that is at BS/4 under player
142                         v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0));
143                         try{
144                                 MapNode n = m_map->getNode(bottompos);
145                                 if(n.d == CONTENT_GRASS)
146                                 {
147                                         n.d = CONTENT_GRASS_FOOTSTEPS;
148                                         m_map->setNode(bottompos, n);
149
150                                         // Update mesh on client
151                                         if(m_map->mapType() == MAPTYPE_CLIENT)
152                                         {
153                                                 v3s16 p_blocks = getNodeBlockPos(bottompos);
154                                                 MapBlock *b = m_map->getBlockNoCreate(p_blocks);
155                                                 b->updateMesh();
156                                         }
157                                 }
158                         }
159                         catch(InvalidPositionException &e)
160                         {
161                         }
162                         //footsteptimer.stop();
163                 }
164         }
165         while(dtime > 0.001);
166         
167         //std::cout<<"Looped "<<loopcount<<" times."<<std::endl;
168 }
169
170 Map & Environment::getMap()
171 {
172         return *m_map;
173 }
174
175 void Environment::addPlayer(Player *player)
176 {
177         DSTACK(__FUNCTION_NAME);
178         //Check that only one local player exists and peer_ids are unique
179         assert(player->isLocal() == false || getLocalPlayer() == NULL);
180         assert(getPlayer(player->peer_id) == NULL);
181         m_players.push_back(player);
182 }
183
184 void Environment::removePlayer(u16 peer_id)
185 {
186         DSTACK(__FUNCTION_NAME);
187 re_search:
188         for(core::list<Player*>::Iterator i = m_players.begin();
189                         i != m_players.end(); i++)
190         {
191                 Player *player = *i;
192                 if(player->peer_id != peer_id)
193                         continue;
194                 
195                 delete player;
196                 m_players.erase(i);
197                 // See if there is an another one
198                 // (shouldn't be, but just to be sure)
199                 goto re_search;
200         }
201 }
202
203 LocalPlayer * Environment::getLocalPlayer()
204 {
205         for(core::list<Player*>::Iterator i = m_players.begin();
206                         i != m_players.end(); i++)
207         {
208                 Player *player = *i;
209                 if(player->isLocal())
210                         return (LocalPlayer*)player;
211         }
212         return NULL;
213 }
214
215 Player * Environment::getPlayer(u16 peer_id)
216 {
217         for(core::list<Player*>::Iterator i = m_players.begin();
218                         i != m_players.end(); i++)
219         {
220                 Player *player = *i;
221                 if(player->peer_id == peer_id)
222                         return player;
223         }
224         return NULL;
225 }
226
227 core::list<Player*> Environment::getPlayers()
228 {
229         return m_players;
230 }
231
232 void Environment::printPlayers(std::ostream &o)
233 {
234         o<<"Players in environment:"<<std::endl;
235         for(core::list<Player*>::Iterator i = m_players.begin();
236                         i != m_players.end(); i++)
237         {
238                 Player *player = *i;
239                 o<<"Player peer_id="<<player->peer_id<<std::endl;
240         }
241 }
242