aboutsummaryrefslogtreecommitdiff
path: root/misc/minetest-icon.ico
blob: 82af67bf918ad7683dfc7b63da97757d8b37d23c (plain)
ofshex dumpascii
0000 00 00 01 00 01 00 30 30 00 00 01 00 20 00 a8 25 00 00 16 00 00 00 28 00 00 00 30 00 00 00 60 00 ......00.......%......(...0...`.
0020 00 00 01 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d 39 59 28 0f 3f ...........................9Y(.?
0160 5c 95 0d 3c 57 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \..<W&..........................
0180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
01a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
01c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
01e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 40 50 10 11 3f 5e 95 12 3f 5e f5 33 6c ...................@P..?^..?^.3l
0220 91 f9 11 3e 5d f5 10 3d 5a 8d 15 40 55 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...>]..=Z..@U...................
0240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
02a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
02c0 00 00 00 00 00 00 00 00 00 00 00 00 00 01 0f 3b 59 56 11 40 5d eb 2b 62 85 f7 63 aa d8 ff 6e b9 ...............;YV.@].+b..c...n.
02e0 e9 ff 62 a9 d7 ff 27 5d 7e f6 10 3f 5d e8 0d 3c 56 4d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..b...']~..?]..<VM..............
0300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0380 00 00 00 00 00 00 0f 3b 58 34 13 42 61 d3 1d 50 70 f5 58 9c c8 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 .......;X4.Ba..Pp.X...n...n...n.
03a0 e9 ff 6e b9 e9 ff 6e b9 e9 ff 53 95 c0 ff 18 48 69 f4 12 41 60 c1 0e 37 5a 25 00 00 00 00 00 00 ..n...n...S....Hi..A`..7Z%......
03c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
03e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2c 35 ..............................,5
0440 38 57 34 36 33 f2 15 44 61 f5 47 86 af fe 6d b8 e8 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 8W463..Da.G...m...n...n...n...n.
0460 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6b b6 e6 ff 41 7d a4 fd 12 40 5d f6 13 42 60 88 17 46 ..n...n...n...k...A}...@]..B`..F
0480 5d 0b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]...............................
04a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
04c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
04e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 30 30 38 20 33 35 32 e5 38 36 ......................008.352.86
0500 2f ff 36 34 2e ff 69 b3 e1 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 /.64..i...n...n...n...n...n...n.
0520 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 65 ad dc ff 2d 65 88 f7 11 40 ..n...n...n...n...n...e...-e...@
0540 5e ec 0c 3b 59 56 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ^..;YV..........................
0560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0580 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
05a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 31 36 36 bd 37 35 30 ff 41 40 3c ff 4c 4f ..................166.750.A@<.LO
05c0 4c ff 36 34 2e ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 69 a4 c8 ff 5c 6c L.64..n...n...n...n...n...i...\l
05e0 71 ff 69 a4 ca ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 58 9c q.i...n...n...n...n...n...n...X.
0600 c8 ff 1c 4e 6e f4 12 40 60 cf 0a 39 58 31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...Nn..@`..9X1..................
0620 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0660 00 00 00 00 00 00 00 00 00 00 2d 35 39 82 36 36 30 fe 3b 3b 35 ff 4e 50 4d ff 43 44 40 ff 38 36 ..........-59.660.;;5.NPM.CD@.86
0680 2f ff 47 5b 65 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6c b0 db ff 5d 6b 71 ff 52 3b 25 ff 7e 5e /.G[e.n...n...n...l...]kq.R;%.~^
06a0 40 ff 51 3a 25 ff 5d 6f 77 ff 6c b2 de ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 @.Q:%.]ow.l...n...n...n...n...n.
06c0 e9 ff 6d b8 e7 ff 45 81 a9 fd 12 40 5e f6 11 41 5d 99 1c 39 4c 1b 00 00 00 00 00 00 00 00 00 00 ..m...E....@^..A]..9L...........
06e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
0720 00 00 2b 37 37 41 35 36 33 f5 39 37 31 ff 49 4b 48 ff 53 57 55 ff 53 57 55 ff 36 34 2e ff 61 97 ..+77A563.971.IKH.SWU.SWU.64..a.
0740 bb ff 6e b9 e9 ff 6e b9 e9 ff 6e b8 e8 ff 63 8b a3 ff 54 40 2d ff 74 57 3a ff c0 92 68 ff cf 9f ..n...n...n...c...T@-.tW:...h...
0760 72 ff be 91 67 ff 6f 52 38 ff 53 42 2f ff 64 90 aa ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 r...g.oR8.SB/.d...n...n...n...n.
0780 e9 ff 6e b9 e9 ff 6e b9 e9 ff 66 af de ff 32 6a 8e f7 33 36 33 fd 27 37 41 95 00 00 80 02 00 00 ..n...n...f...2j..363.'7A.......
07a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
07c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 31 3d 15 31 34 ..........................$1=.14
07e0 35 dc 37 35 2f ff 43 44 40 ff 52 56 54 ff 53 57 55 ff 53 57 55 ff 51 55 53 ff 36 34 2e ff 69 ad 5.75/.CD@.RVT.SWU.SWU.QUS.64..i.
0800 d8 ff 6e b9 e9 ff 67 9e c1 ff 57 47 38 ff 6a 4e 35 ff b8 8b 62 ff cf 9f 72 ff cf 9f 72 ff cf 9f ..n...g...WG8.jN5...b...r...r...
0820 72 ff cf 9f 72 ff cf 9f 72 ff b2 86 5f ff 62 48 30 ff 59 4f 43 ff 67 9e c1 ff 6e b9 e9 ff 6e b9 r...r...r..._.bH0.YOC.g...n...n.
0840 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 36 34 2e ff 40 41 3d fe 33 3a 3a f6 21 37 ..n...n...n...n...64..@A=.3::.!7
0860 43 5c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C\..............................
0880 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 2e 34 36 ab 37 35 30 ff 3f 3f .......................46.750.??
08a0 3a ff 50 52 51 ff 53 57 55 ff 53 57 55 ff 52 56 54 ff 48 4a 46 ff 38 36 31 ff 3d 43 44 ff 6d b5 :.PRQ.SWU.SWU.RVT.HJF.861.=CD.m.
08c0 e3 ff 6e b9 e9 ff 5e 7c 8b ff 7b 5b 3d ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f ..n...^|..{[=...r...r...r...r...
08e0 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff ce 9e 71 ff 9a 73 50 ff 54 3c 27 ff 5c 68 6b ff 6c af r...r...r...r...q..sP.T<'.\hk.l.
0900 da ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 36 34 2e ff 83 88 86 ff 5f 62 5e ff 39 39 ..n...n...n...n...64......_b^.99
0920 35 ff 2c 3b 42 db 20 39 46 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5.,;B..9F(......................
0940 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0d 3c 57 26 13 43 60 bf 36 34 2e ff 37 35 30 ff 3e 3e ...............<W&.C`.64..750.>>
0960 3a ff 50 53 50 ff 53 57 55 ff 4c 50 4c ff 3b 3a 34 ff 38 35 30 ff 58 88 a4 ff 6e b9 e9 ff 6e b9 :.PSP.SWU.LPL.;:4.850.X...n...n.
0980 e9 ff 6e b9 e9 ff 5b 72 7c ff 84 63 44 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f ..n...[r|..cD...r...r...r...r...
09a0 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff c6 97 6c ff 81 60 42 ff 52 3c r...r...r...r...r...r...l..`B.R<
09c0 26 ff 60 80 90 ff 6e b8 e6 ff 6e b9 e9 ff 6e b9 e9 ff 36 34 2e ff 85 8a 88 ff 85 8a 88 ff 7e 83 &.`...n...n...n...64..........~.
09e0 81 ff 52 55 53 ff 37 38 33 fe 29 39 41 aa 1c 39 55 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..RUS.783.)9A..9U...............
0a00 00 00 00 00 00 00 00 55 55 03 13 43 61 a3 13 42 60 f6 47 86 ae fe 36 34 2e ff 36 34 2e ff 36 34 .......UU..Ca..B`.G...64..64..64
0a20 2e ff 37 35 2f ff 3c 3c 37 ff 37 35 2f ff 36 34 2e ff 36 34 2e ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 ..75/.<<7.75/.64..64..n...n...n.
0a40 e9 ff 59 58 53 ff 59 42 2a ff af 84 5c ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f ..YXS.YB*...\...r...r...r...r...
0a60 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff b7 8c r...r...r...r...r...r...r...r...
0a80 62 ff 68 4e 34 ff 56 49 39 ff 66 99 b7 ff 6e b9 e9 ff 36 34 2e ff 69 6d 6a ff 84 89 87 ff 85 8a b.hN4.VI9.f...n...64..imj.......
0aa0 88 ff 85 8a 88 ff 7a 7e 7b ff 49 4c 49 fe 35 38 36 fd 26 35 3e 87 00 00 00 00 00 00 00 00 00 00 ......z~{.ILI.586.&5>...........
0ac0 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fc 68 b1 df ff 6e b9 e9 ff 36 34 2e ff 36 34 2e ff 36 34 .......9U..<Y.h...n...64..64..64
0ae0 2e ff 36 34 2e ff 36 34 2e ff 35 33 34 ff 36 34 31 ff 36 34 2e ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 ..64..64..534.641.64..n...n...n.
0b00 e9 ff 4b 31 19 ff cc 9c 70 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f ..K1....p...r...r...r...r...r...
0b20 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f r...r...r...r...r...r...r...r...
0b40 72 ff cf 9f 72 ff a2 7a 54 ff 57 3f 28 ff 5c 60 5c ff 60 99 bb ff 42 4d 4f ff 48 49 46 ff 85 8a r...r..zT.W?(.\`\.`...BMO.HIF...
0b60 88 ff 85 8a 88 ff 85 8a 88 ff 85 8a 88 ff 70 73 6f ff 36 34 2e ff 00 00 00 00 00 00 00 00 00 00 ..............pso.64............
0b80 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 36 34 2e ff 36 34 2e ff 36 34 .......9U..<Y.n...n...64..64..64
0ba0 2e ff 36 34 2e ff 36 34 2e ff 34 32 4a ff 36 34 3a ff 36 34 2e ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 ..64..64..42J.64:.64..n...n...n.
0bc0 e9 ff 4b 31 19 ff bb 8e 64 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f ..K1....d...r...r...r...r...r...
0be0 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f r...r...r...r...r...r...r...r...
0c00 72 ff cf 9f 72 ff cf 9f 72 ff c9 9a 6e ff 4b 31 19 ff 6e b9 e9 ff 6d b8 e7 ff 36 34 2e ff 85 8a r...r...r...n.K1..n...m...64....
0c20 88 ff 85 8a 88 ff 85 8a 88 ff 85 8a 88 ff 85 8a 88 ff 36 34 2e ff 00 00 00 00 00 00 00 00 00 00 ..................64............
0c40 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 36 34 2e ff 36 34 2e ff 36 34 .......9U..<Y.n...n...64..64..64
0c60 2e ff 36 34 2e ff 36 34 2e ff 36 34 2e ff 38 39 36 ff 40 4c 50 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 ..64..64..64..896.@LP.n...n...n.
0c80 e9 ff 61 7c 89 ff 53 3c 26 ff 82 60 41 ff c6 97 6c ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f ..a|..S<&..`A...l...r...r...r...
0ca0 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f r...r...r...r...r...r...r...r...
0cc0 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff 4b 31 19 ff 6c b3 e0 ff 6e b9 e9 ff 36 34 2e ff 74 78 r...r...r...r.K1..l...n...64..tx
0ce0 75 ff 85 8a 88 ff 85 8a 88 ff 85 8a 88 ff 85 8a 88 ff 36 34 2e ff 00 00 00 00 00 00 00 00 00 00 u.................64............
0d00 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 36 34 2e ff 38 39 36 ff 36 34 .......9U..<Y.n...n...64..896.64
0d20 2e ff 36 34 2e ff 38 38 34 ff 3a 3e 3c ff 5a 8a a6 ff 6e b8 e8 ff 6e b9 e9 ff 6e b9 e9 ff 5e ab ..64..884.:><.Z...n...n...n...^.
0d40 cd ff 3a 89 8a ff 5d a1 bf ff 5e 6a 6d ff 53 3c 25 ff 95 6f 4c ff cc 9d 70 ff cf 9f 72 ff cf 9f ..:...]...^jm.S<%..oL...p...r...
0d60 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f r...r...r...r...r...r...r...r...
0d80 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff 76 5a 3e ff 53 3f 2b ff 61 87 9c ff 59 87 a2 ff 3d 40 r...r...r...r.vZ>.S?+.a...Y...=@
0da0 3e ff 52 55 52 ff 85 8a 88 ff 85 8a 88 ff 85 8a 88 ff 36 34 2e ff 00 00 00 00 00 00 00 00 00 00 >.RUR.............64............
0dc0 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 3f 4a 4e ff 60 98 bb ff 36 34 .......9U..<Y.n...n...?JN.`...64
0de0 2e ff 38 39 35 ff 52 74 88 ff 6c b4 e2 ff 6e b9 e9 ff 6e b9 e9 ff 69 b3 de ff 35 85 82 ff 0e 64 ..895.Rt..l...n...n...i...5....d
0e00 3d ff 12 8c 51 ff 0e 64 3d ff 33 84 7f ff 63 9e bd ff 5a 58 50 ff 5b 43 2b ff a7 7d 57 ff cf 9f =...Q..d=.3...c...ZXP.[C+..}W...
0e20 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f r...r...r...r...r...r...r...r...
0e40 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff b3 87 5f ff 4b 31 19 ff 6e b9 e9 ff 6b b3 r...r...r...r...r..._.K1..n...k.
0e60 e1 ff 36 34 2e ff 7d 81 7f ff 85 8a 88 ff 85 8a 88 ff 36 34 2e ff 00 00 00 00 00 00 00 00 00 00 ..64..}...........64............
0e80 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 6d b8 e7 ff 6e b9 e9 ff 49 61 .......9U..<Y.n...n...m...n...Ia
0ea0 6e ff 68 ab d4 ff 6e b9 e9 ff 6e b9 e9 ff 6e b8 e8 ff 4c 99 ac ff 13 68 45 ff 11 82 4c ff 14 c4 n.h...n...n...n...L....hE...L...
0ec0 6b ff 16 d2 73 ff 15 c7 6d ff 12 85 4f ff 10 65 40 ff 48 97 a4 ff 64 93 af ff 56 48 37 ff 69 4f k...s...m...O..e@.H...d...VH7.iO
0ee0 35 ff b7 8b 62 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 5...b...r...r...r...r...r...r...
0f00 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff b3 87 5f ff 4b 31 19 ff 6e b8 e8 ff 6e b9 r...r...r...r...r..._.K1..n...n.
0f20 e9 ff 52 73 85 ff 3c 3c 37 ff 5f 61 5d ff 83 88 85 ff 36 34 2e ff 00 00 00 00 00 00 00 00 00 00 ..Rs..<<7._a].....64............
0f40 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 .......9U..<Y.n...n...n...n...n.
0f60 e9 ff 6e b9 e9 ff 6e b9 e9 ff 5a a7 c5 ff 1c 72 57 ff 10 72 45 ff 13 b6 64 ff 16 d2 73 ff 16 d2 ..n...n...Z....rW..rE...d...s...
0f80 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 14 bb 66 ff 12 78 49 ff 18 6d 4f ff 53 9f b7 ff 62 81 s...s...s...s...f..xI..mO.S...b.
0fa0 92 ff 53 3c 27 ff 7d 5d 3e ff c3 95 6a ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f 72 ff cf 9f ..S<'.}]>...j...r...r...r...r...
0fc0 72 ff cf 9f 72 ff cf 9f 72 ff c1 93 69 ff 77 58 3b ff 4d 3a 22 ff 29 5b 59 ff 1a 71 83 ff 58 a6 r...r...r...i.wX;.M:".)[Y..q..X.
0fe0 ce ff 6e b9 e9 ff 67 a8 d1 ff 4a 5c 64 ff 40 41 3d ff 36 34 2e ff 00 00 00 00 00 00 00 00 00 00 ..n...g...J\d.@A=.64............
1000 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6e b9 .......9U..<Y.n...n...n...n...n.
1020 e9 ff 66 b1 db ff 31 84 7d ff 0e 66 3f ff 12 a2 5a ff 16 d1 72 ff 16 d2 73 ff 16 d2 73 ff 16 d2 ..f...1.}..f?...Z...r...s...s...
1040 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 12 aa 5e ff 10 6b 42 ff 27 7c s...s...s...s...s...s...^..kB.'|
1060 6a ff 5d a0 bd ff 5d 66 68 ff 55 3c 26 ff 9a 73 4f ff cc 9d 70 ff cf 9f 72 ff cf 9f 72 ff cf 9f j.]...]fh.U<&..sO...p...r...r...
1080 72 ff cc 9d 70 ff 94 6f 4c ff 4f 37 20 ff 41 61 58 ff 4c d9 e9 ff 4e e8 fb ff 31 b1 c0 ff 0b 64 r...p..oL.O7..AaX.L...N...1....d
10a0 70 ff 2b 80 97 ff 64 b0 dd ff 6e b9 e9 ff 5f 96 b8 ff 30 38 36 ff 00 00 00 00 00 00 00 00 00 00 p.+...d...n..._...086...........
10c0 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 6e b9 e9 ff 6c b7 e5 ff 41 90 .......9U..<Y.n...n...n...l...A.
10e0 98 ff 0e 63 3c ff 11 8e 51 ff 15 cb 70 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 ...c<...Q...p...s...s...s...s...
1100 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 15 ce 71 ff 11 99 s...s...s...s...s...s...s...q...
1120 56 ff 0e 65 3d ff 36 88 85 ff 63 9c ba ff 59 54 4a ff 5d 45 2d ff ac 82 5b ff cf 9f 72 ff a7 7e V..e=.6...c...YTJ.]E-...[...r..~
1140 58 ff 56 3e 25 ff 47 49 39 ff 47 bc c7 ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 4b e1 X.V>%.GI9.G...O...O...O...O...K.
1160 f3 ff 26 9a a8 ff 0a 61 6d ff 3c 8d aa ff 6b b7 e6 ff 03 57 61 ff 00 00 00 00 00 00 00 00 00 00 ..&....am.<...k....Wa...........
1180 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 6e b9 e9 ff 6e b9 e9 ff 53 a0 b8 ff 16 6c 4b ff 10 7a .......9U..<Y.n...n...S....lK..z
11a0 48 ff 13 bf 69 ff 16 d2 73 ff 16 d2 73 ff 16 d1 73 ff 0f a7 7d ff 11 b9 79 ff 16 d2 73 ff 16 d2 H...i...s...s...s...}...y...s...
11c0 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 s...s...s...s...s...s...s...s...
11e0 73 ff 15 c8 6d ff 11 8a 50 ff 10 65 40 ff 45 94 9f ff 64 97 b3 ff 57 4b 3c ff 52 3a 22 ff 4a 41 s...m...P..e@.E...d...WK<.R:".JA
1200 2e ff 41 a5 ac ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 3e c9 cd ff 35 bb b7 ff 4f e8 fb ff 4f e9 ..A...O...O...O...>...5...O...O.
1220 fc ff 4f e9 fc ff 44 d4 e6 ff 1b 82 90 ff 10 68 76 ff 02 58 62 ff 00 00 00 00 00 00 00 00 00 00 ..O...D........hv..Xb...........
1240 00 00 00 00 00 00 00 39 55 09 0f 3c 59 fb 5f ab cd ff 22 78 61 ff 0f 6c 41 ff 13 af 61 ff 16 d2 .......9U..<Y._..."xa..lA...a...
1260 73 ff 16 d2 73 ff 16 d2 73 ff 13 c0 77 ff 06 6e 8d ff 06 64 96 ff 04 60 92 ff 09 82 88 ff 15 ce s...s...s...w..n...d...`........
1280 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 s...s...s...s...s...s...s...s...
12a0 73 ff 16 d2 73 ff 16 d2 73 ff 14 be 68 ff 11 7a 4a ff 16 6c 4c ff 53 9f b7 ff 13 4f 52 ff 4e e6 s...s...s...h..zJ..lL.S....OR.N.
12c0 f9 ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 1c 8d 71 ff 07 69 3a ff 07 6f 3e ff 12 7c 58 ff 4f e9 ..O...O...O.....q..i:..o>..|X.O.
12e0 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 3b c2 d3 ff 02 58 62 ff 00 00 00 00 00 00 00 00 00 00 ..O...O...O...;....Xb...........
1300 00 00 00 00 00 00 00 33 4d 0a 0b 53 44 fe 0d 65 3c ff 11 a3 5a ff 16 d1 72 ff 16 d2 73 ff 16 d2 .......3M..SD..e<...Z...r...s...
1320 73 ff 16 d2 73 ff 16 d2 73 ff 0f a5 7e ff 07 67 9c ff 11 7d c1 ff 10 7b bf ff 03 5e 90 ff 14 c7 s...s...s...~..g...}...{...^....
1340 76 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 v...s...s...s...s...s...s...s...
1360 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 13 b5 63 ff 0d 69 3e ff 08 5f 40 ff 4f e9 s...s...s...s...s...c..i>.._@.O.
1380 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 04 60 31 ff 06 97 4d ff 06 9a 4d ff 04 60 31 ff 4f e9 ..O...O...O....`1...M...M..`1.O.
13a0 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 3b c2 d3 ff 03 59 64 ff 00 00 00 00 00 00 00 00 00 00 ..O...O...O...;....Yd...........
13c0 00 00 00 00 00 00 00 55 55 03 0d 5a 42 da 0a 61 37 ff 12 a1 59 ff 16 d1 73 ff 16 d2 73 ff 16 d2 .......UU..ZB..a7...Y...s...s...
13e0 73 ff 16 d2 73 ff 16 d2 73 ff 0f a5 7e ff 08 6a 9e ff 11 7d c1 ff 11 7d c1 ff 04 5f 91 ff 14 c7 s...s...s...~..j...}...}..._....
1400 76 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 v...s...s...s...s...s...s...s...
1420 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 15 c7 6d ff 0f 86 4c ff 0a 61 39 ff 25 95 8f ff 4f e9 s...s...s...s...m...L..a9.%...O.
1440 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 04 60 31 ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 4f e9 ..O...O...O....`1...N...N..`1.O.
1460 fc ff 4f e9 fc ff 44 d4 e6 ff 18 80 8d fe 07 5e 69 fd 08 4c 5d 83 00 00 00 00 00 00 00 00 00 00 ..O...D........^i..L]...........
1480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 4c 42 68 0a 5c 3b f8 0d 6f 40 fe 14 ba 66 ff 16 d2 ...............LBh.\;..o@...f...
14a0 73 ff 16 d2 73 ff 16 d2 73 ff 0f a5 7e ff 08 6a 9d ff 0c 72 8d ff 0e 77 a3 ff 04 5f 91 ff 14 c7 s...s...s...~..j...r...w..._....
14c0 76 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 v...s...s...s...s...s...s...s...
14e0 73 ff 16 d2 73 ff 16 d0 72 ff 12 a1 5a ff 0a 62 38 ff 12 73 5c ff 43 d2 df ff 4f e9 fc ff 4f e9 s...s...r...Z..b8..s\.C...O...O.
1500 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 04 60 31 ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 4c e4 ..O...O...O....`1...N...N..`1.L.
1520 f6 ff 2b a3 b2 ff 06 5d 69 ff 08 53 62 cb 0b 4e 64 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ..+....]i..Sb..Nd...............
1540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 40 04 0b 4f 41 a4 0a 5e 38 fe 0f 86 ...................@@..OA..^8...
1560 4d ff 15 c6 6c ff 16 d2 73 ff 0d 96 6e ff 05 65 44 ff 05 6b 3c ff 05 65 38 ff 04 62 52 ff 12 bd M...l...s...n..eD..k<..e8..bR...
1580 70 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 p...s...s...s...s...s...s...s...
15a0 73 ff 12 b3 63 ff 0b 6a 3d ff 0c 63 44 ff 39 bd c6 ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 s...c..j=..cD.9...O...O...O...O.
15c0 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 04 60 31 ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 08 60 ..O...O...O....`1...N...N..`1..`
15e0 6b fe 08 56 66 e7 0a 43 5b 35 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 k..Vf..C[5......................
1600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 43 4e 17 0b 52 ...........................CN..R
1620 42 ca 08 5e 35 ff 09 77 40 ff 05 66 35 ff 05 81 41 ff 06 99 4e ff 06 96 4c ff 04 76 3e ff 05 69 B..^5..w@..f5...A...N...L..v>..i
1640 36 ff 0f a7 5b ff 16 d1 72 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 10 9a 6...[...r...s...s...s...s...s...
1660 55 ff 0a 5c 33 ff 3c 84 93 ff 1f 54 75 ff 1a 59 75 ff 40 c2 d7 ff 4f e9 fc ff 4f e9 fc ff 4f e9 U..\3.<....Tu..Yu.@...O...O...O.
1680 fc ff 4f e9 fc ff 4f e9 fc ff 4f e9 fc ff 04 60 31 ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 05 49 ..O...O...O....`1...N...N..`1..I
16a0 5d 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ]e..............................
16c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 40 04 05 61 ............................@..a
16e0 33 69 04 62 32 f4 05 76 3c ff 06 96 4c ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 90 3i.b2..v<...L...N...N...N...N...
1700 49 ff 05 72 3a ff 06 72 3b ff 11 b5 62 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 15 c7 I..r:..r;...b...s...s...s...s...
1720 6d ff 0f 82 4b ff 0a 5d 38 ff 31 78 81 ff 49 8b b2 ff 15 47 64 ff 24 75 8f ff 48 d6 ea ff 4f e9 m...K..]8.1x..I....Gd.$u..H...O.
1740 fc ff 4f e9 fc ff 4f e9 fc ff 49 df f0 ff 04 60 31 ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 00 00 ..O...O...I....`1...N...N..`1...
1760 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1780 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 62 2f 51 03 63 33 e8 05 71 .......................b/Q.c3..q
17a0 39 f6 06 92 4b ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 9...K...N...N...N...N...N...N...
17c0 4e ff 06 9a 4e ff 05 8a 46 ff 05 6c 37 ff 09 7f 42 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 N...N...F..l7...B...s...s...s...
17e0 73 ff 16 d2 73 ff 13 b5 63 ff 0c 6d 3e ff 0f 60 43 ff 47 8d a9 ff 34 6f 93 ff 12 44 61 ff 33 9b s...s...c..m>..`C.G...4o...Da.3.
1800 b3 ff 4b e2 f6 ff 2d a7 b8 ff 06 5d 68 ff 04 60 31 ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 00 00 ..K...-....]h..`1...N...N..`1...
1820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 60 31 ff 05 8b 47 ff 06 9a .......................`1...G...
1860 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a N...N...N...N...N...N...N...N...
1880 4e ff 06 9a 4e ff 06 9a 4e ff 06 99 4d ff 04 60 31 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 N...N...N...M..`1...s...s...s...
18a0 73 ff 16 d2 73 ff 16 d2 73 ff 16 d1 73 ff 11 9e 57 ff 0a 60 37 ff 18 65 57 ff 52 96 bc ff 2b 62 s...s...s...s...W..`7..eW.R...+b
18c0 84 ff 10 44 5f ff 09 57 67 ed 08 48 5b 43 04 60 31 ff 05 95 4c ff 06 9a 4d ff 04 60 31 ff 00 00 ...D_..Wg..H[C.`1...L...M..`1...
18e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 60 31 ff 06 9a 4e ff 06 9a .......................`1...N...
1920 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a N...N...N...N...N...N...N...N...
1940 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 N...N...N...N..`1...s...s...s...
1960 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 cb 6f ff 0f 8c 4e ff 0a 5e 36 ff 26 6e s...s...s...s...s...o...N..^6.&n
1980 70 ff 0d 3b 56 ff 00 00 00 00 00 00 00 00 04 61 32 90 04 62 33 f6 04 69 36 f2 04 63 33 cf 00 00 p..;V..........a2..b3..i6..c3...
19a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
19c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 60 31 ff 06 9a 4e ff 06 9a .......................`1...N...
19e0 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a N...N...N...N...N...N...N...N...
1a00 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 N...N...N...N..`1...s...s...s...
1a20 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 14 c3 6b ff 0b 69 s...s...s...s...s...s...s...k..i
1a40 3a fe 0a 59 39 fe 00 00 00 00 00 00 00 00 00 00 00 00 04 5e 31 39 03 61 32 57 00 00 00 01 00 00 :..Y9..............^19.a2W......
1a60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1a80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 60 31 ff 06 9a 4e ff 06 9a .......................`1...N...
1aa0 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a N...N...N...N...N...N...N...N...
1ac0 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 14 bd 68 ff 16 d2 73 ff 16 d2 73 ff 16 d2 N...N...N...N..`1...h...s...s...
1ae0 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 14 bb 67 ff 0c 73 40 f3 09 62 s...s...s...s...s...s...g..s@..b
1b00 35 da 0a 57 39 4c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5..W9L..........................
1b20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1b40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 60 31 ff 06 9a 4e ff 06 9a .......................`1...N...
1b60 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a N...N...N...N...N...N...N...N...
1b80 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 09 5d 35 ff 11 93 54 ff 15 cc 70 ff 16 d2 N...N...N...N..`1..]5...T...p...
1ba0 73 ff 16 d2 73 ff 16 d2 73 ff 16 d2 73 ff 16 ca 6e ff 0f 91 4f f6 09 60 35 f2 08 5b 33 79 00 55 s...s...s...s...n...O..`5..[3y.U
1bc0 2b 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +...............................
1be0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1c00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 60 31 ff 06 9a 4e ff 06 9a .......................`1...N...
1c20 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a N...N...N...N...N...N...N...N...
1c40 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 0d 51 43 26 0c 59 3f dc 0a 61 37 ff 11 a5 N...N...N...N..`1..QC&.Y?..a7...
1c60 5b ff 16 d1 72 ff 16 d1 72 ff 11 a6 5a fc 09 62 35 f5 09 5f 35 a7 0c 5d 2e 16 00 00 00 00 00 00 [...r...r...Z..b5.._5..]........
1c80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1ca0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1cc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 60 31 ff 06 9a 4e ff 06 9a .......................`1...N...
1ce0 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a N...N...N...N...N...N...N...N...
1d00 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 04 60 31 ff 00 00 00 00 00 00 00 00 0a 4d 43 4c 0b 5e N...N...N...N..`1..........MCL.^
1d20 38 da 0a 68 3a f3 0a 67 39 f3 09 61 35 bd 07 5e 2f 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 8..h:..g9..a5..^/&..............
1d40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1d60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1d80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 60 31 ff 05 8b 47 ff 06 9a .......................`1...G...
1da0 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a N...N...N...N...N...N...N...N...
1dc0 4e ff 06 9a 4e ff 06 9a 4e ff 06 99 4d ff 04 60 31 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 N...N...N...M..`1...............
1de0 00 00 0a 5a 34 4a 07 5c 34 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...Z4J.\4E......................
1e00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1e20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1e40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 62 2f 51 03 63 33 e8 05 71 .......................b/Q.c3..q
1e60 39 f5 06 92 4b ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 9...K...N...N...N...N...N...N...
1e80 4e ff 06 9a 4e ff 05 8a 46 ff 04 67 34 f4 04 64 32 c1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 N...N...F..g4..d2...............
1ea0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1ec0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1ee0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1f00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 62 27 0d 04 62 ...........................b'..b
1f20 32 8f 04 63 33 f5 05 81 40 fa 06 98 4d ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 06 9a 4e ff 05 94 2..c3...@...M...N...N...N...N...
1f40 4a ff 05 74 3a f5 04 62 33 ed 03 61 30 5f 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 J..t:..b3..a0_..................
1f60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1f80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1fa0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1fc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
1fe0 00 00 08 5d 2e 21 04 62 32 bd 04 66 34 f5 05 88 45 ff 06 9a 4e ff 06 98 4d ff 05 7e 40 fa 04 63 ...].!.b2..f4...E...N...M..~@..c
2000 33 f5 04 61 33 86 00 55 39 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3..a3..U9.......................
2020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
20a0 00 00 00 00 00 00 00 00 00 00 05 61 33 37 04 64 33 d4 04 69 36 f2 04 63 33 f4 03 62 31 a6 00 60 ...........a37.d3..i6..c3..b1..`
20c0 35 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5...............................
20e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 5f 30 5b 05 60 30 35 00 00 00 00 00 00 ..................._0[.`05......
2180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
21a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
21c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
21e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
22a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
22c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
22e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
23a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
23c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
23e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
2420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ................................
2440 ff ff ff ff 00 00 ff ff ff 7f ff ff 00 00 ff ff fc 1f ff ff 00 00 ff ff f8 0f ff ff 00 00 ff ff ................................
2460 e0 03 ff ff 00 00 ff ff 80 00 ff ff 00 00 ff fe 00 00 7f ff 00 00 ff f8 00 00 1f ff 00 00 ff e0 ................................
2480 00 00 07 ff 00 00 ff c0 00 00 01 ff 00 00 ff 00 00 00 00 ff 00 00 fc 00 00 00 00 3f 00 00 f8 00 ...........................?....
24a0 00 00 00 0f 00 00 e0 00 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 ................................
24c0 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 ................................
24e0 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 ................................
2500 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 e0 00 00 00 00 03 00 00 f8 00 00 00 00 0f 00 00 fc 00 ................................
2520 00 00 00 3f 00 00 ff 00 00 00 00 ff 00 00 ff 80 00 00 00 ff 00 00 fe 00 00 00 00 ff 00 00 fc 00 ...?............................
2540 00 00 10 ff 00 00 fc 00 00 00 30 ff 00 00 fc 00 00 00 3f ff 00 00 fc 00 00 00 7f ff 00 00 fc 00 ..........0.......?.............
2560 00 01 ff ff 00 00 fc 00 04 03 ff ff 00 00 fc 00 07 0f ff ff 00 00 fc 00 07 ff ff ff 00 00 fe 00 ................................
2580 07 ff ff ff 00 00 ff 00 1f ff ff ff 00 00 ff c0 3f ff ff ff 00 00 ff f0 ff ff ff ff 00 00 ff ff ................?...............
25a0 ff ff ff ff 00 00 ff ff ff ff ff ff 00 00 ff ff ff ff ff ff 00 00 ff ff ff ff ff ff 00 00 ..............................
4' href='#n1824'>1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244
/*
Minetest
Copyright (C) 2010-2017 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 "serverenvironment.h"
#include "content_sao.h"
#include "settings.h"
#include "log.h"
#include "mapblock.h"
#include "nodedef.h"
#include "nodemetadata.h"
#include "gamedef.h"
#include "map.h"
#include "porting.h"
#include "profiler.h"
#include "raycast.h"
#include "remoteplayer.h"
#include "scripting_server.h"
#include "server.h"
#include "util/serialize.h"
#include "util/basic_macros.h"
#include "util/pointedthing.h"
#include "threading/mutex_auto_lock.h"
#include "filesys.h"
#include "gameparams.h"
#include "database/database-dummy.h"
#include "database/database-files.h"
#include "database/database-sqlite3.h"
#if USE_POSTGRESQL
#include "database/database-postgresql.h"
#endif
#include <algorithm>

#define LBM_NAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_:"

// A number that is much smaller than the timeout for particle spawners should/could ever be
#define PARTICLE_SPAWNER_NO_EXPIRY -1024.f

/*
	ABMWithState
*/

ABMWithState::ABMWithState(ActiveBlockModifier *abm_):
	abm(abm_)
{
	// Initialize timer to random value to spread processing
	float itv = abm->getTriggerInterval();
	itv = MYMAX(0.001, itv); // No less than 1ms
	int minval = MYMAX(-0.51*itv, -60); // Clamp to
	int maxval = MYMIN(0.51*itv, 60);   // +-60 seconds
	timer = myrand_range(minval, maxval);
}

/*
	LBMManager
*/

void LBMContentMapping::deleteContents()
{
	for (auto &it : lbm_list) {
		delete it;
	}
}

void LBMContentMapping::addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamedef)
{
	// Add the lbm_def to the LBMContentMapping.
	// Unknown names get added to the global NameIdMapping.
	const NodeDefManager *nodedef = gamedef->ndef();

	lbm_list.push_back(lbm_def);

	for (const std::string &nodeTrigger: lbm_def->trigger_contents) {
		std::vector<content_t> c_ids;
		bool found = nodedef->getIds(nodeTrigger, c_ids);
		if (!found) {
			content_t c_id = gamedef->allocateUnknownNodeId(nodeTrigger);
			if (c_id == CONTENT_IGNORE) {
				// Seems it can't be allocated.
				warningstream << "Could not internalize node name \"" << nodeTrigger
					<< "\" while loading LBM \"" << lbm_def->name << "\"." << std::endl;
				continue;
			}
			c_ids.push_back(c_id);
		}

		for (content_t c_id : c_ids) {
			map[c_id].push_back(lbm_def);
		}
	}
}

const std::vector<LoadingBlockModifierDef *> *
LBMContentMapping::lookup(content_t c) const
{
	lbm_map::const_iterator it = map.find(c);
	if (it == map.end())
		return NULL;
	// This first dereferences the iterator, returning
	// a std::vector<LoadingBlockModifierDef *>
	// reference, then we convert it to a pointer.
	return &(it->second);
}

LBMManager::~LBMManager()
{
	for (auto &m_lbm_def : m_lbm_defs) {
		delete m_lbm_def.second;
	}

	for (auto &it : m_lbm_lookup) {
		(it.second).deleteContents();
	}
}

void LBMManager::addLBMDef(LoadingBlockModifierDef *lbm_def)
{
	// Precondition, in query mode the map isn't used anymore
	FATAL_ERROR_IF(m_query_mode,
		"attempted to modify LBMManager in query mode");

	if (!string_allowed(lbm_def->name, LBM_NAME_ALLOWED_CHARS)) {
		throw ModError("Error adding LBM \"" + lbm_def->name +
			"\": Does not follow naming conventions: "
				"Only characters [a-z0-9_:] are allowed.");
	}

	m_lbm_defs[lbm_def->name] = lbm_def;
}

void LBMManager::loadIntroductionTimes(const std::string &times,
	IGameDef *gamedef, u32 now)
{
	m_query_mode = true;

	// name -> time map.
	// Storing it in a map first instead of
	// handling the stuff directly in the loop
	// removes all duplicate entries.
	// TODO make this std::unordered_map
	std::map<std::string, u32> introduction_times;

	/*
	The introduction times string consists of name~time entries,
	with each entry terminated by a semicolon. The time is decimal.
	 */

	size_t idx = 0;
	size_t idx_new;
	while ((idx_new = times.find(';', idx)) != std::string::npos) {
		std::string entry = times.substr(idx, idx_new - idx);
		std::vector<std::string> components = str_split(entry, '~');
		if (components.size() != 2)
			throw SerializationError("Introduction times entry \""
				+ entry + "\" requires exactly one '~'!");
		const std::string &name = components[0];
		u32 time = from_string<u32>(components[1]);
		introduction_times[name] = time;
		idx = idx_new + 1;
	}

	// Put stuff from introduction_times into m_lbm_lookup
	for (std::map<std::string, u32>::const_iterator it = introduction_times.begin();
		it != introduction_times.end(); ++it) {
		const std::string &name = it->first;
		u32 time = it->second;

		std::map<std::string, LoadingBlockModifierDef *>::iterator def_it =
			m_lbm_defs.find(name);
		if (def_it == m_lbm_defs.end()) {
			// This seems to be an LBM entry for
			// an LBM we haven't loaded. Discard it.
			continue;
		}
		LoadingBlockModifierDef *lbm_def = def_it->second;
		if (lbm_def->run_at_every_load) {
			// This seems to be an LBM entry for
			// an LBM that runs at every load.
			// Don't add it just yet.
			continue;
		}

		m_lbm_lookup[time].addLBM(lbm_def, gamedef);

		// Erase the entry so that we know later
		// what elements didn't get put into m_lbm_lookup
		m_lbm_defs.erase(name);
	}

	// Now also add the elements from m_lbm_defs to m_lbm_lookup
	// that weren't added in the previous step.
	// They are introduced first time to this world,
	// or are run at every load (introducement time hardcoded to U32_MAX).

	LBMContentMapping &lbms_we_introduce_now = m_lbm_lookup[now];
	LBMContentMapping &lbms_running_always = m_lbm_lookup[U32_MAX];

	for (auto &m_lbm_def : m_lbm_defs) {
		if (m_lbm_def.second->run_at_every_load) {
			lbms_running_always.addLBM(m_lbm_def.second, gamedef);
		} else {
			lbms_we_introduce_now.addLBM(m_lbm_def.second, gamedef);
		}
	}

	// Clear the list, so that we don't delete remaining elements
	// twice in the destructor
	m_lbm_defs.clear();
}

std::string LBMManager::createIntroductionTimesString()
{
	// Precondition, we must be in query mode
	FATAL_ERROR_IF(!m_query_mode,
		"attempted to query on non fully set up LBMManager");

	std::ostringstream oss;
	for (const auto &it : m_lbm_lookup) {
		u32 time = it.first;
		const std::vector<LoadingBlockModifierDef *> &lbm_list = it.second.lbm_list;
		for (const auto &lbm_def : lbm_list) {
			// Don't add if the LBM runs at every load,
			// then introducement time is hardcoded
			// and doesn't need to be stored
			if (lbm_def->run_at_every_load)
				continue;
			oss << lbm_def->name << "~" << time << ";";
		}
	}
	return oss.str();
}

void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp)
{
	// Precondition, we need m_lbm_lookup to be initialized
	FATAL_ERROR_IF(!m_query_mode,
		"attempted to query on non fully set up LBMManager");
	v3s16 pos_of_block = block->getPosRelative();
	v3s16 pos;
	MapNode n;
	content_t c;
	lbm_lookup_map::const_iterator it = getLBMsIntroducedAfter(stamp);
	for (; it != m_lbm_lookup.end(); ++it) {
		// Cache previous version to speedup lookup which has a very high performance
		// penalty on each call
		content_t previous_c{};
		std::vector<LoadingBlockModifierDef *> *lbm_list = nullptr;

		for (pos.X = 0; pos.X < MAP_BLOCKSIZE; pos.X++)
			for (pos.Y = 0; pos.Y < MAP_BLOCKSIZE; pos.Y++)
				for (pos.Z = 0; pos.Z < MAP_BLOCKSIZE; pos.Z++) {
					n = block->getNodeNoEx(pos);
					c = n.getContent();

					// If content_t are not matching perform an LBM lookup
					if (previous_c != c) {
						lbm_list = (std::vector<LoadingBlockModifierDef *> *)
							it->second.lookup(c);
						previous_c = c;
					}

					if (!lbm_list)
						continue;
					for (auto lbmdef : *lbm_list) {
						lbmdef->trigger(env, pos + pos_of_block, n);
					}
				}
	}
}

/*
	ActiveBlockList
*/

void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
{
	v3s16 p;
	for(p.X=p0.X-r; p.X<=p0.X+r; p.X++)
		for(p.Y=p0.Y-r; p.Y<=p0.Y+r; p.Y++)
			for(p.Z=p0.Z-r; p.Z<=p0.Z+r; p.Z++)
			{
				// limit to a sphere
				if (p.getDistanceFrom(p0) <= r) {
					// Set in list
					list.insert(p);
				}
			}
}

void fillViewConeBlock(v3s16 p0,
	const s16 r,
	const v3f camera_pos,
	const v3f camera_dir,
	const float camera_fov,
	std::set<v3s16> &list)
{
	v3s16 p;
	const s16 r_nodes = r * BS * MAP_BLOCKSIZE;
	for (p.X = p0.X - r; p.X <= p0.X+r; p.X++)
	for (p.Y = p0.Y - r; p.Y <= p0.Y+r; p.Y++)
	for (p.Z = p0.Z - r; p.Z <= p0.Z+r; p.Z++) {
		if (isBlockInSight(p, camera_pos, camera_dir, camera_fov, r_nodes)) {
			list.insert(p);
		}
	}
}

void ActiveBlockList::update(std::vector<PlayerSAO*> &active_players,
	s16 active_block_range,
	s16 active_object_range,
	std::set<v3s16> &blocks_removed,
	std::set<v3s16> &blocks_added)
{
	/*
		Create the new list
	*/
	std::set<v3s16> newlist = m_forceloaded_list;
	m_abm_list = m_forceloaded_list;
	for (const PlayerSAO *playersao : active_players) {
		v3s16 pos = getNodeBlockPos(floatToInt(playersao->getBasePosition(), BS));
		fillRadiusBlock(pos, active_block_range, m_abm_list);
		fillRadiusBlock(pos, active_block_range, newlist);

		s16 player_ao_range = std::min(active_object_range, playersao->getWantedRange());
		// only do this if this would add blocks
		if (player_ao_range > active_block_range) {
			v3f camera_dir = v3f(0,0,1);
			camera_dir.rotateYZBy(playersao->getLookPitch());
			camera_dir.rotateXZBy(playersao->getRotation().Y);
			fillViewConeBlock(pos,
				player_ao_range,
				playersao->getEyePosition(),
				camera_dir,
				playersao->getFov(),
				newlist);
		}
	}

	/*
		Find out which blocks on the old list are not on the new list
	*/
	// Go through old list
	for (v3s16 p : m_list) {
		// If not on new list, it's been removed
		if (newlist.find(p) == newlist.end())
			blocks_removed.insert(p);
	}

	/*
		Find out which blocks on the new list are not on the old list
	*/
	// Go through new list
	for (v3s16 p : newlist) {
		// If not on old list, it's been added
		if(m_list.find(p) == m_list.end())
			blocks_added.insert(p);
	}

	/*
		Update m_list
	*/
	m_list.clear();
	for (v3s16 p : newlist) {
		m_list.insert(p);
	}
}

/*
	ServerEnvironment
*/

ServerEnvironment::ServerEnvironment(ServerMap *map,
	ServerScripting *scriptIface, Server *server,
	const std::string &path_world):
	Environment(server),
	m_map(map),
	m_script(scriptIface),
	m_server(server),
	m_path_world(path_world)
{
	// Determine which database backend to use
	std::string conf_path = path_world + DIR_DELIM + "world.mt";
	Settings conf;

	std::string player_backend_name = "sqlite3";
	std::string auth_backend_name = "sqlite3";

	bool succeeded = conf.readConfigFile(conf_path.c_str());

	// If we open world.mt read the backend configurations.
	if (succeeded) {
		// Read those values before setting defaults
		bool player_backend_exists = conf.exists("player_backend");
		bool auth_backend_exists = conf.exists("auth_backend");

		// player backend is not set, assume it's legacy file backend.
		if (!player_backend_exists) {
			// fall back to files
			conf.set("player_backend", "files");
			player_backend_name = "files";

			if (!conf.updateConfigFile(conf_path.c_str())) {
				errorstream << "ServerEnvironment::ServerEnvironment(): "
						<< "Failed to update world.mt!" << std::endl;
			}
		} else {
			conf.getNoEx("player_backend", player_backend_name);
		}

		// auth backend is not set, assume it's legacy file backend.
		if (!auth_backend_exists) {
			conf.set("auth_backend", "files");
			auth_backend_name = "files";

			if (!conf.updateConfigFile(conf_path.c_str())) {
				errorstream << "ServerEnvironment::ServerEnvironment(): "
						<< "Failed to update world.mt!" << std::endl;
			}
		} else {
			conf.getNoEx("auth_backend", auth_backend_name);
		}
	}

	if (player_backend_name == "files") {
		warningstream << "/!\\ You are using old player file backend. "
				<< "This backend is deprecated and will be removed in a future release /!\\"
				<< std::endl << "Switching to SQLite3 or PostgreSQL is advised, "
				<< "please read http://wiki.minetest.net/Database_backends." << std::endl;
	}

	if (auth_backend_name == "files") {
		warningstream << "/!\\ You are using old auth file backend. "
				<< "This backend is deprecated and will be removed in a future release /!\\"
				<< std::endl << "Switching to SQLite3 is advised, "
				<< "please read http://wiki.minetest.net/Database_backends." << std::endl;
	}

	m_player_database = openPlayerDatabase(player_backend_name, path_world, conf);
	m_auth_database = openAuthDatabase(auth_backend_name, path_world, conf);
}

ServerEnvironment::~ServerEnvironment()
{
	// Clear active block list.
	// This makes the next one delete all active objects.
	m_active_blocks.clear();

	// Convert all objects to static and delete the active objects
	deactivateFarObjects(true);

	// Drop/delete map
	m_map->drop();

	// Delete ActiveBlockModifiers
	for (ABMWithState &m_abm : m_abms) {
		delete m_abm.abm;
	}

	// Deallocate players
	for (RemotePlayer *m_player : m_players) {
		delete m_player;
	}

	delete m_player_database;
	delete m_auth_database;
}

Map & ServerEnvironment::getMap()
{
	return *m_map;
}

ServerMap & ServerEnvironment::getServerMap()
{
	return *m_map;
}

RemotePlayer *ServerEnvironment::getPlayer(const session_t peer_id)
{
	for (RemotePlayer *player : m_players) {
		if (player->getPeerId() == peer_id)
			return player;
	}
	return NULL;
}

RemotePlayer *ServerEnvironment::getPlayer(const char* name)
{
	for (RemotePlayer *player : m_players) {
		if (strcmp(player->getName(), name) == 0)
			return player;
	}
	return NULL;
}

void ServerEnvironment::addPlayer(RemotePlayer *player)
{
	/*
		Check that peer_ids are unique.
		Also check that names are unique.
		Exception: there can be multiple players with peer_id=0
	*/
	// If peer id is non-zero, it has to be unique.
	if (player->getPeerId() != PEER_ID_INEXISTENT)
		FATAL_ERROR_IF(getPlayer(player->getPeerId()) != NULL, "Peer id not unique");
	// Name has to be unique.
	FATAL_ERROR_IF(getPlayer(player->getName()) != NULL, "Player name not unique");
	// Add.
	m_players.push_back(player);
}

void ServerEnvironment::removePlayer(RemotePlayer *player)
{
	for (std::vector<RemotePlayer *>::iterator it = m_players.begin();
		it != m_players.end(); ++it) {
		if ((*it) == player) {
			delete *it;
			m_players.erase(it);
			return;
		}
	}
}

bool ServerEnvironment::removePlayerFromDatabase(const std::string &name)
{
	return m_player_database->removePlayer(name);
}

bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, v3s16 *p)
{
	// Iterate trough nodes on the line
	voxalgo::VoxelLineIterator iterator(pos1 / BS, (pos2 - pos1) / BS);
	do {
		MapNode n = getMap().getNodeNoEx(iterator.m_current_node_pos);

		// Return non-air
		if (n.param0 != CONTENT_AIR) {
			if (p)
				*p = iterator.m_current_node_pos;
			return false;
		}
		iterator.next();
	} while (iterator.m_current_index <= iterator.m_last_index);
	return true;
}

void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason,
	const std::string &str_reason, bool reconnect)
{
	for (RemotePlayer *player : m_players) {
		m_server->DenyAccessVerCompliant(player->getPeerId(),
			player->protocol_version, reason, str_reason, reconnect);
	}
}

void ServerEnvironment::saveLoadedPlayers(bool force)
{
	for (RemotePlayer *player : m_players) {
		if (force || player->checkModified() || (player->getPlayerSAO() &&
				player->getPlayerSAO()->getMeta().isModified())) {
			try {
				m_player_database->savePlayer(player);
			} catch (DatabaseException &e) {
				errorstream << "Failed to save player " << player->getName() << " exception: "
					<< e.what() << std::endl;
				throw;
			}
		}
	}
}

void ServerEnvironment::savePlayer(RemotePlayer *player)
{
	try {
		m_player_database->savePlayer(player);
	} catch (DatabaseException &e) {
		errorstream << "Failed to save player " << player->getName() << " exception: "
			<< e.what() << std::endl;
		throw;
	}
}

PlayerSAO *ServerEnvironment::loadPlayer(RemotePlayer *player, bool *new_player,
	session_t peer_id, bool is_singleplayer)
{
	PlayerSAO *playersao = new PlayerSAO(this, player, peer_id, is_singleplayer);
	// Create player if it doesn't exist
	if (!m_player_database->loadPlayer(player, playersao)) {
		*new_player = true;
		// Set player position
		infostream << "Server: Finding spawn place for player \""
			<< player->getName() << "\"" << std::endl;
		playersao->setBasePosition(m_server->findSpawnPos());

		// Make sure the player is saved
		player->setModified(true);
	} else {
		// If the player exists, ensure that they respawn inside legal bounds
		// This fixes an assert crash when the player can't be added
		// to the environment
		if (objectpos_over_limit(playersao->getBasePosition())) {
			actionstream << "Respawn position for player \""
				<< player->getName() << "\" outside limits, resetting" << std::endl;
			playersao->setBasePosition(m_server->findSpawnPos());
		}
	}

	// Add player to environment
	addPlayer(player);

	/* Clean up old HUD elements from previous sessions */
	player->clearHud();

	/* Add object to environment */
	addActiveObject(playersao);

	return playersao;
}

void ServerEnvironment::saveMeta()
{
	std::string path = m_path_world + DIR_DELIM "env_meta.txt";

	// Open file and serialize
	std::ostringstream ss(std::ios_base::binary);

	Settings args;
	args.setU64("game_time", m_game_time);
	args.setU64("time_of_day", getTimeOfDay());
	args.setU64("last_clear_objects_time", m_last_clear_objects_time);
	args.setU64("lbm_introduction_times_version", 1);
	args.set("lbm_introduction_times",
		m_lbm_mgr.createIntroductionTimesString());
	args.setU64("day_count", m_day_count);
	args.writeLines(ss);
	ss<<"EnvArgsEnd\n";

	if(!fs::safeWriteToFile(path, ss.str()))
	{
		infostream<<"ServerEnvironment::saveMeta(): Failed to write "
			<<path<<std::endl;
		throw SerializationError("Couldn't save env meta");
	}
}

void ServerEnvironment::loadMeta()
{
	// If file doesn't exist, load default environment metadata
	if (!fs::PathExists(m_path_world + DIR_DELIM "env_meta.txt")) {
		infostream << "ServerEnvironment: Loading default environment metadata"
			<< std::endl;
		loadDefaultMeta();
		return;
	}

	infostream << "ServerEnvironment: Loading environment metadata" << std::endl;

	std::string path = m_path_world + DIR_DELIM "env_meta.txt";

	// Open file and deserialize
	std::ifstream is(path.c_str(), std::ios_base::binary);
	if (!is.good()) {
		infostream << "ServerEnvironment::loadMeta(): Failed to open "
			<< path << std::endl;
		throw SerializationError("Couldn't load env meta");
	}

	Settings args;

	if (!args.parseConfigLines(is, "EnvArgsEnd")) {
		throw SerializationError("ServerEnvironment::loadMeta(): "
			"EnvArgsEnd not found!");
	}

	try {
		m_game_time = args.getU64("game_time");
	} catch (SettingNotFoundException &e) {
		// Getting this is crucial, otherwise timestamps are useless
		throw SerializationError("Couldn't load env meta game_time");
	}

	setTimeOfDay(args.exists("time_of_day") ?
		// set day to early morning by default
		args.getU64("time_of_day") : 5250);

	m_last_clear_objects_time = args.exists("last_clear_objects_time") ?
		// If missing, do as if clearObjects was never called
		args.getU64("last_clear_objects_time") : 0;

	std::string lbm_introduction_times;
	try {
		u64 ver = args.getU64("lbm_introduction_times_version");
		if (ver == 1) {
			lbm_introduction_times = args.get("lbm_introduction_times");
		} else {
			infostream << "ServerEnvironment::loadMeta(): Non-supported"
				<< " introduction time version " << ver << std::endl;
		}
	} catch (SettingNotFoundException &e) {
		// No problem, this is expected. Just continue with an empty string
	}
	m_lbm_mgr.loadIntroductionTimes(lbm_introduction_times, m_server, m_game_time);

	m_day_count = args.exists("day_count") ?
		args.getU64("day_count") : 0;
}

/**
 * called if env_meta.txt doesn't exist (e.g. new world)
 */
void ServerEnvironment::loadDefaultMeta()
{
	m_lbm_mgr.loadIntroductionTimes("", m_server, m_game_time);
}

struct ActiveABM
{
	ActiveBlockModifier *abm;
	int chance;
	std::vector<content_t> required_neighbors;
	bool check_required_neighbors; // false if required_neighbors is known to be empty
};

class ABMHandler
{
private:
	ServerEnvironment *m_env;
	std::vector<std::vector<ActiveABM> *> m_aabms;
public:
	ABMHandler(std::vector<ABMWithState> &abms,
		float dtime_s, ServerEnvironment *env,
		bool use_timers):
		m_env(env)
	{
		if(dtime_s < 0.001)
			return;
		const NodeDefManager *ndef = env->getGameDef()->ndef();
		for (ABMWithState &abmws : abms) {
			ActiveBlockModifier *abm = abmws.abm;
			float trigger_interval = abm->getTriggerInterval();
			if(trigger_interval < 0.001)
				trigger_interval = 0.001;
			float actual_interval = dtime_s;
			if(use_timers){
				abmws.timer += dtime_s;
				if(abmws.timer < trigger_interval)
					continue;
				abmws.timer -= trigger_interval;
				actual_interval = trigger_interval;
			}
			float chance = abm->getTriggerChance();
			if(chance == 0)
				chance = 1;
			ActiveABM aabm;
			aabm.abm = abm;
			if (abm->getSimpleCatchUp()) {
				float intervals = actual_interval / trigger_interval;
				if(intervals == 0)
					continue;
				aabm.chance = chance / intervals;
				if(aabm.chance == 0)
					aabm.chance = 1;
			} else {
				aabm.chance = chance;
			}

			// Trigger neighbors
			const std::vector<std::string> &required_neighbors_s =
				abm->getRequiredNeighbors();
			for (const std::string &required_neighbor_s : required_neighbors_s) {
				ndef->getIds(required_neighbor_s, aabm.required_neighbors);
			}
			aabm.check_required_neighbors = !required_neighbors_s.empty();

			// Trigger contents
			const std::vector<std::string> &contents_s = abm->getTriggerContents();
			for (const std::string &content_s : contents_s) {
				std::vector<content_t> ids;
				ndef->getIds(content_s, ids);
				for (content_t c : ids) {
					if (c >= m_aabms.size())
						m_aabms.resize(c + 256, NULL);
					if (!m_aabms[c])
						m_aabms[c] = new std::vector<ActiveABM>;
					m_aabms[c]->push_back(aabm);
				}
			}
		}
	}

	~ABMHandler()
	{
		for (auto &aabms : m_aabms)
			delete aabms;
	}

	// Find out how many objects the given block and its neighbours contain.
	// Returns the number of objects in the block, and also in 'wider' the
	// number of objects in the block and all its neighbours. The latter
	// may an estimate if any neighbours are unloaded.
	u32 countObjects(MapBlock *block, ServerMap * map, u32 &wider)
	{
		wider = 0;
		u32 wider_unknown_count = 0;
		for(s16 x=-1; x<=1; x++)
			for(s16 y=-1; y<=1; y++)
				for(s16 z=-1; z<=1; z++)
				{
					MapBlock *block2 = map->getBlockNoCreateNoEx(
						block->getPos() + v3s16(x,y,z));
					if(block2==NULL){
						wider_unknown_count++;
						continue;
					}
					wider += block2->m_static_objects.m_active.size()
						+ block2->m_static_objects.m_stored.size();
				}
		// Extrapolate
		u32 active_object_count = block->m_static_objects.m_active.size();
		u32 wider_known_count = 3*3*3 - wider_unknown_count;
		wider += wider_unknown_count * wider / wider_known_count;
		return active_object_count;

	}
	void apply(MapBlock *block, int &blocks_scanned, int &abms_run, int &blocks_cached)
	{
		if(m_aabms.empty() || block->isDummy())
			return;

		// Check the content type cache first
		// to see whether there are any ABMs
		// to be run at all for this block.
		if (block->contents_cached) {
			blocks_cached++;
			bool run_abms = false;
			for (content_t c : block->contents) {
				if (c < m_aabms.size() && m_aabms[c]) {
					run_abms = true;
					break;
				}
			}
			if (!run_abms)
				return;
		} else {
			// Clear any caching
			block->contents.clear();
		}
		blocks_scanned++;

		ServerMap *map = &m_env->getServerMap();

		u32 active_object_count_wider;
		u32 active_object_count = this->countObjects(block, map, active_object_count_wider);
		m_env->m_added_objects = 0;

		v3s16 p0;
		for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
		for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
		for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
		{
			const MapNode &n = block->getNodeUnsafe(p0);
			content_t c = n.getContent();
			// Cache content types as we go
			if (!block->contents_cached && !block->do_not_cache_contents) {
				block->contents.insert(c);
				if (block->contents.size() > 64) {
					// Too many different nodes... don't try to cache
					block->do_not_cache_contents = true;
					block->contents.clear();
				}
			}

			if (c >= m_aabms.size() || !m_aabms[c])
				continue;

			v3s16 p = p0 + block->getPosRelative();
			for (ActiveABM &aabm : *m_aabms[c]) {
				if (myrand() % aabm.chance != 0)
					continue;

				// Check neighbors
				if (aabm.check_required_neighbors) {
					v3s16 p1;
					for(p1.X = p0.X-1; p1.X <= p0.X+1; p1.X++)
					for(p1.Y = p0.Y-1; p1.Y <= p0.Y+1; p1.Y++)
					for(p1.Z = p0.Z-1; p1.Z <= p0.Z+1; p1.Z++)
					{
						if(p1 == p0)
							continue;
						content_t c;
						if (block->isValidPosition(p1)) {
							// if the neighbor is found on the same map block
							// get it straight from there
							const MapNode &n = block->getNodeUnsafe(p1);
							c = n.getContent();
						} else {
							// otherwise consult the map
							MapNode n = map->getNodeNoEx(p1 + block->getPosRelative());
							c = n.getContent();
						}
						if (CONTAINS(aabm.required_neighbors, c))
							goto neighbor_found;
					}
					// No required neighbor found
					continue;
				}
				neighbor_found:

				abms_run++;
				// Call all the trigger variations
				aabm.abm->trigger(m_env, p, n);
				aabm.abm->trigger(m_env, p, n,
					active_object_count, active_object_count_wider);

				// Count surrounding objects again if the abms added any
				if(m_env->m_added_objects > 0) {
					active_object_count = countObjects(block, map, active_object_count_wider);
					m_env->m_added_objects = 0;
				}
			}
		}
		block->contents_cached = !block->do_not_cache_contents;
	}
};

void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
{
	// Reset usage timer immediately, otherwise a block that becomes active
	// again at around the same time as it would normally be unloaded will
	// get unloaded incorrectly. (I think this still leaves a small possibility
	// of a race condition between this and server::AsyncRunStep, which only
	// some kind of synchronisation will fix, but it at least reduces the window
	// of opportunity for it to break from seconds to nanoseconds)
	block->resetUsageTimer();

	// Get time difference
	u32 dtime_s = 0;
	u32 stamp = block->getTimestamp();
	if (m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
		dtime_s = m_game_time - stamp;
	dtime_s += additional_dtime;

	/*infostream<<"ServerEnvironment::activateBlock(): block timestamp: "
			<<stamp<<", game time: "<<m_game_time<<std::endl;*/

	// Remove stored static objects if clearObjects was called since block's timestamp
	if (stamp == BLOCK_TIMESTAMP_UNDEFINED || stamp < m_last_clear_objects_time) {
		block->m_static_objects.m_stored.clear();
		// do not set changed flag to avoid unnecessary mapblock writes
	}

	// Set current time as timestamp
	block->setTimestampNoChangedFlag(m_game_time);

	/*infostream<<"ServerEnvironment::activateBlock(): block is "
			<<dtime_s<<" seconds old."<<std::endl;*/

	// Activate stored objects
	activateObjects(block, dtime_s);

	/* Handle LoadingBlockModifiers */
	m_lbm_mgr.applyLBMs(this, block, stamp);

	// Run node timers
	std::vector<NodeTimer> elapsed_timers =
		block->m_node_timers.step((float)dtime_s);
	if (!elapsed_timers.empty()) {
		MapNode n;
		for (const NodeTimer &elapsed_timer : elapsed_timers) {
			n = block->getNodeNoEx(elapsed_timer.position);
			v3s16 p = elapsed_timer.position + block->getPosRelative();
			if (m_script->node_on_timer(p, n, elapsed_timer.elapsed))
				block->setNodeTimer(NodeTimer(elapsed_timer.timeout, 0,
					elapsed_timer.position));
		}
	}
}

void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
{
	m_abms.emplace_back(abm);
}

void ServerEnvironment::addLoadingBlockModifierDef(LoadingBlockModifierDef *lbm)
{
	m_lbm_mgr.addLBMDef(lbm);
}

bool ServerEnvironment::setNode(v3s16 p, const MapNode &n)
{
	const NodeDefManager *ndef = m_server->ndef();
	MapNode n_old = m_map->getNodeNoEx(p);

	const ContentFeatures &cf_old = ndef->get(n_old);

	// Call destructor
	if (cf_old.has_on_destruct)
		m_script->node_on_destruct(p, n_old);

	// Replace node
	if (!m_map->addNodeWithEvent(p, n))
		return false;

	// Update active VoxelManipulator if a mapgen thread
	m_map->updateVManip(p);

	// Call post-destructor
	if (cf_old.has_after_destruct)
		m_script->node_after_destruct(p, n_old);

	// Retrieve node content features
	// if new node is same as old, reuse old definition to prevent a lookup
	const ContentFeatures &cf_new = n_old == n ? cf_old : ndef->get(n);

	// Call constructor
	if (cf_new.has_on_construct)
		m_script->node_on_construct(p, n);

	return true;
}

bool ServerEnvironment::removeNode(v3s16 p)
{
	const NodeDefManager *ndef = m_server->ndef();
	MapNode n_old = m_map->getNodeNoEx(p);

	// Call destructor
	if (ndef->get(n_old).has_on_destruct)
		m_script->node_on_destruct(p, n_old);

	// Replace with air
	// This is slightly optimized compared to addNodeWithEvent(air)
	if (!m_map->removeNodeWithEvent(p))
		return false;

	// Update active VoxelManipulator if a mapgen thread
	m_map->updateVManip(p);

	// Call post-destructor
	if (ndef->get(n_old).has_after_destruct)
		m_script->node_after_destruct(p, n_old);

	// Air doesn't require constructor
	return true;
}

bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
{
	if (!m_map->addNodeWithEvent(p, n, false))
		return false;

	// Update active VoxelManipulator if a mapgen thread
	m_map->updateVManip(p);

	return true;
}

void ServerEnvironment::clearObjects(ClearObjectsMode mode)
{
	infostream << "ServerEnvironment::clearObjects(): "
		<< "Removing all active objects" << std::endl;
	auto cb_removal = [this] (ServerActiveObject *obj, u16 id) {
		if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER)
			return false;

		// Delete static object if block is loaded
		deleteStaticFromBlock(obj, id, MOD_REASON_CLEAR_ALL_OBJECTS, true);

		// If known by some client, don't delete immediately
		if (obj->m_known_by_count > 0) {
			obj->m_pending_removal = true;
			return false;
		}

		// Tell the object about removal
		obj->removingFromEnvironment();
		// Deregister in scripting api
		m_script->removeObjectReference(obj);

		// Delete active object
		if (obj->environmentDeletes())
			delete obj;

		return true;
	};

	m_ao_manager.clear(cb_removal);

	// Get list of loaded blocks
	std::vector<v3s16> loaded_blocks;
	infostream << "ServerEnvironment::clearObjects(): "
		<< "Listing all loaded blocks" << std::endl;
	m_map->listAllLoadedBlocks(loaded_blocks);
	infostream << "ServerEnvironment::clearObjects(): "
		<< "Done listing all loaded blocks: "
		<< loaded_blocks.size()<<std::endl;

	// Get list of loadable blocks
	std::vector<v3s16> loadable_blocks;
	if (mode == CLEAR_OBJECTS_MODE_FULL) {
		infostream << "ServerEnvironment::clearObjects(): "
			<< "Listing all loadable blocks" << std::endl;
		m_map->listAllLoadableBlocks(loadable_blocks);
		infostream << "ServerEnvironment::clearObjects(): "
			<< "Done listing all loadable blocks: "
			<< loadable_blocks.size() << std::endl;
	} else {
		loadable_blocks = loaded_blocks;
	}

	actionstream << "ServerEnvironment::clearObjects(): "
		<< "Now clearing objects in " << loadable_blocks.size()
		<< " blocks" << std::endl;

	// Grab a reference on each loaded block to avoid unloading it
	for (v3s16 p : loaded_blocks) {
		MapBlock *block = m_map->getBlockNoCreateNoEx(p);
		assert(block != NULL);
		block->refGrab();
	}

	// Remove objects in all loadable blocks
	u32 unload_interval = U32_MAX;
	if (mode == CLEAR_OBJECTS_MODE_FULL) {
		unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks");
		unload_interval = MYMAX(unload_interval, 1);
	}
	u32 report_interval = loadable_blocks.size() / 10;
	u32 num_blocks_checked = 0;
	u32 num_blocks_cleared = 0;
	u32 num_objs_cleared = 0;
	for (auto i = loadable_blocks.begin();
		i != loadable_blocks.end(); ++i) {
		v3s16 p = *i;
		MapBlock *block = m_map->emergeBlock(p, false);
		if (!block) {
			errorstream << "ServerEnvironment::clearObjects(): "
				<< "Failed to emerge block " << PP(p) << std::endl;
			continue;
		}
		u32 num_stored = block->m_static_objects.m_stored.size();
		u32 num_active = block->m_static_objects.m_active.size();
		if (num_stored != 0 || num_active != 0) {
			block->m_static_objects.m_stored.clear();
			block->m_static_objects.m_active.clear();
			block->raiseModified(MOD_STATE_WRITE_NEEDED,
				MOD_REASON_CLEAR_ALL_OBJECTS);
			num_objs_cleared += num_stored + num_active;
			num_blocks_cleared++;
		}
		num_blocks_checked++;

		if (report_interval != 0 &&
			num_blocks_checked % report_interval == 0) {
			float percent = 100.0 * (float)num_blocks_checked /
				loadable_blocks.size();
			actionstream << "ServerEnvironment::clearObjects(): "
				<< "Cleared " << num_objs_cleared << " objects"
				<< " in " << num_blocks_cleared << " blocks ("
				<< percent << "%)" << std::endl;
		}
		if (num_blocks_checked % unload_interval == 0) {
			m_map->unloadUnreferencedBlocks();
		}
	}
	m_map->unloadUnreferencedBlocks();

	// Drop references that were added above
	for (v3s16 p : loaded_blocks) {
		MapBlock *block = m_map->getBlockNoCreateNoEx(p);
		assert(block);
		block->refDrop();
	}

	m_last_clear_objects_time = m_game_time;

	actionstream << "ServerEnvironment::clearObjects(): "
		<< "Finished: Cleared " << num_objs_cleared << " objects"
		<< " in " << num_blocks_cleared << " blocks" << std::endl;
}

void ServerEnvironment::step(float dtime)
{
	/* Step time of day */
	stepTimeOfDay(dtime);

	// Update this one
	// NOTE: This is kind of funny on a singleplayer game, but doesn't
	// really matter that much.
	static thread_local const float server_step =
			g_settings->getFloat("dedicated_server_step");
	m_recommended_send_interval = server_step;

	/*
		Increment game time
	*/
	{
		m_game_time_fraction_counter += dtime;
		u32 inc_i = (u32)m_game_time_fraction_counter;
		m_game_time += inc_i;
		m_game_time_fraction_counter -= (float)inc_i;
	}

	/*
		Handle players
	*/
	{
		ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG);
		for (RemotePlayer *player : m_players) {
			// Ignore disconnected players
			if (player->getPeerId() == PEER_ID_INEXISTENT)
				continue;

			// Move
			player->move(dtime, this, 100 * BS);
		}
	}

	/*
		Manage active block list
	*/
	if (m_active_blocks_management_interval.step(dtime, m_cache_active_block_mgmt_interval)) {
		ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg per interval", SPT_AVG);
		/*
			Get player block positions
		*/
		std::vector<PlayerSAO*> players;
		for (RemotePlayer *player: m_players) {
			// Ignore disconnected players
			if (player->getPeerId() == PEER_ID_INEXISTENT)
				continue;

			PlayerSAO *playersao = player->getPlayerSAO();
			assert(playersao);

			players.push_back(playersao);
		}

		/*
			Update list of active blocks, collecting changes
		*/
		// use active_object_send_range_blocks since that is max distance
		// for active objects sent the client anyway
		static thread_local const s16 active_object_range =
				g_settings->getS16("active_object_send_range_blocks");
		static thread_local const s16 active_block_range =
				g_settings->getS16("active_block_range");
		std::set<v3s16> blocks_removed;
		std::set<v3s16> blocks_added;
		m_active_blocks.update(players, active_block_range, active_object_range,
			blocks_removed, blocks_added);

		/*
			Handle removed blocks
		*/

		// Convert active objects that are no more in active blocks to static
		deactivateFarObjects(false);

		for (const v3s16 &p: blocks_removed) {
			MapBlock *block = m_map->getBlockNoCreateNoEx(p);
			if (!block)
				continue;

			// Set current time as timestamp (and let it set ChangedFlag)
			block->setTimestamp(m_game_time);
		}

		/*
			Handle added blocks
		*/

		for (const v3s16 &p: blocks_added) {
			MapBlock *block = m_map->getBlockOrEmerge(p);
			if (!block) {
				m_active_blocks.m_list.erase(p);
				m_active_blocks.m_abm_list.erase(p);
				continue;
			}

			activateBlock(block);
		}
	}

	/*
		Mess around in active blocks
	*/
	if (m_active_blocks_nodemetadata_interval.step(dtime, m_cache_nodetimer_interval)) {
		ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg per interval", SPT_AVG);

		float dtime = m_cache_nodetimer_interval;

		for (const v3s16 &p: m_active_blocks.m_list) {
			MapBlock *block = m_map->getBlockNoCreateNoEx(p);
			if (!block)
				continue;

			// Reset block usage timer
			block->resetUsageTimer();

			// Set current time as timestamp
			block->setTimestampNoChangedFlag(m_game_time);
			// If time has changed much from the one on disk,
			// set block to be saved when it is unloaded
			if(block->getTimestamp() > block->getDiskTimestamp() + 60)
				block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD,
					MOD_REASON_BLOCK_EXPIRED);

			// Run node timers
			std::vector<NodeTimer> elapsed_timers = block->m_node_timers.step(dtime);
			if (!elapsed_timers.empty()) {
				MapNode n;
				v3s16 p2;
				for (const NodeTimer &elapsed_timer: elapsed_timers) {
					n = block->getNodeNoEx(elapsed_timer.position);
					p2 = elapsed_timer.position + block->getPosRelative();
					if (m_script->node_on_timer(p2, n, elapsed_timer.elapsed)) {
						block->setNodeTimer(NodeTimer(
							elapsed_timer.timeout, 0, elapsed_timer.position));
					}
				}
			}
		}
	}

	if (m_active_block_modifier_interval.step(dtime, m_cache_abm_interval))
		do { // breakable
			if (m_active_block_interval_overload_skip > 0) {
				ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips");
				m_active_block_interval_overload_skip--;
				break;
			}
			ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg per interval", SPT_AVG);
			TimeTaker timer("modify in active blocks per interval");

			// Initialize handling of ActiveBlockModifiers
			ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true);

			int blocks_scanned = 0;
			int abms_run = 0;
			int blocks_cached = 0;
			for (const v3s16 &p : m_active_blocks.m_abm_list) {
				MapBlock *block = m_map->getBlockNoCreateNoEx(p);
				if (!block)
					continue;

				// Set current time as timestamp
				block->setTimestampNoChangedFlag(m_game_time);

				/* Handle ActiveBlockModifiers */
				abmhandler.apply(block, blocks_scanned, abms_run, blocks_cached);
			}
			g_profiler->avg("SEnv: active blocks", m_active_blocks.m_abm_list.size());
			g_profiler->avg("SEnv: active blocks cached", blocks_cached);
			g_profiler->avg("SEnv: active blocks scanned for ABMs", blocks_scanned);
			g_profiler->avg("SEnv: ABMs run", abms_run);

			u32 time_ms = timer.stop(true);
			u32 max_time_ms = 200;
			if (time_ms > max_time_ms) {
				warningstream<<"active block modifiers took "
					<<time_ms<<"ms (longer than "
					<<max_time_ms<<"ms)"<<std::endl;
				m_active_block_interval_overload_skip = (time_ms / max_time_ms) + 1;
			}
		}while(0);

	/*
		Step script environment (run global on_step())
	*/
	m_script->environment_Step(dtime);

	/*
		Step active objects
	*/
	{
		ScopeProfiler sp(g_profiler, "SEnv: step act. objs avg", SPT_AVG);

		// This helps the objects to send data at the same time
		bool send_recommended = false;
		m_send_recommended_timer += dtime;
		if (m_send_recommended_timer > getSendRecommendedInterval()) {
			m_send_recommended_timer -= getSendRecommendedInterval();
			send_recommended = true;
		}

		auto cb_state = [this, dtime, send_recommended] (ServerActiveObject *obj) {
			if (obj->isGone())
				return;

			// Step object
			obj->step(dtime, send_recommended);
			// Read messages from object
			while (!obj->m_messages_out.empty()) {
				this->m_active_object_messages.push(obj->m_messages_out.front());
				obj->m_messages_out.pop();
			}
		};
		m_ao_manager.step(dtime, cb_state);
	}

	/*
		Manage active objects
	*/
	if (m_object_management_interval.step(dtime, 0.5)) {
		ScopeProfiler sp(g_profiler, "SEnv: remove removed objs avg /.5s", SPT_AVG);
		removeRemovedObjects();
	}

	/*
		Manage particle spawner expiration
	*/
	if (m_particle_management_interval.step(dtime, 1.0)) {
		for (std::unordered_map<u32, float>::iterator i = m_particle_spawners.begin();
			i != m_particle_spawners.end(); ) {
			//non expiring spawners
			if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) {
				++i;
				continue;
			}

			i->second -= 1.0f;
			if (i->second <= 0.f)
				m_particle_spawners.erase(i++);
			else
				++i;
		}
	}
}

u32 ServerEnvironment::addParticleSpawner(float exptime)
{
	// Timers with lifetime 0 do not expire
	float time = exptime > 0.f ? exptime : PARTICLE_SPAWNER_NO_EXPIRY;

	u32 id = 0;
	for (;;) { // look for unused particlespawner id
		id++;
		std::unordered_map<u32, float>::iterator f = m_particle_spawners.find(id);
		if (f == m_particle_spawners.end()) {
			m_particle_spawners[id] = time;
			break;
		}
	}
	return id;
}

u32 ServerEnvironment::addParticleSpawner(float exptime, u16 attached_id)
{
	u32 id = addParticleSpawner(exptime);
	m_particle_spawner_attachments[id] = attached_id;
	if (ServerActiveObject *obj = getActiveObject(attached_id)) {
		obj->attachParticleSpawner(id);
	}
	return id;
}

void ServerEnvironment::deleteParticleSpawner(u32 id, bool remove_from_object)
{
	m_particle_spawners.erase(id);
	const auto &it = m_particle_spawner_attachments.find(id);
	if (it != m_particle_spawner_attachments.end()) {
		u16 obj_id = it->second;
		ServerActiveObject *sao = getActiveObject(obj_id);
		if (sao != NULL && remove_from_object) {
			sao->detachParticleSpawner(id);
		}
		m_particle_spawner_attachments.erase(id);
	}
}

u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
{
	assert(object);	// Pre-condition
	m_added_objects++;
	u16 id = addActiveObjectRaw(object, true, 0);
	return id;
}

/*
	Finds out what new objects have been added to
	inside a radius around a position
*/
void ServerEnvironment::getAddedActiveObjects(PlayerSAO *playersao, s16 radius,
	s16 player_radius,
	std::set<u16> &current_objects,
	std::queue<u16> &added_objects)
{
	f32 radius_f = radius * BS;
	f32 player_radius_f = player_radius * BS;

	if (player_radius_f < 0.0f)
		player_radius_f = 0.0f;

	m_ao_manager.getAddedActiveObjectsAroundPos(playersao->getBasePosition(), radius_f,
		player_radius_f, current_objects, added_objects);
}

/*
	Finds out what objects have been removed from
	inside a radius around a position
*/
void ServerEnvironment::getRemovedActiveObjects(PlayerSAO *playersao, s16 radius,
	s16 player_radius,
	std::set<u16> &current_objects,
	std::queue<u16> &removed_objects)
{
	f32 radius_f = radius * BS;
	f32 player_radius_f = player_radius * BS;

	if (player_radius_f < 0)
		player_radius_f = 0;
	/*
		Go through current_objects; object is removed if:
		- object is not found in m_active_objects (this is actually an
		  error condition; objects should be removed only after all clients
		  have been informed about removal), or
		- object is to be removed or deactivated, or
		- object is too far away
	*/
	for (u16 id : current_objects) {
		ServerActiveObject *object = getActiveObject(id);

		if (object == NULL) {
			infostream << "ServerEnvironment::getRemovedActiveObjects():"
				<< " object in current_objects is NULL" << std::endl;
			removed_objects.push(id);
			continue;
		}

		if (object->isGone()) {
			removed_objects.push(id);
			continue;
		}

		f32 distance_f = object->getBasePosition().getDistanceFrom(playersao->getBasePosition());
		if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
			if (distance_f <= player_radius_f || player_radius_f == 0)
				continue;
		} else if (distance_f <= radius_f)
			continue;

		// Object is no longer visible
		removed_objects.push(id);
	}
}

void ServerEnvironment::setStaticForActiveObjectsInBlock(
	v3s16 blockpos, bool static_exists, v3s16 static_block)
{
	MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
	if (!block)
		return;

	for (auto &so_it : block->m_static_objects.m_active) {
		// Get the ServerActiveObject counterpart to this StaticObject
		ServerActiveObject *sao = m_ao_manager.getActiveObject(so_it.first);
		if (!sao) {
			// If this ever happens, there must be some kind of nasty bug.
			errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): "
				"Object from MapBlock::m_static_objects::m_active not found "
				"in m_active_objects";
			continue;
		}

		sao->m_static_exists = static_exists;
		sao->m_static_block  = static_block;
	}
}

ActiveObjectMessage ServerEnvironment::getActiveObjectMessage()
{
	if(m_active_object_messages.empty())
		return ActiveObjectMessage(0);

	ActiveObjectMessage message = m_active_object_messages.front();
	m_active_object_messages.pop();
	return message;
}

void ServerEnvironment::getSelectedActiveObjects(
	const core::line3d<f32> &shootline_on_map,
	std::vector<PointedThing> &objects)
{
	std::vector<u16> objectIds;
	getObjectsInsideRadius(objectIds, shootline_on_map.start,
		shootline_on_map.getLength() + 10.0f);
	const v3f line_vector = shootline_on_map.getVector();

	for (u16 objectId : objectIds) {
		ServerActiveObject* obj = getActiveObject(objectId);

		aabb3f selection_box;
		if (!obj->getSelectionBox(&selection_box))
			continue;

		v3f pos = obj->getBasePosition();

		aabb3f offsetted_box(selection_box.MinEdge + pos,
			selection_box.MaxEdge + pos);

		v3f current_intersection;
		v3s16 current_normal;
		if (boxLineCollision(offsetted_box, shootline_on_map.start, line_vector,
				&current_intersection, &current_normal)) {
			objects.emplace_back(
				(s16) objectId, current_intersection, current_normal,
				(current_intersection - shootline_on_map.start).getLengthSQ());
		}
	}
}

/*
	************ Private methods *************
*/

u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
	bool set_changed, u32 dtime_s)
{
	if (!m_ao_manager.registerObject(object)) {
		return 0;
	}

	// Register reference in scripting api (must be done before post-init)
	m_script->addObjectReference(object);
	// Post-initialize object
	object->addedToEnvironment(dtime_s);

	// Add static data to block
	if (object->isStaticAllowed()) {
		// Add static object to active static list of the block
		v3f objectpos = object->getBasePosition();
		StaticObject s_obj(object, objectpos);
		// Add to the block where the object is located in
		v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
		MapBlock *block = m_map->emergeBlock(blockpos);
		if(block){
			block->m_static_objects.m_active[object->getId()] = s_obj;
			object->m_static_exists = true;
			object->m_static_block = blockpos;

			if(set_changed)
				block->raiseModified(MOD_STATE_WRITE_NEEDED,
					MOD_REASON_ADD_ACTIVE_OBJECT_RAW);
		} else {
			v3s16 p = floatToInt(objectpos, BS);
			errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
				<<"could not emerge block for storing id="<<object->getId()
				<<" statically (pos="<<PP(p)<<")"<<std::endl;
		}
	}

	return object->getId();
}

/*
	Remove objects that satisfy (isGone() && m_known_by_count==0)
*/
void ServerEnvironment::removeRemovedObjects()
{
	auto clear_cb = [this] (ServerActiveObject *obj, u16 id) {
		// This shouldn't happen but check it
		if (!obj) {
			errorstream << "ServerEnvironment::removeRemovedObjects(): "
					<< "NULL object found. id=" << id << std::endl;
			return true;
		}

		/*
			We will handle objects marked for removal or deactivation
		*/
		if (!obj->isGone())
			return false;

		/*
			Delete static data from block if removed
		*/
		if (obj->m_pending_removal)
			deleteStaticFromBlock(obj, id, MOD_REASON_REMOVE_OBJECTS_REMOVE, false);

		// If still known by clients, don't actually remove. On some future
		// invocation this will be 0, which is when removal will continue.
		if(obj->m_known_by_count > 0)
			return false;

		/*
			Move static data from active to stored if deactivated
		*/
		if (!obj->m_pending_removal && obj->m_static_exists) {
			MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
			if (block) {
				const auto i = block->m_static_objects.m_active.find(id);
				if (i != block->m_static_objects.m_active.end()) {
					block->m_static_objects.m_stored.push_back(i->second);
					block->m_static_objects.m_active.erase(id);
					block->raiseModified(MOD_STATE_WRITE_NEEDED,
						MOD_REASON_REMOVE_OBJECTS_DEACTIVATE);
				} else {
					warningstream << "ServerEnvironment::removeRemovedObjects(): "
							<< "id=" << id << " m_static_exists=true but "
							<< "static data doesn't actually exist in "
							<< PP(obj->m_static_block) << std::endl;
				}
			} else {
				infostream << "Failed to emerge block from which an object to "
						<< "be deactivated was loaded from. id=" << id << std::endl;
			}
		}

		// Tell the object about removal
		obj->removingFromEnvironment();
		// Deregister in scripting api
		m_script->removeObjectReference(obj);

		// Delete
		if (obj->environmentDeletes())
			delete obj;

		return true;
	};

	m_ao_manager.clear(clear_cb);
}

static void print_hexdump(std::ostream &o, const std::string &data)
{
	const int linelength = 16;
	for(int l=0; ; l++){
		int i0 = linelength * l;
		bool at_end = false;
		int thislinelength = linelength;
		if(i0 + thislinelength > (int)data.size()){
			thislinelength = data.size() - i0;
			at_end = true;
		}
		for(int di=0; di<linelength; di++){
			int i = i0 + di;
			char buf[4];
			if(di<thislinelength)
				porting::mt_snprintf(buf, sizeof(buf), "%.2x ", data[i]);
			else
				porting::mt_snprintf(buf, sizeof(buf), "   ");
			o<<buf;
		}
		o<<" ";
		for(int di=0; di<thislinelength; di++){
			int i = i0 + di;
			if(data[i] >= 32)
				o<<data[i];
			else
				o<<".";
		}
		o<<std::endl;
		if(at_end)
			break;
	}
}

/*
	Convert stored objects from blocks near the players to active.
*/
void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
{
	if(block == NULL)
		return;

	// Ignore if no stored objects (to not set changed flag)
	if(block->m_static_objects.m_stored.empty())
		return;

	verbosestream<<"ServerEnvironment::activateObjects(): "
		<<"activating objects of block "<<PP(block->getPos())
		<<" ("<<block->m_static_objects.m_stored.size()
		<<" objects)"<<std::endl;
	bool large_amount = (block->m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block"));
	if (large_amount) {
		errorstream<<"suspiciously large amount of objects detected: "
			<<block->m_static_objects.m_stored.size()<<" in "
			<<PP(block->getPos())
			<<"; removing all of them."<<std::endl;
		// Clear stored list
		block->m_static_objects.m_stored.clear();
		block->raiseModified(MOD_STATE_WRITE_NEEDED,
			MOD_REASON_TOO_MANY_OBJECTS);
		return;
	}

	// Activate stored objects
	std::vector<StaticObject> new_stored;
	for (const StaticObject &s_obj : block->m_static_objects.m_stored) {
		// Create an active object from the data
		ServerActiveObject *obj = ServerActiveObject::create
			((ActiveObjectType) s_obj.type, this, 0, s_obj.pos, s_obj.data);
		// If couldn't create object, store static data back.
		if(obj == NULL) {
			errorstream<<"ServerEnvironment::activateObjects(): "
				<<"failed to create active object from static object "
				<<"in block "<<PP(s_obj.pos/BS)
				<<" type="<<(int)s_obj.type<<" data:"<<std::endl;
			print_hexdump(verbosestream, s_obj.data);

			new_stored.push_back(s_obj);
			continue;
		}
		verbosestream<<"ServerEnvironment::activateObjects(): "
			<<"activated static object pos="<<PP(s_obj.pos/BS)
			<<" type="<<(int)s_obj.type<<std::endl;
		// This will also add the object to the active static list
		addActiveObjectRaw(obj, false, dtime_s);
	}

	// Clear stored list
	block->m_static_objects.m_stored.clear();
	// Add leftover failed stuff to stored list
	for (const StaticObject &s_obj : new_stored) {
		block->m_static_objects.m_stored.push_back(s_obj);
	}

	/*
		Note: Block hasn't really been modified here.
		The objects have just been activated and moved from the stored
		static list to the active static list.
		As such, the block is essentially the same.
		Thus, do not call block->raiseModified(MOD_STATE_WRITE_NEEDED).
		Otherwise there would be a huge amount of unnecessary I/O.
	*/
}

/*
	Convert objects that are not standing inside active blocks to static.

	If m_known_by_count != 0, active object is not deleted, but static
	data is still updated.

	If force_delete is set, active object is deleted nevertheless. It
	shall only be set so in the destructor of the environment.

	If block wasn't generated (not in memory or on disk),
*/
void ServerEnvironment::deactivateFarObjects(bool _force_delete)
{
	auto cb_deactivate = [this, _force_delete] (ServerActiveObject *obj, u16 id) {
		// force_delete might be overriden per object
		bool force_delete = _force_delete;

		// Do not deactivate if static data creation not allowed
		if (!force_delete && !obj->isStaticAllowed())
			return false;

		// removeRemovedObjects() is responsible for these
		if (!force_delete && obj->isGone())
			return false;

		const v3f &objectpos = obj->getBasePosition();

		// The block in which the object resides in
		v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));

		// If object's static data is stored in a deactivated block and object
		// is actually located in an active block, re-save to the block in
		// which the object is actually located in.
		if (!force_delete && obj->m_static_exists &&
		   !m_active_blocks.contains(obj->m_static_block) &&
		   m_active_blocks.contains(blockpos_o)) {
			// Delete from block where object was located
			deleteStaticFromBlock(obj, id, MOD_REASON_STATIC_DATA_REMOVED, false);

			StaticObject s_obj(obj, objectpos);
			// Save to block where object is located
			saveStaticToBlock(blockpos_o, id, obj, s_obj, MOD_REASON_STATIC_DATA_ADDED);

			return false;
		}

		// If block is still active, don't remove
		if (!force_delete && m_active_blocks.contains(blockpos_o))
			return false;

		verbosestream << "ServerEnvironment::deactivateFarObjects(): "
					  << "deactivating object id=" << id << " on inactive block "
					  << PP(blockpos_o) << std::endl;

		// If known by some client, don't immediately delete.
		bool pending_delete = (obj->m_known_by_count > 0 && !force_delete);

		/*
			Update the static data
		*/
		if (obj->isStaticAllowed()) {
			// Create new static object
			StaticObject s_obj(obj, objectpos);

			bool stays_in_same_block = false;
			bool data_changed = true;

			// Check if static data has changed considerably
			if (obj->m_static_exists) {
				if (obj->m_static_block == blockpos_o)
					stays_in_same_block = true;

				MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);

				if (block) {
					const auto n = block->m_static_objects.m_active.find(id);
					if (n != block->m_static_objects.m_active.end()) {
						StaticObject static_old = n->second;

						float save_movem = obj->getMinimumSavedMovement();

						if (static_old.data == s_obj.data &&
							(static_old.pos - objectpos).getLength() < save_movem)
							data_changed = false;
					} else {
						warningstream << "ServerEnvironment::deactivateFarObjects(): "
								<< "id=" << id << " m_static_exists=true but "
								<< "static data doesn't actually exist in "
								<< PP(obj->m_static_block) << std::endl;
					}
				}
			}

			/*
				While changes are always saved, blocks are only marked as modified
				if the object has moved or different staticdata. (see above)
			*/
			bool shall_be_written = (!stays_in_same_block || data_changed);
			u32 reason = shall_be_written ? MOD_REASON_STATIC_DATA_CHANGED : MOD_REASON_UNKNOWN;

			// Delete old static object
			deleteStaticFromBlock(obj, id, reason, false);

			// Add to the block where the object is located in
			v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
			u16 store_id = pending_delete ? id : 0;
			if (!saveStaticToBlock(blockpos, store_id, obj, s_obj, reason))
				force_delete = true;
		}

		/*
			If known by some client, set pending deactivation.
			Otherwise delete it immediately.
		*/
		if (pending_delete && !force_delete) {
			verbosestream << "ServerEnvironment::deactivateFarObjects(): "
						  << "object id=" << id << " is known by clients"
						  << "; not deleting yet" << std::endl;

			obj->m_pending_deactivation = true;
			return false;
		}

		verbosestream << "ServerEnvironment::deactivateFarObjects(): "
					  << "object id=" << id << " is not known by clients"
					  << "; deleting" << std::endl;

		// Tell the object about removal
		obj->removingFromEnvironment();
		// Deregister in scripting api
		m_script->removeObjectReference(obj);

		// Delete active object
		if (obj->environmentDeletes())
			delete obj;

		return true;
	};

	m_ao_manager.clear(cb_deactivate);
}

void ServerEnvironment::deleteStaticFromBlock(
		ServerActiveObject *obj, u16 id, u32 mod_reason, bool no_emerge)
{
	if (!obj->m_static_exists)
		return;

	MapBlock *block;
	if (no_emerge)
		block = m_map->getBlockNoCreateNoEx(obj->m_static_block);
	else
		block = m_map->emergeBlock(obj->m_static_block, false);
	if (!block) {
		if (!no_emerge)
			errorstream << "ServerEnv: Failed to emerge block " << PP(obj->m_static_block)
					<< " when deleting static data of object from it. id=" << id << std::endl;
		return;
	}

	block->m_static_objects.remove(id);
	if (mod_reason != MOD_REASON_UNKNOWN) // Do not mark as modified if requested
		block->raiseModified(MOD_STATE_WRITE_NEEDED, mod_reason);

	obj->m_static_exists = false;
}

bool ServerEnvironment::saveStaticToBlock(
		v3s16 blockpos, u16 store_id,
		ServerActiveObject *obj, const StaticObject &s_obj,
		u32 mod_reason)
{
	MapBlock *block = nullptr;
	try {
		block = m_map->emergeBlock(blockpos);
	} catch (InvalidPositionException &e) {
		// Handled via NULL pointer
		// NOTE: emergeBlock's failure is usually determined by it
		//       actually returning NULL
	}

	if (!block) {
		errorstream << "ServerEnv: Failed to emerge block " << PP(obj->m_static_block)
				<< " when saving static data of object to it. id=" << store_id << std::endl;
		return false;
	}
	if (block->m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")) {
		warningstream << "ServerEnv: Trying to store id = " << store_id
				<< " statically but block " << PP(blockpos)
				<< " already contains "
				<< block->m_static_objects.m_stored.size()
				<< " objects." << std::endl;
		return false;
	}

	block->m_static_objects.insert(store_id, s_obj);
	if (mod_reason != MOD_REASON_UNKNOWN) // Do not mark as modified if requested
		block->raiseModified(MOD_STATE_WRITE_NEEDED, mod_reason);

	obj->m_static_exists = true;
	obj->m_static_block = blockpos;

	return true;
}

PlayerDatabase *ServerEnvironment::openPlayerDatabase(const std::string &name,
		const std::string &savedir, const Settings &conf)
{

	if (name == "sqlite3")
		return new PlayerDatabaseSQLite3(savedir);

	if (name == "dummy")
		return new Database_Dummy();
#if USE_POSTGRESQL
	if (name == "postgresql") {
		std::string connect_string;
		conf.getNoEx("pgsql_player_connection", connect_string);
		return new PlayerDatabasePostgreSQL(connect_string);
	}
#endif
	if (name == "files")
		return new PlayerDatabaseFiles(savedir + DIR_DELIM + "players");

	throw BaseException(std::string("Database backend ") + name + " not supported.");
}

bool ServerEnvironment::migratePlayersDatabase(const GameParams &game_params,
		const Settings &cmd_args)
{
	std::string migrate_to = cmd_args.get("migrate-players");
	Settings world_mt;
	std::string world_mt_path = game_params.world_path + DIR_DELIM + "world.mt";
	if (!world_mt.readConfigFile(world_mt_path.c_str())) {
		errorstream << "Cannot read world.mt!" << std::endl;
		return false;
	}

	if (!world_mt.exists("player_backend")) {
		errorstream << "Please specify your current backend in world.mt:"
			<< std::endl
			<< "	player_backend = {files|sqlite3|postgresql}"
			<< std::endl;
		return false;
	}

	std::string backend = world_mt.get("player_backend");
	if (backend == migrate_to) {
		errorstream << "Cannot migrate: new backend is same"
			<< " as the old one" << std::endl;
		return false;
	}

	const std::string players_backup_path = game_params.world_path + DIR_DELIM
		+ "players.bak";

	if (backend == "files") {
		// Create backup directory
		fs::CreateDir(players_backup_path);
	}

	try {
		PlayerDatabase *srcdb = ServerEnvironment::openPlayerDatabase(backend,
			game_params.world_path, world_mt);
		PlayerDatabase *dstdb = ServerEnvironment::openPlayerDatabase(migrate_to,
			game_params.world_path, world_mt);

		std::vector<std::string> player_list;
		srcdb->listPlayers(player_list);
		for (std::vector<std::string>::const_iterator it = player_list.begin();
			it != player_list.end(); ++it) {
			actionstream << "Migrating player " << it->c_str() << std::endl;
			RemotePlayer player(it->c_str(), NULL);
			PlayerSAO playerSAO(NULL, &player, 15000, false);

			srcdb->loadPlayer(&player, &playerSAO);

			playerSAO.finalize(&player, std::set<std::string>());
			player.setPlayerSAO(&playerSAO);

			dstdb->savePlayer(&player);

			// For files source, move player files to backup dir
			if (backend == "files") {
				fs::Rename(
					game_params.world_path + DIR_DELIM + "players" + DIR_DELIM + (*it),
					players_backup_path + DIR_DELIM + (*it));
			}
		}

		actionstream << "Successfully migrated " << player_list.size() << " players"
			<< std::endl;
		world_mt.set("player_backend", migrate_to);
		if (!world_mt.updateConfigFile(world_mt_path.c_str()))
			errorstream << "Failed to update world.mt!" << std::endl;
		else
			actionstream << "world.mt updated" << std::endl;

		// When migration is finished from file backend, remove players directory if empty
		if (backend == "files") {
			fs::DeleteSingleFileOrEmptyDirectory(game_params.world_path + DIR_DELIM
				+ "players");
		}

		delete srcdb;
		delete dstdb;

	} catch (BaseException &e) {
		errorstream << "An error occurred during migration: " << e.what() << std::endl;
		return false;
	}
	return true;
}

AuthDatabase *ServerEnvironment::openAuthDatabase(
		const std::string &name, const std::string &savedir, const Settings &conf)
{
	if (name == "sqlite3")
		return new AuthDatabaseSQLite3(savedir);

	if (name == "files")
		return new AuthDatabaseFiles(savedir);

	throw BaseException(std::string("Database backend ") + name + " not supported.");
}

bool ServerEnvironment::migrateAuthDatabase(
		const GameParams &game_params, const Settings &cmd_args)
{
	std::string migrate_to = cmd_args.get("migrate-auth");
	Settings world_mt;
	std::string world_mt_path = game_params.world_path + DIR_DELIM + "world.mt";
	if (!world_mt.readConfigFile(world_mt_path.c_str())) {
		errorstream << "Cannot read world.mt!" << std::endl;
		return false;
	}

	std::string backend = "files";
	if (world_mt.exists("auth_backend"))
		backend = world_mt.get("auth_backend");
	else
		warningstream << "No auth_backend found in world.mt, "
				"assuming \"files\"." << std::endl;

	if (backend == migrate_to) {
		errorstream << "Cannot migrate: new backend is same"
				<< " as the old one" << std::endl;
		return false;
	}

	try {
		const std::unique_ptr<AuthDatabase> srcdb(ServerEnvironment::openAuthDatabase(
				backend, game_params.world_path, world_mt));
		const std::unique_ptr<AuthDatabase> dstdb(ServerEnvironment::openAuthDatabase(
				migrate_to, game_params.world_path, world_mt));

		std::vector<std::string> names_list;
		srcdb->listNames(names_list);
		for (const std::string &name : names_list) {
			actionstream << "Migrating auth entry for " << name << std::endl;
			bool success;
			AuthEntry authEntry;
			success = srcdb->getAuth(name, authEntry);
			success = success && dstdb->createAuth(authEntry);
			if (!success)
				errorstream << "Failed to migrate " << name << std::endl;
		}

		actionstream << "Successfully migrated " << names_list.size()
				<< " auth entries" << std::endl;
		world_mt.set("auth_backend", migrate_to);
		if (!world_mt.updateConfigFile(world_mt_path.c_str()))
			errorstream << "Failed to update world.mt!" << std::endl;
		else
			actionstream << "world.mt updated" << std::endl;

		if (backend == "files") {
			// special-case files migration:
			// move auth.txt to auth.txt.bak if possible
			std::string auth_txt_path =
					game_params.world_path + DIR_DELIM + "auth.txt";
			std::string auth_bak_path = auth_txt_path + ".bak";
			if (!fs::PathExists(auth_bak_path))
				if (fs::Rename(auth_txt_path, auth_bak_path))
					actionstream << "Renamed auth.txt to auth.txt.bak"
							<< std::endl;
				else
					errorstream << "Could not rename auth.txt to "
							"auth.txt.bak" << std::endl;
			else
				warningstream << "auth.txt.bak already exists, auth.txt "
						"not renamed" << std::endl;
		}

	} catch (BaseException &e) {
		errorstream << "An error occurred during migration: " << e.what()
			    << std::endl;
		return false;
	}
	return true;
}