diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 1a569c9eb5..708635e15e 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -644,6 +644,7 @@ resources.max = Max bannedblocks = Banned Blocks objectives = Objectives bannedunits = Banned Units +whitelist = Whitelist addall = Add All launch.from = Launching From: [accent]{0} launch.capacity = Launching Item Capacity: [accent]{0} @@ -1172,6 +1173,7 @@ rules.placerangecheck = Placement Range Check rules.enemyCheat = Infinite Enemy Team Resources rules.blockhealthmultiplier = Block Health Multiplier rules.blockdamagemultiplier = Block Damage Multiplier +rules.hideBannedBlocks = Hide Banned Blocks rules.unitbuildspeedmultiplier = Unit Production Speed Multiplier rules.unitcostmultiplier = Unit Cost Multiplier rules.unithealthmultiplier = Unit Health Multiplier diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index 898bdcd8de..80c5146027 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -95,6 +95,12 @@ public class Rules{ public boolean onlyDepositCore = false; /** If true, every enemy block in the radius of the (enemy) core is destroyed upon death. Used for campaign maps. */ public boolean coreDestroyClear = false; + /** If true, banned blocks are hidden from the build menu. */ + public boolean hideBannedBlocks = false; + /** If true, bannedBlocks becomes a whitelist. */ + public boolean blockWhitelist = false; + /** If true, bannedUnits becomes a whitelist. */ + public boolean unitWhitelist = false; /** Radius around enemy wave drop zones.*/ public float dropZoneRadius = 300f; /** Time between waves in ticks. */ @@ -228,6 +234,14 @@ public class Rules{ return buildSpeedMultiplier * teams.get(team).buildSpeedMultiplier; } + public boolean isBanned(Block block){ + return blockWhitelist != bannedBlocks.contains(block); + } + + public boolean isBanned(UnitType unit){ + return unitWhitelist != bannedUnits.contains(unit); + } + /** A team-specific ruleset. */ public static class TeamRule{ /** Whether, when AI is enabled, ships should be spawned from the core. TODO remove / unnecessary? */ diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index b0d26ae353..cc8deb6b99 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -557,7 +557,7 @@ public class UnitType extends UnlockableContent{ } public boolean isBanned(){ - return state.rules.bannedUnits.contains(this); + return state.rules.isBanned(this); } @Override diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index 8c79d2deec..b6bbf081a0 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -180,7 +180,9 @@ public class CustomRulesDialog extends BaseDialog{ () -> {}, () -> {} )).left().width(300f).row(); + check("@rules.hidebannedblocks", b -> rules.hideBannedBlocks = b, () -> rules.hideBannedBlocks); main.button("@bannedblocks", () -> showBanned("@bannedblocks", ContentType.block, rules.bannedBlocks, Block::canBeBuilt)).left().width(300f).row(); + check("@whitelist", b -> rules.blockWhitelist = b, () -> rules.blockWhitelist); //TODO objectives would be nice if(experimental && false){ @@ -198,6 +200,7 @@ public class CustomRulesDialog extends BaseDialog{ number("@rules.unitcostmultiplier", f -> rules.unitCostMultiplier = f, () -> rules.unitCostMultiplier); main.button("@bannedunits", () -> showBanned("@bannedunits", ContentType.unit, rules.bannedUnits, u -> !u.isHidden())).left().width(300f).row(); + check("@whitelist", b -> rules.unitWhitelist = b, () -> rules.unitWhitelist); title("@rules.title.enemy"); check("@rules.attack", b -> rules.attackMode = b, () -> rules.attackMode); diff --git a/core/src/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/mindustry/ui/dialogs/DatabaseDialog.java index 0700ba562a..0100836ce2 100644 --- a/core/src/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/mindustry/ui/dialogs/DatabaseDialog.java @@ -74,7 +74,7 @@ public class DatabaseDialog extends BaseDialog{ Image image = unlocked(unlock) ? new Image(unlock.uiIcon).setScaling(Scaling.fit) : new Image(Icon.lock, Pal.gray); //banned cross - if(state.isGame() && (unlock instanceof UnitType u && u.isBanned() || unlock instanceof Block b && state.rules.bannedBlocks.contains(b))){ + if(state.isGame() && (unlock instanceof UnitType u && u.isBanned() || unlock instanceof Block b && state.rules.isBanned(b))){ list.stack(image, new Image(Icon.cancel){{ setColor(Color.scarlet); touchable = Touchable.disabled; diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index c64718d56b..92332e8796 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -853,11 +853,11 @@ public class Block extends UnlockableContent implements Senseable{ } public boolean isVisible(){ - return !isHidden(); + return !isHidden() && (state.rules.editor || (!state.rules.hideBannedBlocks || !state.rules.isBanned(this))); } public boolean isPlaceable(){ - return isVisible() && (!state.rules.bannedBlocks.contains(this) || state.rules.editor) && supportsEnv(state.rules.env); + return isVisible() && (!state.rules.isBanned(this) || state.rules.editor) && supportsEnv(state.rules.env); } /** @return whether this block supports a specific environment. */ diff --git a/core/src/mindustry/world/blocks/payloads/Constructor.java b/core/src/mindustry/world/blocks/payloads/Constructor.java index bc13018691..695600afdd 100644 --- a/core/src/mindustry/world/blocks/payloads/Constructor.java +++ b/core/src/mindustry/world/blocks/payloads/Constructor.java @@ -45,7 +45,7 @@ public class Constructor extends BlockProducer{ } public boolean canProduce(Block b){ - return b.isVisible() && b.size >= minBlockSize && b.size <= maxBlockSize && !(b instanceof CoreBlock) && !state.rules.bannedBlocks.contains(b) && b.environmentBuildable() && (filter.isEmpty() || filter.contains(b)); + return b.isVisible() && b.size >= minBlockSize && b.size <= maxBlockSize && !(b instanceof CoreBlock) && !state.rules.isBanned(b) && b.environmentBuildable() && (filter.isEmpty() || filter.contains(b)); } public class ConstructorBuild extends BlockProducerBuild{ @@ -91,4 +91,4 @@ public class Constructor extends BlockProducer{ recipe = Vars.content.block(read.s()); } } -} \ No newline at end of file +} diff --git a/core/src/mindustry/world/blocks/payloads/PayloadRouter.java b/core/src/mindustry/world/blocks/payloads/PayloadRouter.java index baa71ef810..6b10281279 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadRouter.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadRouter.java @@ -44,7 +44,7 @@ public class PayloadRouter extends PayloadConveyor{ } public boolean canSort(Block b){ - return b.isVisible() && b.size <= size && !(b instanceof CoreBlock) && !state.rules.bannedBlocks.contains(b) && b.environmentBuildable(); + return b.isVisible() && b.size <= size && !(b instanceof CoreBlock) && !state.rules.isBanned(b) && b.environmentBuildable(); } public boolean canSort(UnitType t){ diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index b6f6de2380..eab910841e 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -76,7 +76,7 @@ public class PayloadSource extends PayloadBlock{ } public boolean canProduce(Block b){ - return b.isVisible() && b.size < size && !(b instanceof CoreBlock) && !state.rules.bannedBlocks.contains(b) && b.environmentBuildable(); + return b.isVisible() && b.size < size && !(b instanceof CoreBlock) && !state.rules.isBanned(b) && b.environmentBuildable(); } public boolean canProduce(UnitType t){