the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2#include "net.minecraft.world.entity.h"
3#include "net.minecraft.world.entity.item.h"
4#include "net.minecraft.world.level.h"
5#include "net.minecraft.world.level.tile.h"
6#include "net.minecraft.world.phys.h"
7#include "BaseMobSpawner.h"
8
9BaseMobSpawner::BaseMobSpawner()
10{
11 spawnPotentials = NULL;
12 spawnDelay = 20;
13 entityId = L"Pig";
14 nextSpawnData = NULL;
15 spin = oSpin = 0.0;
16
17 minSpawnDelay = SharedConstants::TICKS_PER_SECOND * 10;
18 maxSpawnDelay = SharedConstants::TICKS_PER_SECOND * 40;
19 spawnCount = 4;
20 displayEntity = nullptr;
21 maxNearbyEntities = 6;
22 requiredPlayerRange = 16;
23 spawnRange = 4;
24}
25
26BaseMobSpawner::~BaseMobSpawner()
27{
28 if(spawnPotentials)
29 {
30 for(AUTO_VAR(it,spawnPotentials->begin()); it != spawnPotentials->end(); ++it)
31 {
32 delete *it;
33 }
34 delete spawnPotentials;
35 }
36}
37
38wstring BaseMobSpawner::getEntityId()
39{
40 if (getNextSpawnData() == NULL)
41 {
42 if (entityId.compare(L"Minecart") == 0)
43 {
44 entityId = L"MinecartRideable";
45 }
46 return entityId;
47 }
48 else
49 {
50 return getNextSpawnData()->type;
51 }
52}
53
54void BaseMobSpawner::setEntityId(const wstring &entityId)
55{
56 this->entityId = entityId;
57}
58
59bool BaseMobSpawner::isNearPlayer()
60{
61 return getLevel()->getNearestPlayer(getX() + 0.5, getY() + 0.5, getZ() + 0.5, requiredPlayerRange) != NULL;
62}
63
64void BaseMobSpawner::tick()
65{
66 if (!isNearPlayer())
67 {
68 return;
69 }
70
71 if (getLevel()->isClientSide)
72 {
73 double xP = getX() + getLevel()->random->nextFloat();
74 double yP = getY() + getLevel()->random->nextFloat();
75 double zP = getZ() + getLevel()->random->nextFloat();
76 getLevel()->addParticle(eParticleType_smoke, xP, yP, zP, 0, 0, 0);
77 getLevel()->addParticle(eParticleType_flame, xP, yP, zP, 0, 0, 0);
78
79 if (spawnDelay > 0) spawnDelay--;
80 oSpin = spin;
81 spin = (int)(spin + 1000 / (spawnDelay + 200.0f)) % 360;
82 }
83 else
84 {
85 if (spawnDelay == -1) delay();
86
87 if (spawnDelay > 0)
88 {
89 spawnDelay--;
90 return;
91 }
92
93 bool _delay = false;
94
95 for (int c = 0; c < spawnCount; c++)
96 {
97 shared_ptr<Entity> entity = EntityIO::newEntity(getEntityId(), getLevel());
98 if (entity == NULL) return;
99
100 int nearBy = getLevel()->getEntitiesOfClass( typeid(entity.get()), AABB::newTemp(getX(), getY(), getZ(), getX() + 1, getY() + 1, getZ() + 1)->grow(spawnRange * 2, 4, spawnRange * 2))->size();
101 if (nearBy >= maxNearbyEntities)
102 {
103 delay();
104 return;
105 }
106
107 double xp = getX() + (getLevel()->random->nextDouble() - getLevel()->random->nextDouble()) * spawnRange;
108 double yp = getY() + getLevel()->random->nextInt(3) - 1;
109 double zp = getZ() + (getLevel()->random->nextDouble() - getLevel()->random->nextDouble()) * spawnRange;
110 shared_ptr<Mob> mob = entity->instanceof(eTYPE_MOB) ? dynamic_pointer_cast<Mob>( entity ) : nullptr;
111
112 entity->moveTo(xp, yp, zp, getLevel()->random->nextFloat() * 360, 0);
113
114 if (mob == NULL || mob->canSpawn())
115 {
116 loadDataAndAddEntity(entity);
117 getLevel()->levelEvent(LevelEvent::PARTICLES_MOBTILE_SPAWN, getX(), getY(), getZ(), 0);
118
119 if (mob != NULL)
120 {
121 mob->spawnAnim();
122 }
123
124 _delay = true;
125 }
126 }
127
128 if (_delay) delay();
129 }
130}
131
132shared_ptr<Entity> BaseMobSpawner::loadDataAndAddEntity(shared_ptr<Entity> entity)
133{
134 if (getNextSpawnData() != NULL)
135 {
136 CompoundTag *data = new CompoundTag();
137 entity->save(data);
138
139 vector<Tag *> *tags = getNextSpawnData()->tag->getAllTags();
140 for (AUTO_VAR(it, tags->begin()); it != tags->end(); ++it)
141 {
142 Tag *tag = *it;
143 data->put(tag->getName(), tag->copy());
144 }
145 delete tags;
146
147 entity->load(data);
148 if (entity->level != NULL) entity->level->addEntity(entity);
149
150 // add mounts
151 shared_ptr<Entity> rider = entity;
152 while (data->contains(Entity::RIDING_TAG))
153 {
154 CompoundTag *ridingTag = data->getCompound(Entity::RIDING_TAG);
155 shared_ptr<Entity> mount = EntityIO::newEntity(ridingTag->getString(L"id"), entity->level);
156 if (mount != NULL)
157 {
158 CompoundTag *mountData = new CompoundTag();
159 mount->save(mountData);
160
161 vector<Tag *> *ridingTags = ridingTag->getAllTags();
162 for (AUTO_VAR(it, ridingTags->begin()); it != ridingTags->end(); ++it)
163 {
164 Tag *tag = *it;
165 mountData->put(tag->getName(), tag->copy());
166 }
167 delete ridingTags;
168 mount->load(mountData);
169 mount->moveTo(rider->x, rider->y, rider->z, rider->yRot, rider->xRot);
170
171 if (entity->level != NULL) entity->level->addEntity(mount);
172 rider->ride(mount);
173 }
174 rider = mount;
175 data = ridingTag;
176 }
177
178 }
179 else if (entity->instanceof(eTYPE_LIVINGENTITY) && entity->level != NULL)
180 {
181 dynamic_pointer_cast<Mob>( entity )->finalizeMobSpawn(NULL);
182 getLevel()->addEntity(entity);
183 }
184
185 return entity;
186}
187
188void BaseMobSpawner::delay()
189{
190 if (maxSpawnDelay <= minSpawnDelay)
191 {
192 spawnDelay = minSpawnDelay;
193 }
194 else
195 {
196 spawnDelay = minSpawnDelay + getLevel()->random->nextInt(maxSpawnDelay - minSpawnDelay);
197 }
198
199 if ( (spawnPotentials != NULL) && (spawnPotentials->size() > 0) )
200 {
201 setNextSpawnData( (SpawnData*) WeighedRandom::getRandomItem((Random*)getLevel()->random, (vector<WeighedRandomItem*>*)spawnPotentials) );
202 }
203
204 broadcastEvent(EVENT_SPAWN);
205}
206
207void BaseMobSpawner::load(CompoundTag *tag)
208{
209 entityId = tag->getString(L"EntityId");
210 spawnDelay = tag->getShort(L"Delay");
211
212 if (tag->contains(L"SpawnPotentials"))
213 {
214 spawnPotentials = new vector<SpawnData *>();
215 ListTag<CompoundTag> *potentials = (ListTag<CompoundTag> *) tag->getList(L"SpawnPotentials");
216
217 for (int i = 0; i < potentials->size(); i++)
218 {
219 spawnPotentials->push_back(new SpawnData(potentials->get(i)));
220 }
221 }
222 else
223 {
224 spawnPotentials = NULL;
225 }
226
227 if (tag->contains(L"SpawnData"))
228 {
229 setNextSpawnData(new SpawnData(tag->getCompound(L"SpawnData"), entityId));
230 }
231 else
232 {
233 setNextSpawnData(NULL);
234 }
235
236 if (tag->contains(L"MinSpawnDelay"))
237 {
238 minSpawnDelay = tag->getShort(L"MinSpawnDelay");
239 maxSpawnDelay = tag->getShort(L"MaxSpawnDelay");
240 spawnCount = tag->getShort(L"SpawnCount");
241 }
242
243 if (tag->contains(L"MaxNearbyEntities"))
244 {
245 maxNearbyEntities = tag->getShort(L"MaxNearbyEntities");
246 requiredPlayerRange = tag->getShort(L"RequiredPlayerRange");
247 }
248
249 if (tag->contains(L"SpawnRange")) spawnRange = tag->getShort(L"SpawnRange");
250
251 if (getLevel() != NULL && getLevel()->isClientSide)
252 {
253 displayEntity = nullptr;
254 }
255}
256
257void BaseMobSpawner::save(CompoundTag *tag)
258{
259 tag->putString(L"EntityId", getEntityId());
260 tag->putShort(L"Delay", (short) spawnDelay);
261 tag->putShort(L"MinSpawnDelay", (short) minSpawnDelay);
262 tag->putShort(L"MaxSpawnDelay", (short) maxSpawnDelay);
263 tag->putShort(L"SpawnCount", (short) spawnCount);
264 tag->putShort(L"MaxNearbyEntities", (short) maxNearbyEntities);
265 tag->putShort(L"RequiredPlayerRange", (short) requiredPlayerRange);
266 tag->putShort(L"SpawnRange", (short) spawnRange);
267
268 if (getNextSpawnData() != NULL)
269 {
270 tag->putCompound(L"SpawnData", (CompoundTag *) getNextSpawnData()->tag->copy());
271 }
272
273 if (getNextSpawnData() != NULL || (spawnPotentials != NULL && spawnPotentials->size() > 0))
274 {
275 ListTag<CompoundTag> *list = new ListTag<CompoundTag>();
276
277 if (spawnPotentials != NULL && spawnPotentials->size() > 0)
278 {
279 for (AUTO_VAR(it, spawnPotentials->begin()); it != spawnPotentials->end(); ++it)
280 {
281 SpawnData *data = *it;
282 list->add(data->save());
283 }
284 }
285 else
286 {
287 list->add(getNextSpawnData()->save());
288 }
289
290 tag->put(L"SpawnPotentials", list);
291 }
292}
293
294shared_ptr<Entity> BaseMobSpawner::getDisplayEntity()
295{
296 if (displayEntity == NULL)
297 {
298 shared_ptr<Entity> e = EntityIO::newEntity(getEntityId(), NULL);
299 e = loadDataAndAddEntity(e);
300 displayEntity = e;
301 }
302
303 return displayEntity;
304}
305
306bool BaseMobSpawner::onEventTriggered(int id)
307{
308 if (id == EVENT_SPAWN && getLevel()->isClientSide)
309 {
310 spawnDelay = minSpawnDelay;
311 return true;
312 }
313 return false;
314}
315
316BaseMobSpawner::SpawnData *BaseMobSpawner::getNextSpawnData()
317{
318 return nextSpawnData;
319}
320
321void BaseMobSpawner::setNextSpawnData(SpawnData *nextSpawnData)
322{
323 this->nextSpawnData = nextSpawnData;
324}
325
326BaseMobSpawner::SpawnData::SpawnData(CompoundTag *base) : WeighedRandomItem(base->getInt(L"Weight"))
327{
328 CompoundTag *tag = base->getCompound(L"Properties");
329 wstring _type = base->getString(L"Type");
330
331 if (_type.compare(L"Minecart") == 0)
332 {
333 if (tag != NULL)
334 {
335 switch (tag->getInt(L"Type"))
336 {
337 case Minecart::TYPE_CHEST:
338 type = L"MinecartChest";
339 break;
340 case Minecart::TYPE_FURNACE:
341 type = L"MinecartFurnace";
342 break;
343 case Minecart::TYPE_RIDEABLE:
344 type = L"MinecartRideable";
345 break;
346 }
347 }
348 else
349 {
350 type = L"MinecartRideable";
351 }
352 }
353
354 this->tag = tag;
355 this->type = _type;
356}
357
358BaseMobSpawner::SpawnData::SpawnData(CompoundTag *tag, wstring _type) : WeighedRandomItem(1)
359{
360 if (_type.compare(L"Minecart") == 0)
361 {
362 if (tag != NULL)
363 {
364 switch (tag->getInt(L"Type"))
365 {
366 case Minecart::TYPE_CHEST:
367 _type = L"MinecartChest";
368 break;
369 case Minecart::TYPE_FURNACE:
370 _type = L"MinecartFurnace";
371 break;
372 case Minecart::TYPE_RIDEABLE:
373 _type = L"MinecartRideable";
374 break;
375 }
376 }
377 else
378 {
379 _type = L"MinecartRideable";
380 }
381 }
382
383 this->tag = tag;
384 this->type = _type;
385}
386
387BaseMobSpawner::SpawnData::~SpawnData()
388{
389 delete tag;
390}
391
392CompoundTag *BaseMobSpawner::SpawnData::save()
393{
394 CompoundTag *result = new CompoundTag();
395
396 result->putCompound(L"Properties", tag);
397 result->putString(L"Type", type);
398 result->putInt(L"Weight", randomWeight);
399
400 return result;
401}