001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package net.tridentsdk.world.settings;
018
019import net.tridentsdk.docs.AccessNoDoc;
020
021import javax.annotation.concurrent.Immutable;
022
023/**
024 * Gamerules are applied on a per-world basis and are options for more advanced/low-level properties of the world
025 * such as command blocks, drops, and inventory modifiers
026 *
027 * <p>The default value for all game rules is {@code true} except for {@link #REDUCED_DEBUG_INFO} and
028 * {@link #KEEP_INVENTORY}, which are both {@code false} by default</p>
029 *
030 * @author The TridentSDK Team
031 * @since 0.4-alpha
032 */
033public enum GameRule {
034    /**
035     * Whether command blocks should notify admins when they perform commands
036     */
037    COMMAND_BLOCK_OUTPUT("commandBlockOutput", Value.of(true)),
038    /**
039     * Whether time progresses
040     */
041    DO_DAYLIGHT_CYCLE("doDaylightCycle", Value.of(true)),
042    /**
043     * Whether entities that are not mobs should have drops
044     */
045    DO_ENTITY_DROPS("doEntityDrops", Value.of(true)),
046    /**
047     * Whether fire should spread and naturally extinguish
048     */
049    DO_FIRE_TICK("doFireTick", Value.of(true)),
050    /**
051     * Whether mobs should drop items
052     */
053    DO_MOB_LOOT("doMobLoot", Value.of(true)),
054    /**
055     * Whether mobs should naturally spawn
056     */
057    DO_MOB_SPAWNING("doMobSpawning", Value.of(true)),
058    /**
059     * Whether blocks should have drops
060     */
061    DO_TILE_DROPS("doTileDrops", Value.of(true)),
062    /**
063     * Whether the player should keep items in their inventory after death
064     */
065    KEEP_INVENTORY("keepInventory", Value.of(false)),
066    /**
067     * Whether to log admin commands to server log
068     */
069    LOG_ADMIN_COMMANDS("logAdminCommands", Value.of(true)),
070    /**
071     * Whether creepers, zombies, endermen, ghasts, withers, ender dragons, rabbits, sheep,
072     * and villagers should be able to change blocks and whether villagers, zombies, skeletons,
073     * and zombie pigmen can pick up items
074     */
075    MOB_GRIEFING("mobGriefing", Value.of(true)),
076    /**
077     * Whether the player can regenerate health naturally if their hunger is full enough (doesn't affect external
078     * healing, such as golden apples, the Regeneration effect, etc.)
079     */
080    NATURAL_REGENERATION("naturalRegeneration", Value.of(true)),
081    /**
082     * How often a random block tick occurs (such as plant growth, leaf decay, etc.) per chunk section per game tick.
083     *
084     * <p>Default value: {@code 3}</p>
085     *
086     * <p>0 will disable random ticks, higher numbers will increase random ticks</p>
087     */
088    RANDOM_TICK_SPEED("randomTickSpeed", Value.of(3)),
089    /**
090     * Whether the debug screen shows all or reduced information
091     */
092    REDUCED_DEBUG_INFO("reducedDebugInfo", Value.of(false)),
093    /**
094     * Whether the feedback from commands executed by a player should show up in chat. Also affects the default behavior
095     * of whether command blocks store their output text
096     */
097    SEND_COMMAND_FEEDBACK("sendCommandFeedback", Value.of(true)),
098    /**
099     * Whether a message appears in chat when a player dies
100     */
101    SHOW_DEATH_MESSAGES("showDeathMessages", Value.of(true)),
102    /**
103     * Whether players in spectator mode can generate chunks
104     */
105    SPECTATORS_GENERATE_CHUNKS("spectatorsGenerateChunks", Value.of(true));
106
107    private final Value defValue;
108    private final String raw;
109    GameRule(String raw, Value defValue) {
110        this.raw = raw;
111        this.defValue = defValue;
112    }
113
114    /**
115     * Obtains the default value of the game rule
116     *
117     * @return the default value
118     */
119    public Value defaultValue() {
120        return defValue;
121    }
122
123    /**
124     * Checks if the argument matches the default value
125     *
126     * @param b the boolean to check
127     * @return {@code true} if it matches, {@code false} otherwise
128     */
129    public boolean boolEqualToValue(boolean b) {
130        if (defValue.isInteger()) {
131            throw new IllegalStateException("Value is an integer");
132        }
133
134        return defValue.asBoolean() == b;
135    }
136
137    /**
138     * Checks if the argument matches the default value
139     *
140     * @param i the integer to check
141     * @return {@code true} if it matches, {@code false} otherwise
142     */
143    public boolean intEqualToValue(int i) {
144        if (defValue.isBoolean()) {
145            throw new IllegalStateException("Value is a boolean");
146        }
147
148        return defValue.asInt() == i;
149    }
150
151    @Override
152    public String toString() {
153        return raw;
154    }
155
156    /**
157     * Represents a value which can be possessed by the game rule
158     *
159     * @author The TridentSDK Team
160     */
161    @Immutable
162    public static class Value {
163        private final ValueType type;
164        private final boolean bool;
165        private final int integer;
166
167        private Value(boolean bool) {
168            this.type = ValueType.BOOLEAN;
169            this.bool = bool;
170            this.integer = 0;
171        }
172
173        private Value(int integer) {
174            this.type = ValueType.INTEGER;
175            this.integer = integer;
176            this.bool = false;
177        }
178
179        /**
180         * Creates a new game rule value that takes an integer parameter
181         *
182         * @param integer the game rule parameter
183         * @return the wrapped value
184         */
185        public static Value of(int integer) {
186            return new Value(integer);
187        }
188
189        /**
190         * Creates a new game rule value that takes a boolean parameter
191         *
192         * @param bool the game rule parameter
193         * @return the wrapped value
194         */
195        public static Value of(boolean bool) {
196            return new Value(bool);
197        }
198
199        /**
200         * Checks to see whether this value is an integer
201         *
202         * @return {@code true} if it is an integer, {@code false} if it is a boolean
203         */
204        public boolean isInteger() {
205            return type == ValueType.INTEGER;
206        }
207
208        /**
209         * Checks to see whether this value is a boolean
210         *
211         * @return {@code true} if it is a boolean, {@code false} if it is an integer
212         */
213        public boolean isBoolean() {
214            return type == ValueType.BOOLEAN;
215        }
216
217        /**
218         * Obtains the boolean value
219         *
220         * @return the boolean value
221         */
222        public boolean asBoolean() {
223            if (type != ValueType.BOOLEAN) {
224                throw new IllegalStateException("Value type not a boolean");
225            }
226            return bool;
227        }
228
229        /**
230         * Obtains the integer value
231         *
232         * @return the integer value
233         */
234        public int asInt() {
235            if (type != ValueType.INTEGER) {
236                throw new IllegalStateException("Value type not an integer");
237            }
238            return integer;
239        }
240    }
241
242    @AccessNoDoc
243    private enum ValueType {
244        INTEGER, BOOLEAN
245    }
246}