Add in options, move to boolean, add checkbox, fix caps to match LCE

This commit is contained in:
Alexandra-Myers 2026-03-09 18:46:51 -04:00
parent 0f97ed95ea
commit 43200cb777
19 changed files with 95 additions and 124 deletions

View file

@ -45,11 +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_WORLDMOBCAP 0xC0000000 // 2 bits, 4 values (small(0), medium(1), large(2), unlimited(3))
#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_WORLDMOBCAP_BITSHIFT 30 // Set to this value as there is no other remaining space
enum EGameHostOptionWorldSize
{

View file

@ -636,7 +636,6 @@ enum eGameHostOption
eGameHostOption_BedrockFog,
eGameHostOption_NoHUD,
eGameHostOption_WorldSize,
eGameHostOption_WorldMobCap,
eGameHostOption_All,
eGameHostOption_DisableSaving,
@ -649,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

@ -8063,10 +8063,16 @@ void CMinecraftApp::SetGameHostOption(unsigned int &uiHostSettings, eGameHostOpt
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDSIZE;
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
break;
case eGameHostOption_WorldMobCap:
// Clear the original value first
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDMOBCAP;
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDMOBCAP & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDMOBCAP_BITSHIFT));
case eGameHostOption_NoMobCap:
if(uiVal!=1)
{
uiHostSettings |= GAME_HOST_OPTION_BITMASK_NOMOBCAP;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NOMOBCAP;
}
break;
case eGameHostOption_All:
uiHostSettings=uiVal;
@ -8154,8 +8160,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_WorldMobCap:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDMOBCAP) >> GAME_HOST_OPTION_BITMASK_WORLDMOBCAP_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

@ -1206,6 +1206,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
@ -1213,10 +1214,6 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
pClass->m_MoreOptionsParams.currentWorldSize = static_cast<EGameHostOptionWorldSize>(pClass->m_MoreOptionsParams.worldSize + 1);
pClass->m_MoreOptionsParams.newWorldSize = static_cast<EGameHostOptionWorldSize>(pClass->m_MoreOptionsParams.worldSize + 1);
#endif
app.SetGameHostOption(eGameHostOption_WorldMobCap, pClass->m_MoreOptionsParams.worldMobCap );
// Use helper to update the caps based on what was set earlier
MobCategory::updateMobCaps(pClass->m_MoreOptionsParams.worldMobCap);
g_NetworkManager.HostGame(dwLocalUsersMask,isClientSide,isPrivate,MINECRAFT_NET_MAX_PLAYERS,0);

View file

@ -15,14 +15,6 @@ int m_iWorldSizeTitleA[4] =
};
#endif
string m_iWorldMobCapTitleA[4] =
{
"Small",
"Medium",
"Large",
"Unlimited"
};
UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{
// Setup all the Iggy references we need for this scene
@ -109,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(UIString::UIString("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));
@ -140,10 +133,6 @@ UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *ini
m_tabIndex = m_params->bGenerateOptions ? TAB_WORLD_OPTIONS : TAB_GAME_OPTIONS;
// Introduce a mob cap slider for large worlds. If there were a better solution for this it would be nice...
m_sliderWorldMobCap.init(UIString::UIString("Mob Cap Size: " + m_iWorldMobCapTitleA[m_params->worldMobCap]),eControl_WorldMobCap,0,3,m_params->worldMobCap);
// set the default text
#ifdef _LARGE_WORLDS
wstring wsText=L"";
@ -499,10 +488,10 @@ void UIScene_LaunchMoreOptionsMenu::handleFocusChange(F64 controlId, F64 childId
case eLaunchCheckbox_DayLightCycle:
stringId = IDS_GAMEOPTION_DAYLIGHT_CYCLE;
break;
case eControl_EditSeed:
case eLaunchCheckbox_NoMobCap:
stringId = IDS_GAMEOPTION_SEED;
break;
case eControl_WorldMobCap:
case eControl_EditSeed:
stringId = IDS_GAMEOPTION_SEED;
break;
#ifdef _LARGE_WORLDS
@ -660,11 +649,6 @@ void UIScene_LaunchMoreOptionsMenu::handleSliderMove(F64 sliderId, F64 currentVa
int value = static_cast<int>(currentValue);
switch(static_cast<int>(sliderId))
{
case eControl_WorldMobCap:
m_sliderWorldMobCap.handleSliderMove(value);
m_params->worldMobCap = value;
m_sliderWorldMobCap.setLabel(UIString::UIString("Mob Cap Size: " + m_iWorldMobCapTitleA[m_params->worldMobCap]));
break;
case eControl_WorldSize:
#ifdef _LARGE_WORLDS
m_sliderWorldSize.handleSliderMove(value);

View file

@ -32,13 +32,13 @@ private:
eLaunchCheckbox_TileDrops,
eLaunchCheckbox_NaturalRegeneration,
eLaunchCheckbox_DayLightCycle,
eLaunchCheckbox_NoMobCap,
eLaunchCheckboxes_Count,
eControl_EditSeed,
eControl_WorldSize,
eControl_WorldResize,
eControl_WorldMobCap,
eControl_Count
};
@ -62,7 +62,6 @@ private:
UIControl_TextInput m_editSeed;
UIControl_Slider m_sliderWorldSize;
UIControl_Slider m_sliderWorldResize;
UIControl_Slider m_sliderWorldMobCap; // Added ~ Mob cap slider for user control
IggyName m_funcSetMenuType, m_funcChangeTab, m_funcSetDescription;
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT( m_labelGameOptions, "LabelGame")
@ -87,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")
@ -101,7 +101,6 @@ private:
UI_MAP_ELEMENT( m_labelRandomSeed, "RandomSeed")
UI_MAP_ELEMENT( m_labelWorldSize, "WorldSize")
UI_MAP_ELEMENT( m_sliderWorldSize, "WorldSizeSlider")
UI_MAP_ELEMENT( m_sliderWorldMobCap, "WorldMobCapSlider")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_Structures], "CheckboxStructures")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_BonusChest], "CheckboxBonusChest")

View file

@ -480,8 +480,6 @@ void UIScene_LoadMenu::tick()
m_MoreOptionsParams.bDisableSaving = app.GetGameHostOption(uiHostOptions,eGameHostOption_DisableSaving)>0?TRUE:FALSE;
m_MoreOptionsParams.currentWorldSize = static_cast<EGameHostOptionWorldSize>(app.GetGameHostOption(uiHostOptions, eGameHostOption_WorldSize));
m_MoreOptionsParams.newWorldSize = m_MoreOptionsParams.currentWorldSize;
// Load world mob cap option
m_MoreOptionsParams.worldMobCap = app.GetGameHostOption(uiHostOptions,eGameHostOption_WorldMobCap);
m_MoreOptionsParams.bMobGriefing = app.GetGameHostOption(uiHostOptions, eGameHostOption_MobGriefing);
m_MoreOptionsParams.bKeepInventory = app.GetGameHostOption(uiHostOptions, eGameHostOption_KeepInventory);
@ -490,6 +488,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)
@ -1615,14 +1614,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.SetGameHostOption(eGameHostOption_WorldMobCap, pClass->m_MoreOptionsParams.worldMobCap );
// Use helper to update the caps based on what was set earlier
MobCategory::updateMobCaps(pClass->m_MoreOptionsParams.worldMobCap);
// 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;
@ -359,7 +360,6 @@ typedef struct _LaunchMoreOptionsMenuInitData
wstring seed;
int worldSize;
int worldMobCap;
bool bDisableSaving;
EGameHostOptionWorldSize currentWorldSize;
@ -376,7 +376,6 @@ typedef struct _LaunchMoreOptionsMenuInitData
bTNT = true;
iPad = -1;
worldSize = 3;
worldMobCap = 0;
seed = L"";
bDisableSaving = false;
newWorldSize = e_worldSize_Unknown;
@ -389,6 +388,7 @@ typedef struct _LaunchMoreOptionsMenuInitData
bDoTileDrops = true;
bNaturalRegeneration = true;
bDoDaylightCycle = true;
bNoMobCap=false;
}
}
LaunchMoreOptionsMenuInitData;

