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_DOTILEDROPS 0x08000000
#define GAME_HOST_OPTION_BITMASK_NATURALREGEN 0x10000000 #define GAME_HOST_OPTION_BITMASK_NATURALREGEN 0x10000000
#define GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE 0x20000000 #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_ALL 0xFFFFFFFF
#define GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT 20 #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 enum EGameHostOptionWorldSize
{ {

View file

@ -636,7 +636,6 @@ enum eGameHostOption
eGameHostOption_BedrockFog, eGameHostOption_BedrockFog,
eGameHostOption_NoHUD, eGameHostOption_NoHUD,
eGameHostOption_WorldSize, eGameHostOption_WorldSize,
eGameHostOption_WorldMobCap,
eGameHostOption_All, eGameHostOption_All,
eGameHostOption_DisableSaving, eGameHostOption_DisableSaving,
@ -649,6 +648,7 @@ enum eGameHostOption
eGameHostOption_DoTileDrops, eGameHostOption_DoTileDrops,
eGameHostOption_NaturalRegeneration, eGameHostOption_NaturalRegeneration,
eGameHostOption_DoDaylightCycle, eGameHostOption_DoDaylightCycle,
eGameHostOption_NoMobCap,
}; };
// 4J-PB - If any new DLC items are added to the TMSFiles, this array needs updated // 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;
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT)); uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDSIZE & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT));
break; break;
case eGameHostOption_WorldMobCap: case eGameHostOption_NoMobCap:
// Clear the original value first if(uiVal!=1)
uiHostSettings&=~GAME_HOST_OPTION_BITMASK_WORLDMOBCAP; {
uiHostSettings|=(GAME_HOST_OPTION_BITMASK_WORLDMOBCAP & (uiVal<<GAME_HOST_OPTION_BITMASK_WORLDMOBCAP_BITSHIFT)); uiHostSettings |= GAME_HOST_OPTION_BITMASK_NOMOBCAP;
}
else
{
// off
uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NOMOBCAP;
}
break; break;
case eGameHostOption_All: case eGameHostOption_All:
uiHostSettings=uiVal; uiHostSettings=uiVal;
@ -8154,8 +8160,8 @@ unsigned int CMinecraftApp::GetGameHostOption(unsigned int uiHostSettings, eGame
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOTOWNER); return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOTOWNER);
case eGameHostOption_WorldSize: case eGameHostOption_WorldSize:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT; return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT;
case eGameHostOption_WorldMobCap: case eGameHostOption_NoMobCap:
return (uiHostSettings&GAME_HOST_OPTION_BITMASK_WORLDMOBCAP) >> GAME_HOST_OPTION_BITMASK_WORLDMOBCAP_BITSHIFT; return (uiHostSettings&GAME_HOST_OPTION_BITMASK_NOMOBCAP);
case eGameHostOption_MobGriefing: case eGameHostOption_MobGriefing:
return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_MOBGRIEFING); return !(uiHostSettings&GAME_HOST_OPTION_BITMASK_MOBGRIEFING);
case eGameHostOption_KeepInventory: 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_DoTileDrops, pClass->m_MoreOptionsParams.bDoTileDrops);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration); app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle); app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle);
app.SetGameHostOption(eGameHostOption_NoMobCap, pClass->m_MoreOptionsParams.bNoMobCap);
app.SetGameHostOption(eGameHostOption_WasntSaveOwner, false); app.SetGameHostOption(eGameHostOption_WasntSaveOwner, false);
#ifdef _LARGE_WORLDS #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.currentWorldSize = static_cast<EGameHostOptionWorldSize>(pClass->m_MoreOptionsParams.worldSize + 1);
pClass->m_MoreOptionsParams.newWorldSize = static_cast<EGameHostOptionWorldSize>(pClass->m_MoreOptionsParams.worldSize + 1); pClass->m_MoreOptionsParams.newWorldSize = static_cast<EGameHostOptionWorldSize>(pClass->m_MoreOptionsParams.worldSize + 1);
#endif #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); g_NetworkManager.HostGame(dwLocalUsersMask,isClientSide,isPrivate,MINECRAFT_NET_MAX_PLAYERS,0);

View file

@ -15,14 +15,6 @@ int m_iWorldSizeTitleA[4] =
}; };
#endif #endif
string m_iWorldMobCapTitleA[4] =
{
"Small",
"Medium",
"Large",
"Unlimited"
};
UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) UIScene_LaunchMoreOptionsMenu::UIScene_LaunchMoreOptionsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
{ {
// Setup all the Iggy references we need for this scene // 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_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_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_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_labelGameOptions.init( app.GetString(IDS_GAME_OPTIONS) );
m_labelSeed.init(app.GetString(IDS_CREATE_NEW_WORLD_SEED)); 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; 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 // set the default text
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
wstring wsText=L""; wstring wsText=L"";
@ -499,10 +488,10 @@ void UIScene_LaunchMoreOptionsMenu::handleFocusChange(F64 controlId, F64 childId
case eLaunchCheckbox_DayLightCycle: case eLaunchCheckbox_DayLightCycle:
stringId = IDS_GAMEOPTION_DAYLIGHT_CYCLE; stringId = IDS_GAMEOPTION_DAYLIGHT_CYCLE;
break; break;
case eControl_EditSeed: case eLaunchCheckbox_NoMobCap:
stringId = IDS_GAMEOPTION_SEED; stringId = IDS_GAMEOPTION_SEED;
break; break;
case eControl_WorldMobCap: case eControl_EditSeed:
stringId = IDS_GAMEOPTION_SEED; stringId = IDS_GAMEOPTION_SEED;
break; break;
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
@ -660,11 +649,6 @@ void UIScene_LaunchMoreOptionsMenu::handleSliderMove(F64 sliderId, F64 currentVa
int value = static_cast<int>(currentValue); int value = static_cast<int>(currentValue);
switch(static_cast<int>(sliderId)) 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: case eControl_WorldSize:
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
m_sliderWorldSize.handleSliderMove(value); m_sliderWorldSize.handleSliderMove(value);

View file

@ -32,13 +32,13 @@ private:
eLaunchCheckbox_TileDrops, eLaunchCheckbox_TileDrops,
eLaunchCheckbox_NaturalRegeneration, eLaunchCheckbox_NaturalRegeneration,
eLaunchCheckbox_DayLightCycle, eLaunchCheckbox_DayLightCycle,
eLaunchCheckbox_NoMobCap,
eLaunchCheckboxes_Count, eLaunchCheckboxes_Count,
eControl_EditSeed, eControl_EditSeed,
eControl_WorldSize, eControl_WorldSize,
eControl_WorldResize, eControl_WorldResize,
eControl_WorldMobCap,
eControl_Count eControl_Count
}; };
@ -62,7 +62,6 @@ private:
UIControl_TextInput m_editSeed; UIControl_TextInput m_editSeed;
UIControl_Slider m_sliderWorldSize; UIControl_Slider m_sliderWorldSize;
UIControl_Slider m_sliderWorldResize; UIControl_Slider m_sliderWorldResize;
UIControl_Slider m_sliderWorldMobCap; // Added ~ Mob cap slider for user control
IggyName m_funcSetMenuType, m_funcChangeTab, m_funcSetDescription; IggyName m_funcSetMenuType, m_funcChangeTab, m_funcSetDescription;
UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene)
UI_MAP_ELEMENT( m_labelGameOptions, "LabelGame") 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_MobLoot], "CheckboxMobLoot")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_TileDrops], "CheckboxTileDrops") UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_TileDrops], "CheckboxTileDrops")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_NaturalRegeneration], "CheckboxNaturalRegeneration") UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_NaturalRegeneration], "CheckboxNaturalRegeneration")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_NoMobCap], "CheckboxNoMobCap")
UI_END_MAP_CHILD_ELEMENTS() UI_END_MAP_CHILD_ELEMENTS()
UI_MAP_ELEMENT(m_worldOptions, "WorldOptions") UI_MAP_ELEMENT(m_worldOptions, "WorldOptions")
@ -101,7 +101,6 @@ private:
UI_MAP_ELEMENT( m_labelRandomSeed, "RandomSeed") UI_MAP_ELEMENT( m_labelRandomSeed, "RandomSeed")
UI_MAP_ELEMENT( m_labelWorldSize, "WorldSize") UI_MAP_ELEMENT( m_labelWorldSize, "WorldSize")
UI_MAP_ELEMENT( m_sliderWorldSize, "WorldSizeSlider") 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_Structures], "CheckboxStructures")
UI_MAP_ELEMENT( m_checkboxes[eLaunchCheckbox_BonusChest], "CheckboxBonusChest") 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.bDisableSaving = app.GetGameHostOption(uiHostOptions,eGameHostOption_DisableSaving)>0?TRUE:FALSE;
m_MoreOptionsParams.currentWorldSize = static_cast<EGameHostOptionWorldSize>(app.GetGameHostOption(uiHostOptions, eGameHostOption_WorldSize)); m_MoreOptionsParams.currentWorldSize = static_cast<EGameHostOptionWorldSize>(app.GetGameHostOption(uiHostOptions, eGameHostOption_WorldSize));
m_MoreOptionsParams.newWorldSize = m_MoreOptionsParams.currentWorldSize; 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.bMobGriefing = app.GetGameHostOption(uiHostOptions, eGameHostOption_MobGriefing);
m_MoreOptionsParams.bKeepInventory = app.GetGameHostOption(uiHostOptions, eGameHostOption_KeepInventory); 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.bDoTileDrops = app.GetGameHostOption(uiHostOptions, eGameHostOption_DoTileDrops);
m_MoreOptionsParams.bNaturalRegeneration = app.GetGameHostOption(uiHostOptions, eGameHostOption_NaturalRegeneration); m_MoreOptionsParams.bNaturalRegeneration = app.GetGameHostOption(uiHostOptions, eGameHostOption_NaturalRegeneration);
m_MoreOptionsParams.bDoDaylightCycle = app.GetGameHostOption(uiHostOptions, eGameHostOption_DoDaylightCycle); m_MoreOptionsParams.bDoDaylightCycle = app.GetGameHostOption(uiHostOptions, eGameHostOption_DoDaylightCycle);
m_MoreOptionsParams.bNoMobCap = app.GetGameHostOption(uiHostOptions,eGameHostOption_NoMobCap);
bool cheatsOn = m_MoreOptionsParams.bHostPrivileges; bool cheatsOn = m_MoreOptionsParams.bHostPrivileges;
if (!cheatsOn) 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_DoTileDrops, pClass->m_MoreOptionsParams.bDoTileDrops);
app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration); app.SetGameHostOption(eGameHostOption_NaturalRegeneration, pClass->m_MoreOptionsParams.bNaturalRegeneration);
app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle); app.SetGameHostOption(eGameHostOption_DoDaylightCycle, pClass->m_MoreOptionsParams.bDoDaylightCycle);
app.SetGameHostOption(eGameHostOption_NoMobCap, pClass->m_MoreOptionsParams.bNoMobCap);
#ifdef _LARGE_WORLDS #ifdef _LARGE_WORLDS
app.SetGameHostOption(eGameHostOption_WorldSize, pClass->m_MoreOptionsParams.worldSize+1 ); // 0 is GAME_HOST_OPTION_WORLDSIZE_UNKNOWN app.SetGameHostOption(eGameHostOption_WorldSize, pClass->m_MoreOptionsParams.worldSize+1 ); // 0 is GAME_HOST_OPTION_WORLDSIZE_UNKNOWN
#endif #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(64, true );
// app.SetGameNewWorldSize(0, false ); // app.SetGameNewWorldSize(0, false );

