This commit is contained in:
Alexandra-Myers 2026-04-21 20:03:58 -04:00 committed by GitHub
commit b71061e926
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 764 additions and 686 deletions

View file

@ -45,9 +45,10 @@
#define GAME_HOST_OPTION_BITMASK_DOTILEDROPS 0x08000000
#define GAME_HOST_OPTION_BITMASK_NATURALREGEN 0x10000000
#define GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE 0x20000000
#define GAME_HOST_OPTION_BITMASK_NOMOBCAP 0x40000000
#define GAME_HOST_OPTION_BITMASK_ALL 0xFFFFFFFF
#define GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT 20
#define GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT 20
enum EGameHostOptionWorldSize
{

View file

@ -648,6 +648,7 @@ enum eGameHostOption
eGameHostOption_DoTileDrops,
eGameHostOption_NaturalRegeneration,
eGameHostOption_DoDaylightCycle,
eGameHostOption_NoMobCap,
};
// 4J-PB - If any new DLC items are added to the TMSFiles, this array needs updated

View file

@ -8172,10 +8172,21 @@ void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOpt
}
break;
case eGameHostOption_WorldSize:
// clear the difficulty first
// Clear the original value first
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE;
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
break;
case eGameHostOption_NoMobCap:
if(uiVal!=0)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_NOMOBCAP;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NOMOBCAP;
}
break;
case eGameHostOption_All:
uiHostSettings=uiVal;
break;
@ -8262,6 +8273,8 @@ unsigned int CMinecraftApp::GetGameHostOption(unsigned int uiHostSettings, eGame
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOTOWNER);
case eGameHostOption_WorldSize:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT;
case eGameHostOption_NoMobCap:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOMOBCAP);
case eGameHostOption_MobGriefing:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_MOBGRIEFING);
case eGameHostOption_KeepInventory:

View file

@ -1205,6 +1205,7 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
app.SetGameHostOption(eGameHostOption_DoTileDrops, pClass->m_MoreOptionsParams.bDoTileDrops);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle);
app.SetGameHostOption(eGameHostOption_NoMobCap, pClass->m_MoreOptionsParams.bNoMobCap);
app.SetGameHostOption(eGameHostOption_WasntSaveOwner, false);
#ifdef _LARGE_WORLDS

View file

@ -101,6 +101,7 @@ UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *ini
m_checkboxes[eLaunchCheckbox_TileDrops].init(app.GetString(IDS_TILE_DROPS), eLaunchCheckbox_TileDrops, m_params->bDoTileDrops);
m_checkboxes[eLaunchCheckbox_NaturalRegeneration].init(app.GetString(IDS_NATURAL_REGEN), eLaunchCheckbox_NaturalRegeneration, m_params->bNaturalRegeneration);
m_checkboxes[eLaunchCheckbox_DayLightCycle].init(app.GetString(IDS_DAYLIGHT_CYCLE), eLaunchCheckbox_DayLightCycle, m_params->bDoDaylightCycle);
m_checkboxes[eLaunchCheckbox_NoMobCap].init(app.GetString(IDS_NO_MOB_CAP), eLaunchCheckbox_NoMobCap, m_params->bNoMobCap);
m_labelGameOptions.init( app.GetString(IDS_GAME_OPTIONS) );
m_labelSeed.init(app.GetString(IDS_CREATE_NEW_WORLD_SEED));
@ -419,6 +420,9 @@ void UIScene_LaunchMoreOptionsMenu::handleCheckboxToggled(F64 controlId, bool se
case eLaunchCheckbox_NaturalRegeneration:
m_params->bNaturalRegeneration = selected;
break;
case eLaunchCheckbox_NoMobCap:
m_params->bNoMobCap = selected;
break;
case eLaunchCheckbox_DayLightCycle:
m_params->bDoDaylightCycle = selected;
break;
@ -487,6 +491,9 @@ void UIScene_LaunchMoreOptionsMenu::handleFocusChange(F64 controlId, F64 childId
case eLaunchCheckbox_DayLightCycle:
stringId = IDS_GAMEOPTION_DAYLIGHT_CYCLE;
break;
case eLaunchCheckbox_NoMobCap:
stringId = IDS_GAMEOPTION_NO_MOB_CAP;
break;
case eControl_EditSeed:
stringId = IDS_GAMEOPTION_SEED;
break;

View file

@ -32,6 +32,7 @@ private:
eLaunchCheckbox_TileDrops,
eLaunchCheckbox_NaturalRegeneration,
eLaunchCheckbox_DayLightCycle,
eLaunchCheckbox_NoMobCap,
eLaunchCheckboxes_Count,
@ -85,6 +86,7 @@ private:
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_MobLoot], "CheckboxMobLoot")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_TileDrops], "CheckboxTileDrops")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_NaturalRegeneration], "CheckboxNaturalRegeneration")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_NoMobCap], "CheckboxNoMobCap")
UI_END_MAP_CHILD_ELEMENTS()
UI_MAP_ELEMENT(m_worldOptions, "WorldOptions")

