1 /*
2 Minetest
3 Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #pragma once
21 
22 #include <map>
23 #include <mutex>
24 #include "network/networkprotocol.h"
25 #include "irr_v3d.h"
26 #include "util/container.h"
27 #include "mapgen/mapgen.h" // for MapgenParams
28 #include "map.h"
29 
30 #define BLOCK_EMERGE_ALLOW_GEN   (1 << 0)
31 #define BLOCK_EMERGE_FORCE_QUEUE (1 << 1)
32 
33 #define EMERGE_DBG_OUT(x) {                            \
34 	if (enable_mapgen_debug_info)                      \
35 		infostream << "EmergeThread: " x << std::endl; \
36 }
37 
38 class EmergeThread;
39 class NodeDefManager;
40 class Settings;
41 
42 class BiomeManager;
43 class OreManager;
44 class DecorationManager;
45 class SchematicManager;
46 class Server;
47 class ModApiMapgen;
48 
49 // Structure containing inputs/outputs for chunk generation
50 struct BlockMakeData {
51 	MMVManip *vmanip = nullptr;
52 	u64 seed = 0;
53 	v3s16 blockpos_min;
54 	v3s16 blockpos_max;
55 	UniqueQueue<v3s16> transforming_liquid;
56 	const NodeDefManager *nodedef = nullptr;
57 
58 	BlockMakeData() = default;
59 
~BlockMakeDataBlockMakeData60 	~BlockMakeData() { delete vmanip; }
61 };
62 
63 // Result from processing an item on the emerge queue
64 enum EmergeAction {
65 	EMERGE_CANCELLED,
66 	EMERGE_ERRORED,
67 	EMERGE_FROM_MEMORY,
68 	EMERGE_FROM_DISK,
69 	EMERGE_GENERATED,
70 };
71 
72 // Callback
73 typedef void (*EmergeCompletionCallback)(
74 	v3s16 blockpos, EmergeAction action, void *param);
75 
76 typedef std::vector<
77 	std::pair<
78 		EmergeCompletionCallback,
79 		void *
80 	>
81 > EmergeCallbackList;
82 
83 struct BlockEmergeData {
84 	u16 peer_requested;
85 	u16 flags;
86 	EmergeCallbackList callbacks;
87 };
88 
89 class EmergeParams {
90 	friend class EmergeManager;
91 public:
92 	EmergeParams() = delete;
93 	~EmergeParams();
94 	DISABLE_CLASS_COPY(EmergeParams);
95 
96 	const NodeDefManager *ndef; // shared
97 	bool enable_mapgen_debug_info;
98 
99 	u32 gen_notify_on;
100 	const std::set<u32> *gen_notify_on_deco_ids; // shared
101 
102 	BiomeManager *biomemgr;
103 	OreManager *oremgr;
104 	DecorationManager *decomgr;
105 	SchematicManager *schemmgr;
106 
107 private:
108 	EmergeParams(EmergeManager *parent, const BiomeManager *biomemgr,
109 		const OreManager *oremgr, const DecorationManager *decomgr,
110 		const SchematicManager *schemmgr);
111 };
112 
113 class EmergeManager {
114 	/* The mod API needs unchecked access to allow:
115 	 * - using decomgr or oremgr to place decos/ores
116 	 * - using schemmgr to load and place schematics
117 	 */
118 	friend class ModApiMapgen;
119 public:
120 	const NodeDefManager *ndef;
121 	bool enable_mapgen_debug_info;
122 
123 	// Generation Notify
124 	u32 gen_notify_on = 0;
125 	std::set<u32> gen_notify_on_deco_ids;
126 
127 	// Parameters passed to mapgens owned by ServerMap
128 	// TODO(hmmmm): Remove this after mapgen helper methods using them
129 	// are moved to ServerMap
130 	MapgenParams *mgparams;
131 
132 	// Hackish workaround:
133 	// For now, EmergeManager must hold onto a ptr to the Map's setting manager
134 	// since the Map can only be accessed through the Environment, and the
135 	// Environment is not created until after script initialization.
136 	MapSettingsManager *map_settings_mgr;
137 
138 	// Methods
139 	EmergeManager(Server *server);
140 	~EmergeManager();
141 	DISABLE_CLASS_COPY(EmergeManager);
142 
143 	// no usage restrictions
getBiomeManager()144 	const BiomeManager *getBiomeManager() const { return biomemgr; }
getOreManager()145 	const OreManager *getOreManager() const { return oremgr; }
getDecorationManager()146 	const DecorationManager *getDecorationManager() const { return decomgr; }
getSchematicManager()147 	const SchematicManager *getSchematicManager() const { return schemmgr; }
148 	// only usable before mapgen init
149 	BiomeManager *getWritableBiomeManager();
150 	OreManager *getWritableOreManager();
151 	DecorationManager *getWritableDecorationManager();
152 	SchematicManager *getWritableSchematicManager();
153 
154 	void initMapgens(MapgenParams *mgparams);
155 
156 	void startThreads();
157 	void stopThreads();
158 	bool isRunning();
159 
160 	bool enqueueBlockEmerge(
161 		session_t peer_id,
162 		v3s16 blockpos,
163 		bool allow_generate,
164 		bool ignore_queue_limits=false);
165 
166 	bool enqueueBlockEmergeEx(
167 		v3s16 blockpos,
168 		session_t peer_id,
169 		u16 flags,
170 		EmergeCompletionCallback callback,
171 		void *callback_param);
172 
173 	v3s16 getContainingChunk(v3s16 blockpos);
174 
175 	Mapgen *getCurrentMapgen();
176 
177 	// Mapgen helpers methods
178 	int getSpawnLevelAtPoint(v2s16 p);
179 	int getGroundLevelAtPoint(v2s16 p);
180 	bool isBlockUnderground(v3s16 blockpos);
181 
182 	static v3s16 getContainingChunk(v3s16 blockpos, s16 chunksize);
183 
184 private:
185 	std::vector<Mapgen *> m_mapgens;
186 	std::vector<EmergeThread *> m_threads;
187 	bool m_threads_active = false;
188 
189 	std::mutex m_queue_mutex;
190 	std::map<v3s16, BlockEmergeData> m_blocks_enqueued;
191 	std::unordered_map<u16, u16> m_peer_queue_count;
192 
193 	u16 m_qlimit_total;
194 	u16 m_qlimit_diskonly;
195 	u16 m_qlimit_generate;
196 
197 	// Managers of various map generation-related components
198 	// Note that each Mapgen gets a copy(!) of these to work with
199 	BiomeManager *biomemgr;
200 	OreManager *oremgr;
201 	DecorationManager *decomgr;
202 	SchematicManager *schemmgr;
203 
204 	// Requires m_queue_mutex held
205 	EmergeThread *getOptimalThread();
206 
207 	bool pushBlockEmergeData(
208 		v3s16 pos,
209 		u16 peer_requested,
210 		u16 flags,
211 		EmergeCompletionCallback callback,
212 		void *callback_param,
213 		bool *entry_already_exists);
214 
215 	bool popBlockEmergeData(v3s16 pos, BlockEmergeData *bedata);
216 
217 	friend class EmergeThread;
218 };
219