View file

@ -350,6 +350,7 @@ typedef struct _LaunchMoreOptionsMenuInitData
bool bDoTileDrops; bool bDoTileDrops;
bool bNaturalRegeneration; bool bNaturalRegeneration;
bool bDoDaylightCycle; bool bDoDaylightCycle;
bool bNoMobCap;
bool bOnlineSettingChangedBySystem; bool bOnlineSettingChangedBySystem;
@ -359,7 +360,6 @@ typedef struct _LaunchMoreOptionsMenuInitData
wstring seed; wstring seed;
int worldSize; int worldSize;
int worldMobCap;
bool bDisableSaving; bool bDisableSaving;
EGameHostOptionWorldSize currentWorldSize; EGameHostOptionWorldSize currentWorldSize;
@ -376,7 +376,6 @@ typedef struct _LaunchMoreOptionsMenuInitData
bTNT = true; bTNT = true;
iPad = -1; iPad = -1;
worldSize = 3; worldSize = 3;
worldMobCap = 0;
seed = L""; seed = L"";
bDisableSaving = false; bDisableSaving = false;
newWorldSize = e_worldSize_Unknown; newWorldSize = e_worldSize_Unknown;
@ -389,6 +388,7 @@ typedef struct _LaunchMoreOptionsMenuInitData
bDoTileDrops = true; bDoTileDrops = true;
bNaturalRegeneration = true; bNaturalRegeneration = true;
bDoDaylightCycle = true; bDoDaylightCycle = true;
bNoMobCap=false;
} }
} }
LaunchMoreOptionsMenuInitData; 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_Difficulty, GetDedicatedServerInt(settings, L"difficulty", app.GetGameHostOption(eGameHostOption_Difficulty)));
app.SetGameHostOption(eGameHostOption_GameType, GetDedicatedServerInt(settings, L"gamemode", app.GetGameHostOption(eGameHostOption_GameType))); 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_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_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); 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_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); 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("\n*** SERVER SETTINGS ***\n");
app.DebugPrintf("ServerSettings: host-friends-only is %s\n",(app.GetGameHostOption(eGameHostOption_FriendsOfFriends)>0)?"on":"off"); 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"); 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) vector<Biome::MobSpawnerData *> *Biome::getMobs(MobCategory *category)
{ {
if (category == MobCategory::monster) return &enemies; 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::waterCreature) return &waterFriendlies;
if (category == MobCategory::creature_chicken) return &friendlies_chicken; if (category == MobCategory::creature_chicken) return &friendlies_chicken;
if (category == MobCategory::creature_wolf) return &friendlies_wolf; if (category == MobCategory::creature_wolf) return &friendlies_wolf;

View file

@ -82,6 +82,7 @@ public:
protected: protected:
vector<MobSpawnerData *> enemies; 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 *> friendlies;
vector<MobSpawnerData *> waterFriendlies; vector<MobSpawnerData *> waterFriendlies;
vector<MobSpawnerData *> friendlies_chicken; vector<MobSpawnerData *> friendlies_chicken;

View file

@ -4695,7 +4695,7 @@ void Level::decrementUnsavedChunkCount()
bool Level::canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType) bool Level::canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType)
{ {
if (app.GetGameHostOption(eGameHostOption_WorldMobCap) == 3) if (app.GetGameHostOption(eGameHostOption_NoMobCap))
{ {
return true; 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 // 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); 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); // Raised these to be identical to base LCE
ambient = new MobCategory(15, Material::air, true, false, eTYPE_AMBIENT, false), 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); waterCreature = new MobCategory(5, Material::water, true, false, eTYPE_WATERANIMAL, false);
values[0] = monster; values[0] = monster;
@ -62,18 +63,53 @@ void MobCategory::staticCtor()
values[4] = creature_wolf; values[4] = creature_wolf;
values[5] = creature_chicken; values[5] = creature_chicken;
values[6] = creature_mushroomcow; 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) 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 // 4J - added
const eINSTANCEOF MobCategory::getEnumBaseClass() const eINSTANCEOF MobCategory::getEnumBaseClass()
{ {
if (app.GetGameHostOption(eGameHostOption_NoMobCap)) return m_eJavaBase;
return m_eBase; return m_eBase;
} }
@ -105,72 +141,4 @@ bool MobCategory::isSingleType()
bool MobCategory::isPersistent() bool MobCategory::isPersistent()
{ {
return m_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_isPersistent;
const bool m_isSingleType; // 4J Added const bool m_isSingleType; // 4J Added
const eINSTANCEOF m_eBase; // 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); 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: public:
const type_info getBaseClass(); const type_info getBaseClass();
@ -85,7 +91,5 @@ public:
bool isPersistent(); bool isPersistent();
public: public:
// Add a function to update the mob caps
static void updateMobCaps(int mode);
static void staticCtor(); 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 // Use variable to not repeat checks
int maxInstances = mobCategory->getMaxInstancesPerLevel(); int maxInstances = mobCategory->getMaxInstancesPerLevel();
// Check for if the mob cap is "off" (works as Java does, scaled by chunk count) // 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) if (usesChunkLimit)
{ {
// Use Java logic for the max count instead, accounting for chunks polled and the magic number. // Use Java logic for the max count instead, accounting for chunks polled and the magic number.
maxInstances = mobCategory->getMaxInstancesPerChunk() * chunksToPoll.size() / 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 // 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