001/*
002 * PlotSquared, a land and world management plugin for Minecraft.
003 * Copyright (C) IntellectualSites <https://intellectualsites.com>
004 * Copyright (C) IntellectualSites team and contributors
005 *
006 * This program is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
018 */
019package com.plotsquared.core.plot.flag;
020
021import com.google.common.base.Preconditions;
022import com.plotsquared.core.plot.flag.implementations.AnalysisFlag;
023import com.plotsquared.core.plot.flag.implementations.AnimalAttackFlag;
024import com.plotsquared.core.plot.flag.implementations.AnimalCapFlag;
025import com.plotsquared.core.plot.flag.implementations.AnimalInteractFlag;
026import com.plotsquared.core.plot.flag.implementations.BeaconEffectsFlag;
027import com.plotsquared.core.plot.flag.implementations.BlockBurnFlag;
028import com.plotsquared.core.plot.flag.implementations.BlockIgnitionFlag;
029import com.plotsquared.core.plot.flag.implementations.BlockedCmdsFlag;
030import com.plotsquared.core.plot.flag.implementations.BreakFlag;
031import com.plotsquared.core.plot.flag.implementations.ChatFlag;
032import com.plotsquared.core.plot.flag.implementations.CopperOxideFlag;
033import com.plotsquared.core.plot.flag.implementations.CoralDryFlag;
034import com.plotsquared.core.plot.flag.implementations.CropGrowFlag;
035import com.plotsquared.core.plot.flag.implementations.DenyExitFlag;
036import com.plotsquared.core.plot.flag.implementations.DenyPortalTravelFlag;
037import com.plotsquared.core.plot.flag.implementations.DenyPortalsFlag;
038import com.plotsquared.core.plot.flag.implementations.DenyTeleportFlag;
039import com.plotsquared.core.plot.flag.implementations.DescriptionFlag;
040import com.plotsquared.core.plot.flag.implementations.DeviceInteractFlag;
041import com.plotsquared.core.plot.flag.implementations.DisablePhysicsFlag;
042import com.plotsquared.core.plot.flag.implementations.DoneFlag;
043import com.plotsquared.core.plot.flag.implementations.DropProtectionFlag;
044import com.plotsquared.core.plot.flag.implementations.EntityCapFlag;
045import com.plotsquared.core.plot.flag.implementations.EntityChangeBlockFlag;
046import com.plotsquared.core.plot.flag.implementations.ExplosionFlag;
047import com.plotsquared.core.plot.flag.implementations.FarewellFlag;
048import com.plotsquared.core.plot.flag.implementations.FeedFlag;
049import com.plotsquared.core.plot.flag.implementations.FlyFlag;
050import com.plotsquared.core.plot.flag.implementations.ForcefieldFlag;
051import com.plotsquared.core.plot.flag.implementations.GamemodeFlag;
052import com.plotsquared.core.plot.flag.implementations.GrassGrowFlag;
053import com.plotsquared.core.plot.flag.implementations.GreetingFlag;
054import com.plotsquared.core.plot.flag.implementations.GuestGamemodeFlag;
055import com.plotsquared.core.plot.flag.implementations.HangingBreakFlag;
056import com.plotsquared.core.plot.flag.implementations.HangingPlaceFlag;
057import com.plotsquared.core.plot.flag.implementations.HealFlag;
058import com.plotsquared.core.plot.flag.implementations.HideInfoFlag;
059import com.plotsquared.core.plot.flag.implementations.HostileAttackFlag;
060import com.plotsquared.core.plot.flag.implementations.HostileCapFlag;
061import com.plotsquared.core.plot.flag.implementations.HostileInteractFlag;
062import com.plotsquared.core.plot.flag.implementations.IceFormFlag;
063import com.plotsquared.core.plot.flag.implementations.IceMeltFlag;
064import com.plotsquared.core.plot.flag.implementations.InstabreakFlag;
065import com.plotsquared.core.plot.flag.implementations.InvincibleFlag;
066import com.plotsquared.core.plot.flag.implementations.ItemDropFlag;
067import com.plotsquared.core.plot.flag.implementations.KeepFlag;
068import com.plotsquared.core.plot.flag.implementations.KeepInventoryFlag;
069import com.plotsquared.core.plot.flag.implementations.KelpGrowFlag;
070import com.plotsquared.core.plot.flag.implementations.LeafDecayFlag;
071import com.plotsquared.core.plot.flag.implementations.LecternReadBookFlag;
072import com.plotsquared.core.plot.flag.implementations.LiquidFlowFlag;
073import com.plotsquared.core.plot.flag.implementations.MiscBreakFlag;
074import com.plotsquared.core.plot.flag.implementations.MiscCapFlag;
075import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag;
076import com.plotsquared.core.plot.flag.implementations.MiscPlaceFlag;
077import com.plotsquared.core.plot.flag.implementations.MobBreakFlag;
078import com.plotsquared.core.plot.flag.implementations.MobCapFlag;
079import com.plotsquared.core.plot.flag.implementations.MobPlaceFlag;
080import com.plotsquared.core.plot.flag.implementations.MusicFlag;
081import com.plotsquared.core.plot.flag.implementations.MycelGrowFlag;
082import com.plotsquared.core.plot.flag.implementations.NoWorldeditFlag;
083import com.plotsquared.core.plot.flag.implementations.NotifyEnterFlag;
084import com.plotsquared.core.plot.flag.implementations.NotifyLeaveFlag;
085import com.plotsquared.core.plot.flag.implementations.PlaceFlag;
086import com.plotsquared.core.plot.flag.implementations.PlayerInteractFlag;
087import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag;
088import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag;
089import com.plotsquared.core.plot.flag.implementations.PriceFlag;
090import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag;
091import com.plotsquared.core.plot.flag.implementations.PveFlag;
092import com.plotsquared.core.plot.flag.implementations.PvpFlag;
093import com.plotsquared.core.plot.flag.implementations.RedstoneFlag;
094import com.plotsquared.core.plot.flag.implementations.SculkSensorInteractFlag;
095import com.plotsquared.core.plot.flag.implementations.ServerPlotFlag;
096import com.plotsquared.core.plot.flag.implementations.SnowFormFlag;
097import com.plotsquared.core.plot.flag.implementations.SnowMeltFlag;
098import com.plotsquared.core.plot.flag.implementations.SoilDryFlag;
099import com.plotsquared.core.plot.flag.implementations.TamedAttackFlag;
100import com.plotsquared.core.plot.flag.implementations.TamedInteractFlag;
101import com.plotsquared.core.plot.flag.implementations.TimeFlag;
102import com.plotsquared.core.plot.flag.implementations.TitlesFlag;
103import com.plotsquared.core.plot.flag.implementations.UntrustedVisitFlag;
104import com.plotsquared.core.plot.flag.implementations.UseFlag;
105import com.plotsquared.core.plot.flag.implementations.VehicleBreakFlag;
106import com.plotsquared.core.plot.flag.implementations.VehicleCapFlag;
107import com.plotsquared.core.plot.flag.implementations.VehiclePlaceFlag;
108import com.plotsquared.core.plot.flag.implementations.VehicleUseFlag;
109import com.plotsquared.core.plot.flag.implementations.VillagerInteractFlag;
110import com.plotsquared.core.plot.flag.implementations.VineGrowFlag;
111import com.plotsquared.core.plot.flag.implementations.WeatherFlag;
112import org.checkerframework.checker.nullness.qual.NonNull;
113
114import java.util.Collections;
115import java.util.HashMap;
116import java.util.Locale;
117import java.util.Map;
118
119public final class GlobalFlagContainer extends FlagContainer {
120
121    private static GlobalFlagContainer instance;
122    private static Map<String, Class<?>> stringClassMap;
123
124    private GlobalFlagContainer() {
125        super(null, (flag, type) -> {
126            if (type == PlotFlagUpdateType.FLAG_ADDED) {
127                stringClassMap.put(flag.getName().toLowerCase(Locale.ENGLISH), flag.getClass());
128            }
129        });
130        stringClassMap = new HashMap<>();
131
132        // Register all default flags here
133        // Block type list flags
134        this.addFlag(BreakFlag.BREAK_NONE);
135        this.addFlag(UseFlag.USE_NONE);
136        this.addFlag(PlaceFlag.PLACE_NONE);
137
138        // Boolean flags
139        this.addFlag(AnimalAttackFlag.ANIMAL_ATTACK_FALSE);
140        this.addFlag(AnimalInteractFlag.ANIMAL_INTERACT_FALSE);
141        this.addFlag(BlockBurnFlag.BLOCK_BURN_FALSE);
142        this.addFlag(BeaconEffectsFlag.BEACON_EFFECT_TRUE);
143        this.addFlag(BlockIgnitionFlag.BLOCK_IGNITION_TRUE);
144        this.addFlag(ChatFlag.CHAT_FLAG_TRUE);
145        this.addFlag(CopperOxideFlag.COPPER_OXIDE_FALSE);
146        this.addFlag(CoralDryFlag.CORAL_DRY_FALSE);
147        this.addFlag(CropGrowFlag.CROP_GROW_TRUE);
148        this.addFlag(DenyExitFlag.DENY_EXIT_FLAG_FALSE);
149        this.addFlag(DenyPortalsFlag.DENY_PORTALS_FALSE);
150        this.addFlag(DenyPortalTravelFlag.DENY_PORTAL_TRAVEL_FALSE);
151        this.addFlag(DeviceInteractFlag.DEVICE_INTERACT_FALSE);
152        this.addFlag(DisablePhysicsFlag.DISABLE_PHYSICS_FALSE);
153        this.addFlag(DropProtectionFlag.DROP_PROTECTION_FALSE);
154        this.addFlag(EntityChangeBlockFlag.ENTITY_CHANGE_BLOCK_FALSE);
155        this.addFlag(ExplosionFlag.EXPLOSION_FALSE);
156        this.addFlag(ForcefieldFlag.FORCEFIELD_FALSE);
157        this.addFlag(GrassGrowFlag.GRASS_GROW_TRUE);
158        this.addFlag(HangingBreakFlag.HANGING_BREAK_FALSE);
159        this.addFlag(HangingPlaceFlag.HANGING_PLACE_FALSE);
160        this.addFlag(HideInfoFlag.HIDE_INFO_FALSE);
161        this.addFlag(HostileAttackFlag.HOSTILE_ATTACK_FALSE);
162        this.addFlag(HostileInteractFlag.HOSTILE_INTERACT_FALSE);
163        this.addFlag(IceFormFlag.ICE_FORM_FALSE);
164        this.addFlag(IceMeltFlag.ICE_MELT_FALSE);
165        this.addFlag(InstabreakFlag.INSTABREAK_FALSE);
166        this.addFlag(InvincibleFlag.INVINCIBLE_FALSE);
167        this.addFlag(ItemDropFlag.ITEM_DROP_TRUE);
168        this.addFlag(KeepInventoryFlag.KEEP_INVENTORY_FALSE);
169        this.addFlag(KelpGrowFlag.KELP_GROW_TRUE);
170        this.addFlag(LeafDecayFlag.LEAF_DECAY_TRUE);
171        this.addFlag(LecternReadBookFlag.LECTERN_READ_BOOK_FALSE);
172        this.addFlag(MiscBreakFlag.MISC_BREAK_FALSE);
173        this.addFlag(MobBreakFlag.MOB_BREAK_FALSE);
174        this.addFlag(MobPlaceFlag.MOB_PLACE_FALSE);
175        this.addFlag(MiscInteractFlag.MISC_INTERACT_FALSE);
176        this.addFlag(SculkSensorInteractFlag.SCULK_SENSOR_INTERACT_FALSE);
177        this.addFlag(MiscPlaceFlag.MISC_PLACE_FALSE);
178        this.addFlag(MycelGrowFlag.MYCEL_GROW_TRUE);
179        this.addFlag(NotifyEnterFlag.NOTIFY_ENTER_FALSE);
180        this.addFlag(NotifyLeaveFlag.NOTIFY_LEAVE_FALSE);
181        this.addFlag(NoWorldeditFlag.NO_WORLDEDIT_FALSE);
182        this.addFlag(PlayerInteractFlag.PLAYER_INTERACT_FALSE);
183        this.addFlag(PreventCreativeCopyFlag.PREVENT_CREATIVE_COPY_FALSE);
184        this.addFlag(PveFlag.PVE_FALSE);
185        this.addFlag(PvpFlag.PVP_FALSE);
186        this.addFlag(RedstoneFlag.REDSTONE_TRUE);
187        this.addFlag(ServerPlotFlag.SERVER_PLOT_FALSE);
188        this.addFlag(SnowFormFlag.SNOW_FORM_FALSE);
189        this.addFlag(SnowMeltFlag.SNOW_MELT_TRUE);
190        this.addFlag(SoilDryFlag.SOIL_DRY_FALSE);
191        this.addFlag(TamedAttackFlag.TAMED_ATTACK_FALSE);
192        this.addFlag(TamedInteractFlag.TAMED_INTERACT_FALSE);
193        this.addFlag(UntrustedVisitFlag.UNTRUSTED_VISIT_FLAG_TRUE);
194        this.addFlag(VehicleBreakFlag.VEHICLE_BREAK_FALSE);
195        this.addFlag(VehiclePlaceFlag.VEHICLE_PLACE_FALSE);
196        this.addFlag(VehicleUseFlag.VEHICLE_USE_FALSE);
197        this.addFlag(VillagerInteractFlag.VILLAGER_INTERACT_FALSE);
198        this.addFlag(VineGrowFlag.VINE_GROW_TRUE);
199        this.addFlag(ProjectilesFlag.PROJECTILES_FALSE);
200
201        // Double flags
202        this.addFlag(PriceFlag.PRICE_NOT_BUYABLE);
203
204        // Enum Flags
205        this.addFlag(DenyTeleportFlag.DENY_TELEPORT_FLAG_NONE);
206        this.addFlag(FlyFlag.FLIGHT_FLAG_DEFAULT);
207        this.addFlag(LiquidFlowFlag.LIQUID_FLOW_DEFAULT);
208        this.addFlag(TitlesFlag.TITLES_NONE);
209        this.addFlag(WeatherFlag.PLOT_WEATHER_FLAG_OFF);
210
211        // Internal flags
212        this.addFlag(new AnalysisFlag(Collections.emptyList()));
213        this.addFlag(new DoneFlag(""));
214
215        // Integer flags
216        this.addFlag(AnimalCapFlag.ANIMAL_CAP_UNLIMITED);
217        this.addFlag(EntityCapFlag.ENTITY_CAP_UNLIMITED);
218        this.addFlag(HostileCapFlag.HOSTILE_CAP_UNLIMITED);
219        this.addFlag(MiscCapFlag.MISC_CAP_UNLIMITED);
220        this.addFlag(MobCapFlag.MOB_CAP_UNLIMITED);
221        this.addFlag(TimeFlag.TIME_DISABLED);
222        this.addFlag(VehicleCapFlag.VEHICLE_CAP_UNLIMITED);
223
224        // Misc
225        this.addFlag(BlockedCmdsFlag.BLOCKED_CMDS_FLAG_NONE);
226        this.addFlag(GamemodeFlag.GAMEMODE_FLAG_DEFAULT);
227        this.addFlag(GuestGamemodeFlag.GUEST_GAMEMODE_FLAG_DEFAULT);
228        this.addFlag(KeepFlag.KEEP_FLAG_FALSE);
229        this.addFlag(MusicFlag.MUSIC_FLAG_NONE);
230
231        // String flags
232        this.addFlag(DescriptionFlag.DESCRIPTION_FLAG_EMPTY);
233        this.addFlag(GreetingFlag.GREETING_FLAG_EMPTY);
234        this.addFlag(FarewellFlag.FAREWELL_FLAG_EMPTY);
235        this.addFlag(PlotTitleFlag.TITLE_FLAG_DEFAULT);
236
237        // Timed flags
238        this.addFlag(FeedFlag.FEED_NOTHING);
239        this.addFlag(HealFlag.HEAL_NOTHING);
240    }
241
242    public static void setup() {
243        Preconditions.checkState(instance == null, "Cannot setup the container twice");
244        instance = new GlobalFlagContainer();
245    }
246
247    public static GlobalFlagContainer getInstance() {
248        return GlobalFlagContainer.instance;
249    }
250
251    @Override
252    public PlotFlag<?, ?> getFlagErased(Class<?> flagClass) {
253        final PlotFlag<?, ?> flag = super.getFlagErased(flagClass);
254        if (flag != null) {
255            return flag;
256        } else {
257            throw new IllegalStateException(String.format("Unrecognized flag '%s'. All flag types"
258                    + " must be present in the global flag container.", flagClass.getSimpleName()));
259        }
260    }
261
262    @NonNull
263    @Override
264    public <V, T extends PlotFlag<V, ?>> T getFlag(Class<? extends T> flagClass) {
265        final PlotFlag<?, ?> flag = super.getFlag(flagClass);
266        if (flag != null) {
267            return castUnsafe(flag);
268        } else {
269            throw new IllegalStateException(String.format("Unrecognized flag '%s'. All flag types"
270                    + " must be present in the global flag container.", flagClass.getSimpleName()));
271        }
272    }
273
274    public Class<?> getFlagClassFromString(final String name) {
275        return stringClassMap.get(name.toLowerCase(Locale.ENGLISH));
276    }
277
278    public PlotFlag<?, ?> getFlagFromString(final String name) {
279        final Class<?> flagClass = this.getFlagClassFromString(name);
280        if (flagClass == null) {
281            return null;
282        }
283        return getFlagErased(flagClass);
284    }
285
286}