View file

@ -618,7 +618,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_WorldMobCap, GetDedicatedServerInt(settings, L"world-mob-cap", app.GetGameHostOption(eGameHostOption_WorldMobCap)));
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);
@ -626,9 +626,6 @@ bool MinecraftServer::initServer(int64_t seed, NetworkGameInitData *initData, DW
app.SetGameHostOption(eGameHostOption_FireSpreads, GetDedicatedServerBool(settings, L"fire-spreads", app.GetGameHostOption(eGameHostOption_FireSpreads) > 0) ? 1 : 0);
app.SetGameHostOption(eGameHostOption_TNT, GetDedicatedServerBool(settings, L"tnt", app.GetGameHostOption(eGameHostOption_TNT) > 0) ? 1 : 0);
// Use helper to update the caps based on what was set earlier
MobCategory::updateMobCaps(app.GetGameHostOption(eGameHostOption_WorldMobCap));
app.DebugPrintf("\n*** SERVER SETTINGS ***\n");
app.DebugPrintf("ServerSettings: host-friends-only is %s\n",(app.GetGameHostOption(eGameHostOption_FriendsOfFriends)>0)?"on":"off");
app.DebugPrintf("ServerSettings: game-type is %s\n",(app.GetGameHostOption(eGameHostOption_GameType)==0)?"Survival Mode":"Creative Mode");

View file

@ -222,7 +222,24 @@ int Biome::getSkyColor(float temp)
vector<Biome::MobSpawnerData *> *Biome::getMobs(MobCategory *category)
{
if (category == MobCategory::monster) return &enemies;
if (category == MobCategory::creature) return &friendlies;
if (category == MobCategory::creature)
{
if (app.GetGameHostOption(eGameHostOption_NoMobCap))
{
// Only input into this if necessary, this should be after all others are set up for this biome as well
if (allFriendlies.empty()) {
// If empty, reserve the combined size of all mob spawner data
allFriendlies.reserve(friendlies.size() + friendlies_chicken.size() + friendlies_wolf.size() + friendlies_mushroomcow.size());
// Combine each vector into allFriendlies
allFriendlies.insert(allFriendlies.end(), friendlies.begin(), friendlies.end());
allFriendlies.insert(allFriendlies.end(), friendlies_chicken.begin(), friendlies_chicken.end());
allFriendlies.insert(allFriendlies.end(), friendlies_wolf.begin(), friendlies_wolf.end());
allFriendlies.insert(allFriendlies.end(), friendlies_mushroomcow.begin(), friendlies_mushroomcow.end());
}
return &allFriendlies; // Use combined vector when using Java logic
}
return &friendlies;
}
if (category == MobCategory::waterCreature) return &waterFriendlies;
if (category == MobCategory::creature_chicken) return &friendlies_chicken;
if (category == MobCategory::creature_wolf) return &friendlies_wolf;

View file

@ -82,6 +82,7 @@ public:
protected:
vector<MobSpawnerData *> enemies;
vector<MobSpawnerData *> allFriendlies; // Added to not have to recombine with other groups every time spawner data is used
vector<MobSpawnerData *> friendlies;
vector<MobSpawnerData *> waterFriendlies;
vector<MobSpawnerData *> friendlies_chicken;

View file

@ -4695,7 +4695,7 @@ void Level::decrementUnsavedChunkCount()
bool Level::canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType)
{
if (app.GetGameHostOption(eGameHostOption_WorldMobCap) == 3)
if (app.GetGameHostOption(eGameHostOption_NoMobCap))
{
return true;
}

View file

@ -47,8 +47,9 @@ 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);
creature = new MobCategory(10, Material::air, true, true, eTYPE_ANIMALS_SPAWN_LIMIT_CHECK, false);
ambient = new MobCategory(15, Material::air, true, false, eTYPE_AMBIENT, false),
// Raised these to be identical to base LCE
creature = new MobCategory(50, Material::air, true, true, eTYPE_ANIMALS_SPAWN_LIMIT_CHECK, eTYPE_ANIMAL, false);
ambient = new MobCategory(20, Material::air, true, false, eTYPE_AMBIENT, false),
waterCreature = new MobCategory(5, Material::water, true, false, eTYPE_WATERANIMAL, false);
values[0] = monster;
@ -62,18 +63,53 @@ void MobCategory::staticCtor()
values[4] = creature_wolf;
values[5] = creature_chicken;
values[6] = creature_mushroomcow;
updateMobCaps(0); // Set the mob caps to the default limits
maxNaturalMonsters = 50;
maxNaturalAnimals = 50;
maxNaturalAmbient = 20;
maxNaturalSquid = 5;
maxNaturalChickens = 8;
maxNaturalWolves = 8;
maxNaturalMushroomCows = 2;
maxSnowGolems = 16;
maxIronGolems = 16;
maxBosses = 1;
maxVillagersWithBreeding = 35;
monster->m_maxPerLevel = maxNaturalMonsters;
creature->m_maxPerLevel = maxNaturalAnimals;
ambient->m_maxPerLevel = maxNaturalAmbient;
waterCreature->m_maxPerLevel = maxNaturalSquid;
creature_wolf->m_maxPerLevel = maxNaturalWolves;
creature_chicken->m_maxPerLevel = maxNaturalChickens;
creature_mushroomcow->m_maxPerLevel = maxNaturalMushroomCows;
maxAnimalsWithBreeding = maxNaturalAnimals + 20;
maxChickensWithBreeding = maxNaturalChickens + 8;
maxMushroomCowsWithBreeding = maxNaturalMushroomCows + 20;
maxWolvesWithBreeding = maxNaturalWolves + 8;
maxAnimalsWithSpawnEgg = maxAnimalsWithBreeding + 20;
maxChickensWithSpawnEgg = maxChickensWithBreeding + 10;
maxWolvesWithSpawnEgg = maxWolvesWithBreeding + 10;
maxMonstersWithSpawnEgg = maxNaturalMonsters + 20;
maxVillagersWithSpawnEgg = maxVillagersWithBreeding + 15;
maxMushroomCowsWithSpawnEgg = maxMushroomCowsWithBreeding + 8;
maxSquidsWithSpawnEgg = maxNaturalSquid + 8;
maxAmbientWithSpawnEgg = maxNaturalAmbient + 8;
}
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)
: m_max(maxVar), spawnPositionMaterial(spawnPositionMaterial), m_isFriendly(isFriendly), m_isPersistent(isPersistent), m_eBase(eBase), m_eJavaBase(eBase), m_isSingleType(isSingleType)
{
}
MobCategory::MobCategory(int maxVar, Material *spawnPositionMaterial, bool isFriendly, bool isPersistent, eINSTANCEOF eBase, eINSTANCEOF eJavaBase, bool isSingleType)
: m_max(maxVar), spawnPositionMaterial(spawnPositionMaterial), m_isFriendly(isFriendly), m_isPersistent(isPersistent), m_eBase(eBase), m_eJavaBase(eJavaBase), m_isSingleType(isSingleType)
{
}
// 4J - added
const eINSTANCEOF MobCategory::getEnumBaseClass()
{
if (app.GetGameHostOption(eGameHostOption_NoMobCap)) return m_eJavaBase;
return m_eBase;
}
@ -105,72 +141,4 @@ bool MobCategory::isSingleType()
bool MobCategory::isPersistent()
{
return m_isPersistent;
}
void MobCategory::updateMobCaps(int mode)
{
switch (mode)
{
case 0: // Original limits
maxNaturalMonsters = 50;
maxNaturalAnimals = 50;
maxNaturalAmbient = 20;
maxNaturalSquid = 5;
maxNaturalChickens = 8;
maxNaturalWolves = 8;
maxNaturalMushroomCows = 2;
maxSnowGolems = 16;
maxIronGolems = 16;
maxBosses = 1;
maxVillagersWithBreeding = 35;
break;
case 1:
// Match previous definition of limits
maxNaturalMonsters = 70;
maxNaturalAnimals = 70;
maxNaturalAmbient = 20;
maxNaturalSquid = 10;
maxNaturalChickens = 16;
maxNaturalWolves = 16;
maxNaturalMushroomCows = 8;
maxSnowGolems = 16;
maxIronGolems = 16;
maxBosses = 1;
maxVillagersWithBreeding = 50;
break;
case 2: // Large, higher than both original and new limits
maxNaturalMonsters = 100;
maxNaturalAnimals = 100;
maxNaturalAmbient = 40;
maxNaturalSquid = 15;
maxNaturalChickens = 24;
maxNaturalWolves = 24;
maxNaturalMushroomCows = 16;
maxSnowGolems = 32;
maxIronGolems = 32;
maxBosses = 3;
maxVillagersWithBreeding = 100;
break;
case 3:
return; // Keep current limits, as all related checks are bypassed in this case
}
monster->m_maxPerLevel = maxNaturalMonsters;
creature->m_maxPerLevel = maxNaturalAnimals;
ambient->m_maxPerLevel = maxNaturalAmbient;
waterCreature->m_maxPerLevel = maxNaturalSquid;
creature_wolf->m_maxPerLevel = maxNaturalWolves;
creature_chicken->m_maxPerLevel = maxNaturalChickens;
creature_mushroomcow->m_maxPerLevel = maxNaturalMushroomCows;
maxAnimalsWithBreeding = maxNaturalAnimals + 20;
maxChickensWithBreeding = maxNaturalChickens + 8;
maxMushroomCowsWithBreeding = maxNaturalMushroomCows + 20;
maxWolvesWithBreeding = maxNaturalWolves + 8;
maxAnimalsWithSpawnEgg = maxAnimalsWithBreeding + 20;
maxChickensWithSpawnEgg = maxChickensWithBreeding + 10;
maxWolvesWithSpawnEgg = maxWolvesWithBreeding + 10;
maxMonstersWithSpawnEgg = maxNaturalMonsters + 20;
maxVillagersWithSpawnEgg = maxVillagersWithBreeding + 15;
maxMushroomCowsWithSpawnEgg = maxMushroomCowsWithBreeding + 8;
maxSquidsWithSpawnEgg = maxNaturalSquid + 8;
maxAmbientWithSpawnEgg = maxNaturalAmbient + 8;
}

View file

@ -71,8 +71,14 @@ private:
const bool m_isPersistent;
const bool m_isSingleType; // 4J Added
const eINSTANCEOF m_eBase; // 4J added
// Added for animals so that wolves, mushroomcows, and chickens can be included in the category count.
// Only used when mob cap is unlimited, done to ensure the wolves and chickens can spawn properly.
// When using the shorter constructor, this will be set to m_eBase.
const eINSTANCEOF m_eJavaBase;
MobCategory(int maxVar, Material *spawnPositionMaterial, bool isFriendly, bool isPersistent, eINSTANCEOF eBase, bool isSingleType);
// Additional constructor, allows specifying the enum to use if mob cap is unlimited
MobCategory(int maxVar, Material * spawnPositionMaterial, bool isFriendly, bool isPersistent, eINSTANCEOF eBase, eINSTANCEOF eJavaBase, bool isSingleType);
public:
const type_info getBaseClass();
@ -85,7 +91,5 @@ public:
bool isPersistent();
public:
// Add a function to update the mob caps
static void updateMobCaps(int mode);
static void staticCtor();
};

View file

@ -212,11 +212,13 @@ const int MobSpawner::tick(ServerLevel *level, bool spawnEnemies, bool spawnFrie
// Use variable to not repeat checks
int maxInstances = mobCategory->getMaxInstancesPerLevel();
// Check for if the mob cap is "off" (works as Java does, scaled by chunk count)
bool usesChunkLimit = app.GetGameHostOption(eGameHostOption_WorldMobCap) == 3;
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;
// Cancel spawning under extra categories, with this option they should be included in creature
if (i > 3) continue;
}
// 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