From b691c43c44ff180d10e7d4a9afc83b98551ff586 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 1 Mar 2026 12:16:08 +0800 Subject: Initial commit --- Minecraft.World/MonsterPlacerItem.cpp | 291 ++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 Minecraft.World/MonsterPlacerItem.cpp (limited to 'Minecraft.World/MonsterPlacerItem.cpp') diff --git a/Minecraft.World/MonsterPlacerItem.cpp b/Minecraft.World/MonsterPlacerItem.cpp new file mode 100644 index 00000000..a2970033 --- /dev/null +++ b/Minecraft.World/MonsterPlacerItem.cpp @@ -0,0 +1,291 @@ +#include "stdafx.h" +#include "..\Minecraft.Client\Minecraft.h" +#include "net.minecraft.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.level.tile.h" +#include "net.minecraft.world.level.tile.entity.h" +#include "net.minecraft.world.entity.h" +#include "net.minecraft.world.entity.npc.h" +#include "net.minecraft.world.h" +#include "MonsterPlacerItem.h" +#include "Difficulty.h" + + +MonsterPlacerItem::MonsterPlacerItem(int id) : Item(id) +{ + setMaxStackSize(16); // 4J-PB brought forward. It is 64 on PC, but we'll never be able to place that many + setStackedByData(true); + overlay = NULL; +} + +wstring MonsterPlacerItem::getHoverName(shared_ptr itemInstance) +{ + wstring elementName = getDescription(); + + int nameId = EntityIO::getNameId(itemInstance->getAuxValue()); + if (nameId >= 0) + { + elementName = replaceAll(elementName,L"{*CREATURE*}",app.GetString(nameId)); + //elementName += " " + I18n.get("entity." + encodeId + ".name"); + } + else + { + elementName = replaceAll(elementName,L"{*CREATURE*}",L""); + } + + return elementName; +} + +int MonsterPlacerItem::getColor(shared_ptr item, int spriteLayer) +{ + AUTO_VAR(it, EntityIO::idsSpawnableInCreative.find(item->getAuxValue())); + if (it != EntityIO::idsSpawnableInCreative.end()) + { + EntityIO::SpawnableMobInfo *spawnableMobInfo = it->second; + if (spriteLayer == 0) { + return Minecraft::GetInstance()->getColourTable()->getColor( spawnableMobInfo->eggColor1 ); + } + return Minecraft::GetInstance()->getColourTable()->getColor( spawnableMobInfo->eggColor2 ); + } + return 0xffffff; +} + +bool MonsterPlacerItem::hasMultipleSpriteLayers() +{ + return true; +} + +Icon *MonsterPlacerItem::getLayerIcon(int auxValue, int spriteLayer) +{ + if (spriteLayer > 0) + { + return overlay; + } + return Item::getLayerIcon(auxValue, spriteLayer); +} + +// 4J-PB - added for dispenser +shared_ptr MonsterPlacerItem::canSpawn(int iAuxVal, Level *level, int *piResult) +{ + shared_ptr newEntity = EntityIO::newById(iAuxVal, level); + if (newEntity != NULL) + { + bool canSpawn = false; + + switch(newEntity->GetType()) + { + case eTYPE_CHICKEN: + if(level->canCreateMore( eTYPE_CHICKEN, Level::eSpawnType_Egg) ) + { + canSpawn = true; + } + else + { + *piResult=eSpawnResult_FailTooManyChickens; + } + break; + case eTYPE_WOLF: + if(level->canCreateMore( eTYPE_WOLF, Level::eSpawnType_Egg) ) + { + canSpawn = true; + } + else + { + *piResult=eSpawnResult_FailTooManyWolves; + } + break; + case eTYPE_VILLAGER: + if(level->canCreateMore( eTYPE_VILLAGER, Level::eSpawnType_Egg) ) + { + canSpawn = true; + } + else + { + *piResult=eSpawnResult_FailTooManyVillagers; + } + break; + case eTYPE_MUSHROOMCOW: + if(level->canCreateMore(eTYPE_MUSHROOMCOW, Level::eSpawnType_Egg) ) + { + canSpawn = true; + } + else + { + *piResult=eSpawnResult_FailTooManyMooshrooms; + } + break; + case eTYPE_SQUID: + if(level->canCreateMore( eTYPE_SQUID, Level::eSpawnType_Egg) ) + { + canSpawn = true; + } + else + { + *piResult=eSpawnResult_FailTooManySquid; + } + break; + default: + if( (newEntity->GetType() & eTYPE_ANIMALS_SPAWN_LIMIT_CHECK) == eTYPE_ANIMALS_SPAWN_LIMIT_CHECK) + { + if( level->canCreateMore( newEntity->GetType(), Level::eSpawnType_Egg ) ) + { + canSpawn = true; + } + else + { + // different message for each animal + + *piResult=eSpawnResult_FailTooManyPigsCowsSheepCats; + } + } + else if( (newEntity->GetType() & eTYPE_MONSTER) == eTYPE_MONSTER) + { + // 4J-PB - check if the player is trying to spawn an enemy in peaceful mode + if(level->difficulty==Difficulty::PEACEFUL) + { + *piResult=eSpawnResult_FailCantSpawnInPeaceful; + } + else if(level->canCreateMore( newEntity->GetType(), Level::eSpawnType_Egg) ) + { + canSpawn = true; + } + else + { + *piResult=eSpawnResult_FailTooManyMonsters; + } + } + break; + } + + if(canSpawn) + { + return newEntity; + } + } + + return nullptr; +} + +bool MonsterPlacerItem::useOn(shared_ptr itemInstance, shared_ptr player, Level *level, int x, int y, int z, int face, float clickX, float clickY, float clickZ, bool bTestUseOnOnly) +{ + if (level->isClientSide) + { + return true; + } + + int tile = level->getTile(x, y, z); + +#ifndef _CONTENT_PACKAGE + if(app.DebugSettingsOn() && tile == Tile::mobSpawner_Id) + { + // 4J Stu - Force adding this as a tile update + level->setTile(x,y,z,0); + level->setTile(x,y,z,Tile::mobSpawner_Id); + shared_ptr mste = dynamic_pointer_cast( level->getTileEntity(x,y,z) ); + if(mste != NULL) + { + mste->setEntityId( EntityIO::getEncodeId(itemInstance->getAuxValue()) ); + return true; + } + } +#endif + + x += Facing::STEP_X[face]; + y += Facing::STEP_Y[face]; + z += Facing::STEP_Z[face]; + + double yOff = 0; + // 4J-PB - missing parentheses added + if (face == Facing::UP && (tile == Tile::fence_Id || tile == Tile::netherFence_Id)) + { + // special case + yOff = .5; + } + + int iResult=0; + bool spawned = spawnMobAt(level, itemInstance->getAuxValue(), x + .5, y + yOff, z + .5, &iResult) != NULL; + + if(bTestUseOnOnly) + { + return spawned; + } + + if (spawned) + { + if (!player->abilities.instabuild) + { + itemInstance->count--; + } + } + else + { + // some negative sound effect? + //level->levelEvent(LevelEvent::SOUND_CLICK_FAIL, x, y, z, 0); + switch(iResult) + { + case eSpawnResult_FailTooManyPigsCowsSheepCats: + player->displayClientMessage(IDS_MAX_PIGS_SHEEP_COWS_CATS_SPAWNED ); + break; + case eSpawnResult_FailTooManyChickens: + player->displayClientMessage(IDS_MAX_CHICKENS_SPAWNED ); + break; + case eSpawnResult_FailTooManySquid: + player->displayClientMessage(IDS_MAX_SQUID_SPAWNED ); + break; + case eSpawnResult_FailTooManyWolves: + player->displayClientMessage(IDS_MAX_WOLVES_SPAWNED ); + break; + case eSpawnResult_FailTooManyMooshrooms: + player->displayClientMessage(IDS_MAX_MOOSHROOMS_SPAWNED ); + break; + case eSpawnResult_FailTooManyMonsters: + player->displayClientMessage(IDS_MAX_ENEMIES_SPAWNED ); + break; + case eSpawnResult_FailTooManyVillagers: + player->displayClientMessage(IDS_MAX_VILLAGERS_SPAWNED ); + break; + case eSpawnResult_FailCantSpawnInPeaceful: + player->displayClientMessage(IDS_CANT_SPAWN_IN_PEACEFUL ); + break; + + } + } + + return true; +} + +shared_ptr MonsterPlacerItem::spawnMobAt(Level *level, int mobId, double x, double y, double z, int *piResult) +{ + if (EntityIO::idsSpawnableInCreative.find(mobId) == EntityIO::idsSpawnableInCreative.end()) + { + return nullptr; + } + + shared_ptr newEntity = nullptr; + + for (int i = 0; i < SPAWN_COUNT; i++) + { + newEntity = canSpawn(mobId, level, piResult); + + shared_ptr mob = dynamic_pointer_cast(newEntity); + if (mob) + { + newEntity->moveTo(x, y, z, Mth::wrapDegrees(level->random->nextFloat() * 360), 0); + newEntity->setDespawnProtected(); // 4J added, default to being protected against despawning (has to be done after initial position is set) + mob->yHeadRot = mob->yRot; + mob->yBodyRot = mob->yRot; + + mob->finalizeMobSpawn(); + level->addEntity(newEntity); + mob->playAmbientSound(); + } + } + + return newEntity; +} + +void MonsterPlacerItem::registerIcons(IconRegister *iconRegister) +{ + Item::registerIcons(iconRegister); + overlay = iconRegister->registerIcon(L"monsterPlacer_overlay"); +} -- cgit v1.2.3