View file

@ -508,6 +508,7 @@ void UIScene_LoadMenu::tick()
m_MoreOptionsParams.bDoTileDrops = app.GetGameHostOption(uiHostOptions, eGameHostOption_DoTileDrops);
m_MoreOptionsParams.bNaturalRegeneration = app.GetGameHostOption(uiHostOptions, eGameHostOption_NaturalRegeneration);
m_MoreOptionsParams.bDoDaylightCycle = app.GetGameHostOption(uiHostOptions, eGameHostOption_DoDaylightCycle);
m_MoreOptionsParams.bNoMobCap = app.GetGameHostOption(uiHostOptions,eGameHostOption_NoMobCap);
bool cheatsOn = m_MoreOptionsParams.bHostPrivileges;
if (!cheatsOn)
@ -1633,10 +1634,12 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
app.SetGameHostOption(eGameHostOption_DoTileDrops, pClass->m_MoreOptionsParams.bDoTileDrops);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle);
app.SetGameHostOption(eGameHostOption_NoMobCap, pClass->m_MoreOptionsParams.bNoMobCap);
#ifdef _LARGE_WORLDS
app.SetGameHostOption(eGameHostOption_WorldSize, pClass->m_MoreOptionsParams.worldSize+1 ); // 0 is GAME_HOST_OPTION_WORLDSIZE_UNKNOWN
#endif
// app.SetGameNewWorldSize(64, true );
// app.SetGameNewWorldSize(0, false );

View file

@ -350,6 +350,7 @@ typedef struct _LaunchMoreOptionsMenuInitData
bool bDoTileDrops;
bool bNaturalRegeneration;
bool bDoDaylightCycle;
bool bNoMobCap;
bool bOnlineSettingChangedBySystem;
@ -387,6 +388,7 @@ typedef struct _LaunchMoreOptionsMenuInitData
bDoTileDrops = true;
bNaturalRegeneration = true;
bDoDaylightCycle = true;
bNoMobCap=false;
}
}
LaunchMoreOptionsMenuInitData;

View file

