1313using System ;
1414using System . Collections . Generic ;
1515using System . Diagnostics ;
16+ using System . Drawing . Text ;
1617using System . Linq ;
18+ using UnityEngine ;
19+ using Logger = Rocket . Core . Logging . Logger ;
1720
1821namespace RestoreMonarchy . BuildingRestrictions
1922{
@@ -78,7 +81,10 @@ protected override void Unload()
7881 { "PlayerNotFound" , "Player [[b]]{0}[[/b]] not found." } ,
7982 { "BuildingStatsOtherNoPermission" , "You don't have permission to check other player building stats." } ,
8083 { "MaxBarricadeHeightRestriction" , "You can't build [[b]]{0}[[/b]] because it's higher than max [[b]]{1}m[[/b]] height above the ground." } ,
81- { "MaxStructureHeightRestriction" , "You can't build [[b]]{0}[[/b]] because it's higher than max [[b]]{1}m[[/b]] height above the ground." }
84+ { "MaxStructureHeightRestriction" , "You can't build [[b]]{0}[[/b]] because it's higher than max [[b]]{1}m[[/b]] height above the ground." } ,
85+ { "BuildingsInLocationRestriction" , "You can't build [[b]]{0}[[/b]] here because you have reached the limit of max [[b]]{1}[[/b]] buildings in this location." } ,
86+ { "BuildingsInLocationRestrictionNone" , "You can't build in this location." } ,
87+ { "BuildingsInLocationRestrictionInfo" , "You have built [[b]]{0}/{1}[[/b]] buildings in this location." }
8288 } ;
8389
8490 private void OnLevelLoaded ( int level )
@@ -100,8 +106,11 @@ private void OnLevelLoaded(int level)
100106 {
101107 ItemId = drop . asset . id ,
102108 Build = drop . asset . build ,
103- Transform = drop . model
109+ Transform = drop . model ,
110+ IsInBound = TryGetBoundsWithHeight ( drop . model . position , out byte boundIndex ) ,
111+ BoundIndex = boundIndex
104112 } ;
113+
105114 BarricadeData data = drop . GetServersideData ( ) ;
106115 Database . AddPlayerBarricade ( data . owner , playerBarricade ) ;
107116 }
@@ -119,8 +128,11 @@ private void OnLevelLoaded(int level)
119128 {
120129 ItemId = drop . asset . id ,
121130 Construct = drop . asset . construct ,
122- Transform = drop . model
131+ Transform = drop . model ,
132+ IsInBound = TryGetBoundsWithHeight ( drop . model . position , out byte boundIndex ) ,
133+ BoundIndex = boundIndex
123134 } ;
135+
124136 StructureData data = drop . GetServersideData ( ) ;
125137 Database . AddPlayerStructure ( data . owner , playerStructure ) ;
126138 }
@@ -158,7 +170,7 @@ public decimal GetPlayerBuildingsMultiplier(IRocketPlayer player)
158170 return multiplier ;
159171 }
160172
161- private void OnDeployBarricadeRequested ( Barricade barricade , ItemBarricadeAsset asset , UnityEngine . Transform hit , ref UnityEngine . Vector3 point , ref float angle_x , ref float angle_y , ref float angle_z , ref ulong owner , ref ulong group , ref bool shouldAllow )
173+ private void OnDeployBarricadeRequested ( Barricade barricade , ItemBarricadeAsset asset , Transform hit , ref Vector3 point , ref float angle_x , ref float angle_y , ref float angle_z , ref ulong owner , ref ulong group , ref bool shouldAllow )
162174 {
163175 if ( ! shouldAllow )
164176 {
@@ -219,6 +231,34 @@ private void OnDeployBarricadeRequested(Barricade barricade, ItemBarricadeAsset
219231 }
220232 }
221233
234+ System . Action action = null ;
235+ if ( Configuration . Instance . EnableMaxBuildingsPerLocation && TryGetBoundsWithHeight ( point , out byte boundIndex )
236+ && asset . build != EBuild . BEACON && asset . build != EBuild . VEHICLE && asset . build != EBuild . CHARGE && asset . build != EBuild . SAFEZONE )
237+ {
238+ if ( Configuration . Instance . MaxBuildingsPerLocation == 0 )
239+ {
240+ SendMessageToPlayer ( unturnedPlayer , "BuildingsInLocationRestrictionNone" ) ;
241+ shouldAllow = false ;
242+ return ;
243+ }
244+
245+ int barricadesCount = playerBuildings ? . Barricades . Count ( x => x . IsInBound && x . BoundIndex == boundIndex ) ?? 0 ;
246+ int structuresCount = playerBuildings ? . Structures . Count ( x => x . IsInBound && x . BoundIndex == boundIndex ) ?? 0 ;
247+ int buildingsCount = barricadesCount + structuresCount ;
248+
249+ int maxBuildings = ( int ) ( Configuration . Instance . MaxBuildingsPerLocation * multiplier ) ;
250+ if ( maxBuildings <= buildingsCount )
251+ {
252+ SendMessageToPlayer ( unturnedPlayer , "BuildingsInLocationRestriction" , itemName , maxBuildings ) ;
253+ shouldAllow = false ;
254+ return ;
255+ }
256+ else
257+ {
258+ action = ( ) => SendMessageToPlayer ( unturnedPlayer , "BuildingsInLocationRestrictionInfo" , buildingsCount + 1 , maxBuildings ) ;
259+ }
260+ }
261+
222262 if ( Configuration . Instance . Barricades != null && Configuration . Instance . Barricades . Any ( ) )
223263 {
224264 int itemIdCount = playerBuildings ? . Barricades . Count ( x => x . ItemId == barricade . asset . id ) ?? 0 ;
@@ -256,6 +296,11 @@ private void OnDeployBarricadeRequested(Barricade barricade, ItemBarricadeAsset
256296 return ;
257297 }
258298 }
299+
300+ if ( action != null )
301+ {
302+ action ( ) ;
303+ }
259304 }
260305
261306 private void OnDeployStructureRequested ( Structure structure , ItemStructureAsset asset , ref UnityEngine . Vector3 point , ref float angle_x , ref float angle_y , ref float angle_z , ref ulong owner , ref ulong group , ref bool shouldAllow )
@@ -319,6 +364,33 @@ private void OnDeployStructureRequested(Structure structure, ItemStructureAsset
319364 }
320365 }
321366
367+ System . Action action = null ;
368+ if ( Configuration . Instance . EnableMaxBuildingsPerLocation && TryGetBoundsWithHeight ( point , out byte boundIndex ) )
369+ {
370+ if ( Configuration . Instance . MaxBuildingsPerLocation == 0 )
371+ {
372+ SendMessageToPlayer ( unturnedPlayer , "BuildingsInLocationRestrictionNone" ) ;
373+ shouldAllow = false ;
374+ return ;
375+ }
376+
377+ int barricadesCount = playerBuildings ? . Barricades . Count ( x => x . IsInBound && x . BoundIndex == boundIndex ) ?? 0 ;
378+ int structuresCount = playerBuildings ? . Structures . Count ( x => x . IsInBound && x . BoundIndex == boundIndex ) ?? 0 ;
379+ int buildingsCount = barricadesCount + structuresCount ;
380+
381+ int maxBuildings = ( int ) ( Configuration . Instance . MaxBuildingsPerLocation * multiplier ) ;
382+ if ( maxBuildings <= buildingsCount )
383+ {
384+ SendMessageToPlayer ( unturnedPlayer , "BuildingsInLocationRestriction" , itemName , maxBuildings ) ;
385+ shouldAllow = false ;
386+ return ;
387+ }
388+ else
389+ {
390+ action = ( ) => SendMessageToPlayer ( unturnedPlayer , "BuildingsInLocationRestrictionInfo" , buildingsCount + 1 , maxBuildings ) ;
391+ }
392+ }
393+
322394 if ( Configuration . Instance . Structures != null && Configuration . Instance . Structures . Any ( ) )
323395 {
324396 int itemIdCount = playerBuildings ? . Structures . Count ( x => x . ItemId == structure . asset . id ) ?? 0 ;
@@ -356,6 +428,11 @@ private void OnDeployStructureRequested(Structure structure, ItemStructureAsset
356428 return ;
357429 }
358430 }
431+
432+ if ( action != null )
433+ {
434+ action ( ) ;
435+ }
359436 }
360437
361438 private void OnBarricadeSpawned ( BarricadeRegion region , BarricadeDrop drop )
@@ -365,7 +442,9 @@ private void OnBarricadeSpawned(BarricadeRegion region, BarricadeDrop drop)
365442 {
366443 ItemId = drop . asset . id ,
367444 Build = drop . asset . build ,
368- Transform = drop . model
445+ Transform = drop . model ,
446+ IsInBound = TryGetBoundsWithHeight ( drop . model . position , out byte boundIndex ) ,
447+ BoundIndex = boundIndex
369448 } ;
370449 Database . AddPlayerBarricade ( barricadeData . owner , playerBarricade ) ;
371450 }
@@ -377,11 +456,36 @@ private void OnStructureSpawned(StructureRegion region, StructureDrop drop)
377456 {
378457 ItemId = drop . asset . id ,
379458 Construct = drop . asset . construct ,
380- Transform = drop . model
459+ Transform = drop . model ,
460+ IsInBound = TryGetBoundsWithHeight ( drop . model . position , out byte boundIndex ) ,
461+ BoundIndex = boundIndex
381462 } ;
382463 Database . AddPlayerStructure ( structureData . owner , playerStructure ) ;
383464 }
384465
466+ public bool TryGetBoundsWithHeight ( Vector3 position , out byte boundIndex )
467+ {
468+ if ( LevelNavigation . tryGetBounds ( position , out boundIndex ) )
469+ {
470+ Bounds bound = LevelNavigation . bounds [ boundIndex ] ;
471+ if ( IsInBoundsHeight ( bound , position ) )
472+ {
473+ return true ;
474+ }
475+ }
476+
477+ return false ;
478+ }
479+
480+ private bool IsInBoundsHeight ( Bounds bound , Vector3 position )
481+ {
482+ float goundLevel = LevelGround . getHeight ( position ) ;
483+ float buildingY = position . y ;
484+ float buildingHeight = buildingY - goundLevel ;
485+
486+ return buildingHeight <= Configuration . Instance . MaxBuildingsPerLocationHeight ;
487+ }
488+
385489 internal void SendMessageToPlayer ( IRocketPlayer player , string translationKey , params object [ ] placeholder )
386490 {
387491 if ( player == null )
0 commit comments