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 "..\Minecraft.Client\Minecraft.h"
3#include "net.minecraft.h"
4#include "net.minecraft.world.level.h"
5#include "net.minecraft.world.level.tile.h"
6#include "net.minecraft.world.level.tile.entity.h"
7#include "net.minecraft.world.entity.h"
8#include "net.minecraft.world.entity.npc.h"
9#include "net.minecraft.world.h"
10#include "HitResult.h"
11#include "SpawnEggItem.h"
12#include "Difficulty.h"
13
14
15SpawnEggItem::SpawnEggItem(int id) : Item(id)
16{
17 setMaxStackSize(16); // 4J-PB brought forward. It is 64 on PC, but we'll never be able to place that many
18 setStackedByData(true);
19 overlay = NULL;
20}
21
22wstring SpawnEggItem::getHoverName(shared_ptr<ItemInstance> itemInstance)
23{
24 wstring elementName = getDescription();
25
26 int nameId = EntityIO::getNameId(itemInstance->getAuxValue());
27 if (nameId >= 0)
28 {
29 elementName = replaceAll(elementName,L"{*CREATURE*}",app.GetString(nameId));
30 //elementName += " " + I18n.get("entity." + encodeId + ".name");
31 }
32 else
33 {
34 elementName = replaceAll(elementName,L"{*CREATURE*}",L"");
35 }
36
37 return elementName;
38}
39
40int SpawnEggItem::getColor(shared_ptr<ItemInstance> item, int spriteLayer)
41{
42 AUTO_VAR(it, EntityIO::idsSpawnableInCreative.find(item->getAuxValue()));
43 if (it != EntityIO::idsSpawnableInCreative.end())
44 {
45 EntityIO::SpawnableMobInfo *spawnableMobInfo = it->second;
46 if (spriteLayer == 0) {
47 return Minecraft::GetInstance()->getColourTable()->getColor( spawnableMobInfo->eggColor1 );
48 }
49 return Minecraft::GetInstance()->getColourTable()->getColor( spawnableMobInfo->eggColor2 );
50 }
51 return 0xffffff;
52}
53
54bool SpawnEggItem::hasMultipleSpriteLayers()
55{
56 return true;
57}
58
59Icon *SpawnEggItem::getLayerIcon(int auxValue, int spriteLayer)
60{
61 if (spriteLayer > 0)
62 {
63 return overlay;
64 }
65 return Item::getLayerIcon(auxValue, spriteLayer);
66}
67
68// 4J-PB - added for dispenser
69shared_ptr<Entity> SpawnEggItem::canSpawn(int iAuxVal, Level *level, int *piResult)
70{
71 shared_ptr<Entity> newEntity = EntityIO::newById(iAuxVal, level);
72 if (newEntity != NULL)
73 {
74 bool canSpawn = false;
75
76 switch(newEntity->GetType())
77 {
78 case eTYPE_CHICKEN:
79 if(level->canCreateMore( eTYPE_CHICKEN, Level::eSpawnType_Egg) )
80 {
81 canSpawn = true;
82 }
83 else
84 {
85 *piResult=eSpawnResult_FailTooManyChickens;
86 }
87 break;
88 case eTYPE_WOLF:
89 if(level->canCreateMore( eTYPE_WOLF, Level::eSpawnType_Egg) )
90 {
91 canSpawn = true;
92 }
93 else
94 {
95 *piResult=eSpawnResult_FailTooManyWolves;
96 }
97 break;
98 case eTYPE_VILLAGER:
99 if(level->canCreateMore( eTYPE_VILLAGER, Level::eSpawnType_Egg) )
100 {
101 canSpawn = true;
102 }
103 else
104 {
105 *piResult=eSpawnResult_FailTooManyVillagers;
106 }
107 break;
108 case eTYPE_MUSHROOMCOW:
109 if(level->canCreateMore(eTYPE_MUSHROOMCOW, Level::eSpawnType_Egg) )
110 {
111 canSpawn = true;
112 }
113 else
114 {
115 *piResult=eSpawnResult_FailTooManyMooshrooms;
116 }
117 break;
118 case eTYPE_SQUID:
119 if(level->canCreateMore( eTYPE_SQUID, Level::eSpawnType_Egg) )
120 {
121 canSpawn = true;
122 }
123 else
124 {
125 *piResult=eSpawnResult_FailTooManySquid;
126 }
127 break;
128 case eTYPE_BAT:
129 if(level->canCreateMore( eTYPE_BAT, Level::eSpawnType_Egg) )
130 {
131 canSpawn = true;
132 }
133 else
134 {
135 *piResult=eSpawnResult_FailTooManyBats;
136 }
137 break;
138 default:
139 if ( eTYPE_FLAGSET(eTYPE_ANIMALS_SPAWN_LIMIT_CHECK, newEntity->GetType()) )
140 {
141 if( level->canCreateMore( newEntity->GetType(), Level::eSpawnType_Egg ) )
142 {
143 canSpawn = true;
144 }
145 else
146 {
147 // different message for each animal
148
149 *piResult=eSpawnResult_FailTooManyPigsCowsSheepCats;
150 }
151 }
152 // 4J: Use eTYPE_ENEMY instead of monster (slimes and ghasts aren't monsters)
153 else if(newEntity->instanceof(eTYPE_ENEMY))
154 {
155 // 4J-PB - check if the player is trying to spawn an enemy in peaceful mode
156 if(level->difficulty==Difficulty::PEACEFUL)
157 {
158 *piResult=eSpawnResult_FailCantSpawnInPeaceful;
159 }
160 else if(level->canCreateMore( newEntity->GetType(), Level::eSpawnType_Egg) )
161 {
162 canSpawn = true;
163 }
164 else
165 {
166 *piResult=eSpawnResult_FailTooManyMonsters;
167 }
168 }
169#ifndef _CONTENT_PACKAGE
170 else if(app.DebugArtToolsOn())
171 {
172 canSpawn = true;
173 }
174#endif
175 break;
176 }
177
178 if(canSpawn)
179 {
180 return newEntity;
181 }
182 }
183
184 return nullptr;
185}
186
187bool SpawnEggItem::useOn(shared_ptr<ItemInstance> itemInstance, shared_ptr<Player> player, Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly)
188{
189 if (level->isClientSide)
190 {
191 return true;
192 }
193
194 int tile = level->getTile(x, y, z);
195
196#ifndef _CONTENT_PACKAGE
197 if(app.DebugArtToolsOn() && tile == Tile::mobSpawner_Id)
198 {
199 // 4J Stu - Force adding this as a tile update
200 level->removeTile(x,y,z);
201 level->setTileAndData(x,y,z,Tile::mobSpawner_Id, 0, Tile::UPDATE_ALL);
202 shared_ptr<MobSpawnerTileEntity> mste = dynamic_pointer_cast<MobSpawnerTileEntity>( level->getTileEntity(x,y,z) );
203 if(mste != NULL)
204 {
205 mste->setEntityId( EntityIO::getEncodeId(itemInstance->getAuxValue()) );
206 return true;
207 }
208 }
209#endif
210
211 x += Facing::STEP_X[face];
212 y += Facing::STEP_Y[face];
213 z += Facing::STEP_Z[face];
214
215 double yOff = 0;
216 if (face == Facing::UP && (Tile::tiles[tile] != NULL && Tile::tiles[tile]->getRenderShape() == Tile::SHAPE_FENCE))
217 {
218 // special case
219 yOff = .5;
220 }
221
222 int iResult=0;
223 shared_ptr<Entity> result = spawnMobAt(level, itemInstance->getAuxValue(), x + .5, y + yOff, z + .5, &iResult);
224
225 if(bTestUseOnOnly)
226 {
227 return result != NULL;
228 }
229
230 if (result != NULL)
231 {
232 // 4J-JEV: SetCustomName is a method for Mob not LivingEntity; so change instanceof to check for Mobs.
233 if ( result->instanceof(eTYPE_MOB) && itemInstance->hasCustomHoverName() )
234 {
235 dynamic_pointer_cast<Mob>(result)->setCustomName(itemInstance->getHoverName());
236 }
237 if ( !player->abilities.instabuild )
238 {
239 itemInstance->count--;
240 }
241 }
242 else
243 {
244 DisplaySpawnError(player, iResult);
245 }
246
247 return true;
248}
249
250shared_ptr<ItemInstance> SpawnEggItem::use(shared_ptr<ItemInstance> itemInstance, Level *level, shared_ptr<Player> player)
251{
252 if (level->isClientSide) return itemInstance;
253
254 HitResult *hr = getPlayerPOVHitResult(level, player, true);
255 if (hr == NULL)
256 {
257 delete hr;
258 return itemInstance;
259 }
260
261 if (hr->type == HitResult::TILE)
262 {
263 int xt = hr->x;
264 int yt = hr->y;
265 int zt = hr->z;
266
267 if (!level->mayInteract(player, xt, yt, zt,0))
268 {
269 delete hr;
270 return itemInstance;
271 }
272 if (!player->mayUseItemAt(xt, yt, zt, hr->f, itemInstance)) return itemInstance;
273
274 if (level->getMaterial(xt, yt, zt) == Material::water)
275 {
276 int iResult=0;
277 shared_ptr<Entity> result = spawnMobAt(level, itemInstance->getAuxValue(), xt, yt, zt, &iResult);
278 if (result != NULL)
279 {
280 // 4J-JEV: SetCustomName is a method for Mob not LivingEntity; so change instanceof to check for Mobs.
281 if ( result->instanceof(eTYPE_MOB) && itemInstance->hasCustomHoverName() )
282 {
283 dynamic_pointer_cast<Mob>(result)->setCustomName(itemInstance->getHoverName());
284 }
285 if (!player->abilities.instabuild)
286 {
287 itemInstance->count--;
288 }
289 }
290 else
291 {
292 SpawnEggItem::DisplaySpawnError(player, iResult);
293 }
294 }
295 }
296 return itemInstance;
297}
298
299shared_ptr<Entity> SpawnEggItem::spawnMobAt(Level *level, int auxVal, double x, double y, double z, int *piResult)
300{
301 int mobId = auxVal;
302 int extraData = 0;
303
304 //4J Stu - Enable spawning specific entity sub-types
305 mobId = auxVal & 0xFFF;
306 extraData = auxVal >> 12;
307
308 if (EntityIO::idsSpawnableInCreative.find(mobId) == EntityIO::idsSpawnableInCreative.end())
309 {
310 return nullptr;
311 }
312
313 shared_ptr<Entity> newEntity = nullptr;
314
315 for (int i = 0; i < SPAWN_COUNT; i++)
316 {
317 newEntity = canSpawn(mobId, level, piResult);
318
319 // 4J-JEV: DynCasting to Mob not LivingEntity; so change instanceof to check for Mobs.
320 if ( newEntity != NULL && newEntity->instanceof(eTYPE_MOB) )
321 {
322 shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(newEntity);
323 newEntity->moveTo(x, y, z, Mth::wrapDegrees(level->random->nextFloat() * 360), 0);
324 newEntity->setDespawnProtected(); // 4J added, default to being protected against despawning (has to be done after initial position is set)
325 mob->yHeadRot = mob->yRot;
326 mob->yBodyRot = mob->yRot;
327
328 mob->finalizeMobSpawn(NULL, extraData);
329 level->addEntity(newEntity);
330 mob->playAmbientSound();
331 }
332 }
333
334 return newEntity;
335}
336
337void SpawnEggItem::registerIcons(IconRegister *iconRegister)
338{
339 Item::registerIcons(iconRegister);
340 overlay = iconRegister->registerIcon(getIconName() + L"_overlay");
341}
342
343void SpawnEggItem::DisplaySpawnError(shared_ptr<Player> player, int result)
344{
345 // some negative sound effect?
346 //level->levelEvent(LevelEvent::SOUND_CLICK_FAIL, x, y, z, 0);
347 switch(result)
348 {
349 case eSpawnResult_FailTooManyPigsCowsSheepCats:
350 player->displayClientMessage(IDS_MAX_PIGS_SHEEP_COWS_CATS_SPAWNED );
351 break;
352 case eSpawnResult_FailTooManyChickens:
353 player->displayClientMessage(IDS_MAX_CHICKENS_SPAWNED );
354 break;
355 case eSpawnResult_FailTooManySquid:
356 player->displayClientMessage(IDS_MAX_SQUID_SPAWNED );
357 break;
358 case eSpawnResult_FailTooManyBats:
359 player->displayClientMessage(IDS_MAX_BATS_SPAWNED);
360 break;
361 case eSpawnResult_FailTooManyWolves:
362 player->displayClientMessage(IDS_MAX_WOLVES_SPAWNED );
363 break;
364 case eSpawnResult_FailTooManyMooshrooms:
365 player->displayClientMessage(IDS_MAX_MOOSHROOMS_SPAWNED );
366 break;
367 case eSpawnResult_FailTooManyMonsters:
368 player->displayClientMessage(IDS_MAX_ENEMIES_SPAWNED );
369 break;
370 case eSpawnResult_FailTooManyVillagers:
371 player->displayClientMessage(IDS_MAX_VILLAGERS_SPAWNED );
372 break;
373 case eSpawnResult_FailCantSpawnInPeaceful:
374 player->displayClientMessage(IDS_CANT_SPAWN_IN_PEACEFUL );
375 break;
376
377 }
378}