@ -623,6 +623,7 @@ bool MinecraftServer::initServer(int64_t seed, NetworkGameInitData *initData, DW
app.SetGameHostOption(eGameHostOption_Difficulty, GetDedicatedServerInt(settings, L"difficulty", app.GetGameHostOption(eGameHostOption_Difficulty)));
app.SetGameHostOption(eGameHostOption_GameType, GetDedicatedServerInt(settings, L"gamemode", app.GetGameHostOption(eGameHostOption_GameType)));
app.SetGameHostOption(eGameHostOption_NoMobCap, GetDedicatedServerBool(settings, L"no-mob-cap", app.GetGameHostOption(eGameHostOption_NoMobCap)));
app.SetGameHostOption(eGameHostOption_Structures, GetDedicatedServerBool(settings, L"generate-structures", app.GetGameHostOption(eGameHostOption_Structures) > 0) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_BonusChest, GetDedicatedServerBool(settings, L"bonus-chest", app.GetGameHostOption(eGameHostOption_BonusChest) > 0) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_PvP, GetDedicatedServerBool(settings, L"pvp", app.GetGameHostOption(eGameHostOption_PvP) > 0) ? 1 : 0);

View file

@ -6662,6 +6662,10 @@ Would you like to install the mash-up pack or texture pack now?</value>
<value>When disabled, players will not regenerate health naturally.</value>
</data>
<data name="IDS_GAMEOPTION_NO_MOB_CAP">
<value>When enabled, there will be no limit on spawn egg use or breeding, and spawning limit will be modified by the amount of loaded chunks.</value>
</data>
<data name="IDS_GAMEOPTION_DAYLIGHT_CYCLE">
<value>When disabled, the time of day will not change.</value>
</data>
@ -7281,6 +7285,10 @@ Would you like to install the mash-up pack or texture pack now?</value>
<value>Natural Regeneration</value>
</data>
<data name="IDS_NO_MOB_CAP">
<value>No Mob Cap</value>
</data>
<data name="IDS_DAYLIGHT_CYCLE">
<value>Daylight Cycle</value>
</data>

File diff suppressed because it is too large Load diff

View file

@ -4695,6 +4695,10 @@ void Level::decrementUnsavedChunkCount()
bool Level::canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType)
{
if (app.GetGameHostOption(eGameHostOption_NoMobCap))
{
return true;
}
int count = 0;
int max = 0;
if(spawnType == eSpawnType_Egg || spawnType == eSpawnType_Portal)
@ -4703,52 +4707,52 @@ bool Level::canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType)
{
case eTYPE_VILLAGER:
count = countInstanceOf( eTYPE_VILLAGER, true);
max = MobCategory::MAX_XBOX_VILLAGERS_WITH_SPAWN_EGG;
max = MobCategory::max_villagers_with_spawn_egg;
break;
case eTYPE_CHICKEN:
count = countInstanceOf( eTYPE_CHICKEN, true);
max = MobCategory::MAX_XBOX_CHICKENS_WITH_SPAWN_EGG;
max = MobCategory::max_chickens_with_spawn_egg;
break;
case eTYPE_WOLF:
count = countInstanceOf( eTYPE_WOLF, true);
max = MobCategory::MAX_XBOX_WOLVES_WITH_SPAWN_EGG;
max = MobCategory::max_wolves_with_spawn_egg;
break;
case eTYPE_MUSHROOMCOW:
count = countInstanceOf( eTYPE_MUSHROOMCOW, true);
max = MobCategory::MAX_XBOX_MUSHROOMCOWS_WITH_SPAWN_EGG;
max = MobCategory::max_mushroomcows_with_spawn_egg;
break;
case eTYPE_SQUID:
count = countInstanceOf( eTYPE_SQUID, true);
max = MobCategory::MAX_XBOX_SQUIDS_WITH_SPAWN_EGG;
max = MobCategory::max_squids_with_spawn_egg;
break;
case eTYPE_SNOWMAN:
count = countInstanceOf( eTYPE_SNOWMAN, true);
max = MobCategory::MAX_XBOX_SNOWMEN;
max = MobCategory::max_snow_golems;
break;
case eTYPE_VILLAGERGOLEM:
count = countInstanceOf( eTYPE_VILLAGERGOLEM, true);
max = MobCategory::MAX_XBOX_IRONGOLEM;
max = MobCategory::max_iron_golems;
break;
case eTYPE_WITHERBOSS:
count = countInstanceOf(eTYPE_WITHERBOSS, true) + countInstanceOf(eTYPE_ENDERDRAGON, true);
max = MobCategory::MAX_CONSOLE_BOSS;
max = MobCategory::max_bosses;
break;
default:
if((type & eTYPE_ANIMALS_SPAWN_LIMIT_CHECK) == eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)
{
count = countInstanceOf( eTYPE_ANIMALS_SPAWN_LIMIT_CHECK, false);
max = MobCategory::MAX_XBOX_ANIMALS_WITH_SPAWN_EGG;
max = MobCategory::max_animals_with_spawn_egg;
}
// 4J: Use eTYPE_ENEMY instead of monster (slimes and ghasts aren't monsters)
else if(Entity::instanceof(type, eTYPE_ENEMY))
{
count = countInstanceOf(eTYPE_ENEMY, false);
max = MobCategory::MAX_XBOX_MONSTERS_WITH_SPAWN_EGG;
max = MobCategory::max_monsters_with_spawn_egg;
}
else if( (type & eTYPE_AMBIENT) == eTYPE_AMBIENT)
{
count = countInstanceOf( eTYPE_AMBIENT, false);
max = MobCategory::MAX_AMBIENT_WITH_SPAWN_EGG;
max = MobCategory::max_ambient_with_spawn_egg;
}
// 4J: Added minecart and boats
else if (Entity::instanceof(type, eTYPE_MINECART))
@ -4769,25 +4773,25 @@ bool Level::canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType)
{
case eTYPE_VILLAGER:
count = countInstanceOf( eTYPE_VILLAGER, true);
max = MobCategory::MAX_VILLAGERS_WITH_BREEDING;
max = MobCategory::max_villagers_with_breeding;
break;
case eTYPE_CHICKEN:
count = countInstanceOf( eTYPE_CHICKEN, true);
max = MobCategory::MAX_XBOX_CHICKENS_WITH_BREEDING;
max = MobCategory::max_chickens_with_breeding;
break;
case eTYPE_WOLF:
count = countInstanceOf( eTYPE_WOLF, true);
max = MobCategory::MAX_XBOX_WOLVES_WITH_BREEDING;
max = MobCategory::max_wolves_with_breeding;
break;
case eTYPE_MUSHROOMCOW:
count = countInstanceOf( eTYPE_MUSHROOMCOW, true);
max = MobCategory::MAX_XBOX_MUSHROOMCOWS_WITH_BREEDING;
max = MobCategory::max_mushroomcows_with_breeding;
break;
default:
if((type & eTYPE_ANIMALS_SPAWN_LIMIT_CHECK) == eTYPE_ANIMALS_SPAWN_LIMIT_CHECK)
{
count = countInstanceOf( eTYPE_ANIMALS_SPAWN_LIMIT_CHECK, false);
max = MobCategory::MAX_XBOX_ANIMALS_WITH_BREEDING;
max = MobCategory::max_animals_with_breeding;
}
else if( (type & eTYPE_MONSTER) == eTYPE_MONSTER)
{

View file

@ -5,6 +5,30 @@
#include "Material.h"
#include "MobCategory.h"
int MobCategory::max_natural_monsters = 50;
int MobCategory::max_natural_animals = 50;
int MobCategory::max_natural_ambient = 20;
int MobCategory::max_natural_squid = 5;
int MobCategory::max_natural_chickens = 8;
int MobCategory::max_natural_wolves = 8;
int MobCategory::max_natural_mushroomcows = 2;
int MobCategory::max_snow_golems = 16;
int MobCategory::max_iron_golems = 16;
int MobCategory::max_bosses = 1;
int MobCategory::max_villagers_with_breeding = 35;
int MobCategory::max_animals_with_breeding = max_natural_animals + 20;
int MobCategory::max_chickens_with_breeding = max_natural_chickens + 8;
int MobCategory::max_mushroomcows_with_breeding = max_natural_mushroomcows + 20;
int MobCategory::max_wolves_with_breeding = max_natural_wolves + 8;
int MobCategory::max_animals_with_spawn_egg = max_animals_with_breeding + 20;
int MobCategory::max_chickens_with_spawn_egg = max_chickens_with_breeding + 10;
int MobCategory::max_wolves_with_spawn_egg = max_wolves_with_breeding + 10;
int MobCategory::max_monsters_with_spawn_egg = max_natural_monsters + 20;
int MobCategory::max_villagers_with_spawn_egg = max_villagers_with_breeding + 15;
int MobCategory::max_mushroomcows_with_spawn_egg = max_mushroomcows_with_breeding + 8;
int MobCategory::max_squids_with_spawn_egg = max_natural_squid + 8;
int MobCategory::max_ambient_with_spawn_egg = max_natural_ambient + 8;
MobCategory *MobCategory::monster = nullptr;
MobCategory *MobCategory::creature = nullptr;
MobCategory *MobCategory::ambient = nullptr;
@ -19,26 +43,27 @@ MobCategoryArray MobCategory::values = MobCategoryArray(7);
void MobCategory::staticCtor()
{
// 4J - adjusted the max levels here for the xbox version, which now represent the max levels in the whole world
monster = new MobCategory(70, Material::air, false, false, eTYPE_MONSTER, false, CONSOLE_MONSTERS_HARD_LIMIT);
creature = new MobCategory(10, Material::air, true, true, eTYPE_ANIMALS_SPAWN_LIMIT_CHECK, false, CONSOLE_ANIMALS_HARD_LIMIT);
ambient = new MobCategory(15, Material::air, true, false, eTYPE_AMBIENT, false, CONSOLE_AMBIENT_HARD_LIMIT),
waterCreature = new MobCategory(5, Material::water, true, false, eTYPE_WATERANIMAL, false, CONSOLE_SQUID_HARD_LIMIT);
// Use pointers to modifiable fields, in future can become modifiable
monster = new MobCategory(&max_natural_monsters, Material::air, false, false, eTYPE_MONSTER, false);
creature = new MobCategory(&max_natural_animals, Material::air, true, true, eTYPE_ANIMALS_SPAWN_LIMIT_CHECK, false);
ambient = new MobCategory(&max_natural_ambient, Material::air, true, false, eTYPE_AMBIENT, false),
waterCreature = new MobCategory(&max_natural_squid, Material::water, true, false, eTYPE_WATERANIMAL, false);
values[0] = monster;
values[1] = creature;
values[2] = ambient;
values[3] = waterCreature;
// 4J - added 2 new categories to give us better control over spawning wolves & chickens
creature_wolf = new MobCategory(3, Material::air, true, true, eTYPE_WOLF, true, MAX_XBOX_WOLVES);
creature_chicken = new MobCategory( 2, Material::air, true, true, eTYPE_CHICKEN, true, MAX_XBOX_CHICKENS);
creature_mushroomcow = new MobCategory(2, Material::air, true, true, eTYPE_MUSHROOMCOW, true, MAX_XBOX_MUSHROOMCOWS);
creature_wolf = new MobCategory(&max_natural_wolves, Material::air, true, true, eTYPE_WOLF, true);
creature_chicken = new MobCategory(&max_natural_chickens, Material::air, true, true, eTYPE_CHICKEN, true);
creature_mushroomcow = new MobCategory(&max_natural_mushroomcows, Material::air, true, true, eTYPE_MUSHROOMCOW, true);
values[4] = creature_wolf;
values[5] = creature_chicken;
values[6] = creature_mushroomcow;
}
MobCategory::MobCategory(int maxVar, Material *spawnPositionMaterial, bool isFriendly, bool isPersistent, eINSTANCEOF eBase, bool isSingleType, int maxPerLevel)
: m_max(maxVar), spawnPositionMaterial(spawnPositionMaterial), m_isFriendly(isFriendly), m_isPersistent(isPersistent), m_eBase(eBase), m_isSingleType(isSingleType), m_maxPerLevel(maxPerLevel)
MobCategory::MobCategory(int *maxVar, Material *spawnPositionMaterial, bool isFriendly, bool isPersistent, eINSTANCEOF eBase, bool isSingleType)
: m_max(maxVar), spawnPositionMaterial(spawnPositionMaterial), m_isFriendly(isFriendly), m_isPersistent(isPersistent), m_eBase(eBase), m_isSingleType(isSingleType)
{
}
@ -50,12 +75,7 @@ const eINSTANCEOF MobCategory::getEnumBaseClass()
int MobCategory::getMaxInstancesPerChunk()
{
return m_max;
}
int MobCategory::getMaxInstancesPerLevel() // 4J added
{
return m_maxPerLevel;
return *m_max;
}
Material *MobCategory::getSpawnPositionMaterial()
@ -76,4 +96,4 @@ bool MobCategory::isSingleType()
bool MobCategory::isPersistent()
{
return m_isPersistent;
}
}

View file

@ -7,32 +7,32 @@ class MobCategory
{
public:
// 4J - putting constants for xbox spawning in one place to tidy things up a bit - all numbers are per level
static const int CONSOLE_MONSTERS_HARD_LIMIT = 50; // Max number of enemies (skeleton, zombie, creeper etc) that the mob spawner will produce
static const int CONSOLE_ANIMALS_HARD_LIMIT = 50; // Max number of animals (cows, sheep, pigs) that the mob spawner will produce
static const int CONSOLE_AMBIENT_HARD_LIMIT = 20; // Ambient mobs
static int max_natural_monsters; // Max number of enemies (skeleton, zombie, creeper etc) that the mob spawner will produce
static int max_natural_animals; // Max number of animals (cows, sheep, pigs) that the mob spawner will produce
static int max_natural_ambient; // Ambient mobs
static int max_natural_squid; // Max number of squid that the mob spawner will produce
static int max_natural_chickens; // Max number of chickens that the mob spawner will produce
static int max_natural_wolves; // Max number of wolves that the mob spawner will produce
static int max_natural_mushroomcows; // Max number of mushroom cows that the mob spawner will produce
static const int MAX_XBOX_CHICKENS = 8; // Max number of chickens that the mob spawner will produce
static const int MAX_XBOX_WOLVES = 8; // Max number of wolves that the mob spawner will produce
static const int MAX_XBOX_MUSHROOMCOWS = 2; // Max number of mushroom cows that the mob spawner will produce
static const int MAX_XBOX_SNOWMEN = 16; // Max number of snow golems that can be created by placing blocks - 4J-PB increased limit due to player requests
static const int MAX_XBOX_IRONGOLEM = 16; // Max number of iron golems that can be created by placing blocks - 4J-PB increased limit due to player requests
static const int CONSOLE_SQUID_HARD_LIMIT = 5;
static const int MAX_CONSOLE_BOSS = 1; // Max number of bosses (enderdragon/wither)
static const int MAX_XBOX_ANIMALS_WITH_BREEDING = CONSOLE_ANIMALS_HARD_LIMIT + 20; // Max number of animals that we can produce (in total), when breeding
static const int MAX_XBOX_CHICKENS_WITH_BREEDING = MAX_XBOX_CHICKENS + 8; // Max number of chickens that we can produce (in total), when breeding/hatching
static const int MAX_XBOX_MUSHROOMCOWS_WITH_BREEDING = MAX_XBOX_MUSHROOMCOWS + 20; // Max number of mushroom cows that we can produce (in total), when breeding
static const int MAX_XBOX_WOLVES_WITH_BREEDING = MAX_XBOX_WOLVES + 8; // Max number of wolves that we can produce (in total), when breeding
static const int MAX_VILLAGERS_WITH_BREEDING = 35;
static int max_snow_golems; // Max number of snow golems that can be created by placing blocks - 4J-PB increased limit due to player requests
static int max_iron_golems; // Max number of iron golems that can be created by placing blocks - 4J-PB increased limit due to player requests
static int max_bosses; // Max number of bosses (enderdragon/wither)
static const int MAX_XBOX_ANIMALS_WITH_SPAWN_EGG = MAX_XBOX_ANIMALS_WITH_BREEDING + 20;
static const int MAX_XBOX_CHICKENS_WITH_SPAWN_EGG = MAX_XBOX_CHICKENS_WITH_BREEDING + 10;
static const int MAX_XBOX_WOLVES_WITH_SPAWN_EGG = MAX_XBOX_WOLVES_WITH_BREEDING + 10;
static const int MAX_XBOX_MONSTERS_WITH_SPAWN_EGG = CONSOLE_MONSTERS_HARD_LIMIT + 20;
static const int MAX_XBOX_VILLAGERS_WITH_SPAWN_EGG = MAX_VILLAGERS_WITH_BREEDING + 15; // 4J-PB - increased this limit due to player requests
static const int MAX_XBOX_MUSHROOMCOWS_WITH_SPAWN_EGG = MAX_XBOX_MUSHROOMCOWS_WITH_BREEDING + 8;
static const int MAX_XBOX_SQUIDS_WITH_SPAWN_EGG = CONSOLE_SQUID_HARD_LIMIT + 8;
static const int MAX_AMBIENT_WITH_SPAWN_EGG = CONSOLE_AMBIENT_HARD_LIMIT + 8;
static int max_animals_with_breeding; // Max number of animals that we can produce (in total), when breeding
static int max_chickens_with_breeding; // Max number of chickens that we can produce (in total), when breeding/hatching
static int max_mushroomcows_with_breeding; // Max number of mushroom cows that we can produce (in total), when breeding
static int max_wolves_with_breeding; // Max number of wolves that we can produce (in total), when breeding
static int max_villagers_with_breeding; // Max number of villagers that we can produce (in total), when breeding
static int max_animals_with_spawn_egg; // Max number of animals that we can produce (in total), when using spawn eggs
static int max_chickens_with_spawn_egg; // Max number of chickens that we can produce (in total), when using spawn eggs
static int max_wolves_with_spawn_egg; // Max number of wolves that we can produce (in total), when using spawn eggs
static int max_monsters_with_spawn_egg; // Max number of monsters that we can produce (in total), when using spawn eggs
static int max_villagers_with_spawn_egg; // Max number of villagers that we can produce (in total), when using spawn eggs - 4J-PB increased limit due to player requests
static int max_mushroomcows_with_spawn_egg; // Max number of mushroom cows that we can produce (in total), when using spawn eggs
static int max_squids_with_spawn_egg; // Max number of squids that we can produce (in total), when using spawn eggs
static int max_ambient_with_spawn_egg; // Max number of ambient mobs that we can produce (in total), when using spawn eggs
/*
Maximum animals = 50 + 20 + 20 = 90
@ -64,21 +64,21 @@ public:
private:
const int m_max;
const int m_maxPerLevel;
// Use pointers to allow for this to be changed indirectly whilst staying a const
const int *m_max;
const Material *spawnPositionMaterial;
const bool m_isFriendly;
const bool m_isPersistent;
const bool m_isSingleType; // 4J Added
const eINSTANCEOF m_eBase; // 4J added
MobCategory(int maxVar, Material *spawnPositionMaterial, bool isFriendly, bool isPersistent, eINSTANCEOF eBase, bool isSingleType, int maxPerLevel);
MobCategory(int *maxVar, Material *spawnPositionMaterial, bool isFriendly, bool isPersistent, eINSTANCEOF eBase, bool isSingleType);
public:
const type_info getBaseClass();
const eINSTANCEOF getEnumBaseClass(); // 4J added
int getMaxInstancesPerChunk();
int getMaxInstancesPerLevel(); // 4J added
// int getMaxInstancesPerLevel(); 4J added ~ Removed as it has been merged with getMaxInstancesPerChunk()
Material *getSpawnPositionMaterial();
bool isFriendly();
bool isSingleType();

View file

@ -209,10 +209,20 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
}
}
// Use variable to not repeat checks
int maxInstances = mobCategory->getMaxInstancesPerChunk(); // Merged in values from getMaxInstancesPerLevel(), so changed to use getMaxInstancesPerChunk()
// Check for if the mob cap is "off" (works as Java does, scaled by chunk count)
bool usesChunkLimit = app.GetGameHostOption(eGameHostOption_NoMobCap);
if (usesChunkLimit)
{
// Use Java logic for the max count instead, accounting for chunks polled and the magic number.
maxInstances = mobCategory->getMaxInstancesPerChunk() * chunksToPoll.size() / MAGIC_NUMBER;
}
// 4J - this is now quite different to the java version. We just have global max counts for the level whereas the original has a max per chunk that
// scales with the number of chunks to be polled.
int categoryCount = level->countInstanceOf( mobCategory->getEnumBaseClass(), mobCategory->isSingleType());
if( categoryCount >= mobCategory->getMaxInstancesPerLevel())
if(categoryCount >= maxInstances)
{
continue;
}
@ -314,6 +324,7 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
// was added initially to stop flat lands being totally populated with slimes but seems like a generally good rule.
eINSTANCEOF mobType = mob->GetType();
// Keep this check the same despite it not existing in Java as it would otherwise be a much more significant change to behavior.
if( ( mobType & eTYPE_ANIMALS_SPAWN_LIMIT_CHECK ) || ( mobType & eTYPE_MONSTER ) )
{
// even more special rule for ghasts, because filling up the nether with 25 of them is a bit unpleasant. In the java version they are
@ -321,25 +332,25 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
// aren't actually even counted properly themselves
if( mobType == eTYPE_GHAST )
{
if( level->countInstanceOf(mobType, true) >= 4 ) continue;
if( level->countInstanceOf(mobType, true) >= 4 ) continue;
}
else if( mobType == eTYPE_ENDERMAN && level->dimension->id == 1 )
{
// Special rule for the end, as we only have Endermen (plus the dragon). Increase the spawnable counts based on level difficulty
int maxEndermen = mobCategory->getMaxInstancesPerLevel();
int maxEndermen = maxInstances;
if( level->difficulty == Difficulty::NORMAL )
{
maxEndermen -= mobCategory->getMaxInstancesPerLevel()/4;
maxEndermen -= maxInstances/4;
}
else if( level->difficulty <= Difficulty::EASY)
{
maxEndermen -= mobCategory->getMaxInstancesPerLevel()/2;
maxEndermen -= maxInstances/2;
}
if( level->countInstanceOf(mobType, true) >= maxEndermen ) continue;
}
else if( level->countInstanceOf(mobType, true) >= ( mobCategory->getMaxInstancesPerLevel() / 2 ) ) continue;
else if( level->countInstanceOf(mobType, true) >= ( maxInstances / 2 ) ) continue;
}
mob->moveTo(xx, yy, zz, level->random->nextFloat() * 360, 0);
@ -359,7 +370,7 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
// 4J - change here so that we can't ever make more than the desired amount of entities in each priority. In the original java version
// depending on the random spawn positions being considered the only limit as to the number of entities created per category is the number
// of chunks to poll.
if (categoryCount >= mobCategory->getMaxInstancesPerLevel() ) goto categoryLoop;
if (categoryCount >= maxInstances ) goto categoryLoop;
if (clusterSize >= mob->getMaxSpawnClusterSize()) goto chunkLoop;
}
}
@ -425,7 +436,7 @@ bool MobSpawner::isSpawnPositionOk(MobCategory *category, Level *level, int x, i
int tt = level->getTile(x, y - 1, z);
return tt != Tile::unbreakable_Id && !level->isSolidBlockingTile(x, y, z) && !level->getMaterial(x, y, z)->isLiquid() && !level->isSolidBlockingTile(x, y + 1, z);
}
}
}
void MobSpawner::postProcessSpawnMobs(Level *level, Biome *biome, int xo, int zo, int cellWidth, int cellHeight, Random *random)
{

View file

@ -12,6 +12,8 @@ class Level;
class MobSpawner
{
private:
// For some reason, this constant is used in Java as the dividend for the max count of a mob category in the level, thus this is done to keep parity.
static const int MAGIC_NUMBER = 289;
static const int MIN_SPAWN_DISTANCE;
protected: