-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathDefaultConfig.java
More file actions
414 lines (373 loc) · 16.2 KB
/
DefaultConfig.java
File metadata and controls
414 lines (373 loc) · 16.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
/*
* Copyright (C) 2021 - 2024 spnda
* This file is part of BlockProt <https://github.com/spnda/BlockProt>.
*
* BlockProt is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* BlockProt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with BlockProt. If not, see <http://www.gnu.org/licenses/>.
*/
package de.sean.blockprot.bukkit.config;
import de.sean.blockprot.bukkit.BlockProt;
import de.tr7zw.changeme.nbtapi.utils.MinecraftVersion;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.DoubleChest;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.BlockInventoryHolder;
import org.bukkit.inventory.InventoryHolder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* The default config of the {@link BlockProt} plugin.
*/
public final class DefaultConfig extends BlockProtConfig {
/**
* A list of all lockable tile entities.
*/
private final ArrayList<Material> lockableTileEntities = new ArrayList<>();
/**
* A list of all available shulker boxes, so we
* can save the protection state even after breaking.
*/
private final ArrayList<Material> shulkerBoxes = new ArrayList<>();
/**
* We can only lock normal blocks after 1.16.4. Therefore, in all versions prior this list will
* be empty. Doors are separately listed inside of [lockableDoors].
*/
private final ArrayList<Material> lockableBlocks = new ArrayList<>();
/**
* Doors are separate for LockUtil#applyToDoor and also only work after 1.16.4 Spigot.
*/
private final ArrayList<Material> lockableDoors = new ArrayList<>();
private final ArrayList<InventoryType> lockableInventories = new ArrayList<>(Arrays.asList(
InventoryType.CHEST, InventoryType.FURNACE, InventoryType.SMOKER, InventoryType.BLAST_FURNACE, InventoryType.HOPPER,
InventoryType.BARREL, InventoryType.BREWING, InventoryType.SHULKER_BOX, InventoryType.ANVIL, InventoryType.DISPENSER,
InventoryType.DROPPER, InventoryType.LECTERN
));
/**
* As we differentiate between tile entities and blocks, it's best if we validate the values in the
* config so that {@link #lockableTileEntities} actually only contains tile entities.
*/
private final HashSet<Material> knownGoodTileEntities = new HashSet<>(Arrays.asList(
Material.CHEST, Material.TRAPPED_CHEST, Material.FURNACE, Material.SMOKER, Material.BLAST_FURNACE,
Material.HOPPER, Material.BARREL, Material.BREWING_STAND, Material.DISPENSER, Material.DROPPER,
Material.LECTERN, Material.BEEHIVE, Material.BEE_NEST,
Material.OAK_SIGN, Material.OAK_WALL_SIGN,
Material.SPRUCE_SIGN, Material.SPRUCE_WALL_SIGN,
Material.BIRCH_SIGN, Material.BIRCH_WALL_SIGN,
Material.JUNGLE_SIGN, Material.JUNGLE_WALL_SIGN,
Material.ACACIA_SIGN, Material.ACACIA_WALL_SIGN,
Material.DARK_OAK_SIGN, Material.DARK_OAK_WALL_SIGN,
Material.CRIMSON_SIGN, Material.CRIMSON_WALL_SIGN,
Material.WARPED_SIGN, Material.WARPED_WALL_SIGN
));
private final List<String> excludedWorlds;
private final boolean simpleHopperProtection;
/**
* Create a new default configuration from given {@code config}.
*
* @param config The yaml configuration, should be the {@code config.yml}.
* @since 0.3.3
*/
public DefaultConfig(@NotNull final FileConfiguration config) {
super(config);
this.excludedWorlds = config.getStringList("excluded_worlds");
this.simpleHopperProtection = config.getBoolean("simple_hopper_protection");
this.removeBlockDefaults();
this.loadBlocksFromConfig();
}
private <T extends Enum<?>> void loadBlockListFromConfig(
@NotNull String key, @NotNull final ArrayList<T> list, @NotNull final T[] enumValues, Function<T, Boolean> validateCallback) {
List<?> configList = config.getList(key);
if (configList == null) return;
final var stringList = configList
.stream()
.filter(String.class::isInstance)
.map(String.class::cast)
.distinct() // Remove duplicates
.collect(Collectors.toCollection(ArrayList::new));
final var newEnumValues = this.loadEnumValuesByName(enumValues, stringList);
newEnumValues.removeIf((value) -> {
if (!validateCallback.apply(value)) {
BlockProt.getInstance().getLogger().warning("Caught invalid value passed to " + key + ": " + value.toString());
return true;
}
return false;
});
list.addAll(newEnumValues);
}
/**
* Loads all the different lists from the config.yml file and adds
* them to the various lists in LockUtil.
*
* @since 0.3.3
*/
private void loadBlocksFromConfig() {
// Add some materials which are not valid in some versions
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_19_R1)) {
this.knownGoodTileEntities.addAll(List.of(Material.MANGROVE_SIGN, Material.MANGROVE_WALL_SIGN));
}
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_20_R1)) {
this.knownGoodTileEntities.add(Material.CHISELED_BOOKSHELF);
this.knownGoodTileEntities.addAll(List.of(Material.OAK_WALL_HANGING_SIGN, Material.OAK_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.SPRUCE_WALL_HANGING_SIGN, Material.SPRUCE_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.BIRCH_WALL_HANGING_SIGN, Material.BIRCH_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.JUNGLE_WALL_HANGING_SIGN, Material.JUNGLE_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.ACACIA_WALL_HANGING_SIGN, Material.ACACIA_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.DARK_OAK_WALL_HANGING_SIGN, Material.DARK_OAK_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.CRIMSON_WALL_HANGING_SIGN, Material.CRIMSON_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.WARPED_WALL_HANGING_SIGN, Material.WARPED_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.MANGROVE_HANGING_SIGN, Material.MANGROVE_WALL_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.CHERRY_SIGN, Material.CHERRY_WALL_SIGN, Material.CHERRY_HANGING_SIGN, Material.CHERRY_WALL_HANGING_SIGN));
this.knownGoodTileEntities.addAll(List.of(Material.BAMBOO_SIGN, Material.BAMBOO_WALL_SIGN, Material.BAMBOO_HANGING_SIGN, Material.BAMBOO_WALL_HANGING_SIGN));
}
loadBlockListFromConfig("lockable_tile_entities", this.lockableTileEntities, Material.values(),
knownGoodTileEntities::contains);
loadBlockListFromConfig("lockable_shulker_boxes", this.shulkerBoxes, Material.values(),
material -> material.toString().contains("SHULKER_BOX"));
if (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_16_R3)) {
loadBlockListFromConfig("lockable_blocks", this.lockableBlocks, Material.values(),
material -> !knownGoodTileEntities.contains(material));
loadBlockListFromConfig("lockable_doors", this.lockableDoors, Material.values(),
material -> material.toString().contains("DOOR"));
lockableBlocks.addAll(lockableDoors);
}
}
/**
* Get the filename of the language file we use.
* This file should be located in /plugins/BlockProt/.
*
* @return The name of the language file.
* @since 0.3.3
*/
@Nullable
public String getLanguageFile() {
return config.getString("language_file");
}
/**
* Whether we should replace the translation files on each startup
* and therefore discard any potential changes made to the files
* by the server admin.
*
* @return True if translation files should be replaced.
*/
public boolean shouldReplaceTranslations() {
if (!this.config.contains("replace_translations")) return true;
return this.config.getBoolean("replace_translations");
}
/**
* Whether or not to we should notify a OP player of any updates
* when they join the server.
*
* @return True if a op should be notified of updates.
* @since 0.3.3
*/
public boolean shouldNotifyOpOfUpdates() {
if (!this.config.contains("notify_op_of_updates")) return false;
return this.config.getBoolean("notify_op_of_updates");
}
/**
* Checks the config if the "redstone_disallowed_by_default" key is
* set to true. If it was not found, it defaults to false.
*
* @return True if redstone should be automatically disabled when a
* block is placed.
* @since 0.3.3
*/
public boolean disallowRedstoneOnPlace() {
if (this.config.contains("redstone_disallowed_by_default")) {
return config.getBoolean("redstone_disallowed_by_default");
} else {
return true;
}
}
/**
* Checks if given {@code world} should be excluded from any
* block protection functionality.
*
* @param world The world to check for.
* @return If true, we shall not allow players to own and protect
* any blocks in given {@code world}.
* @since 0.4.4
*/
public boolean isWorldExcluded(World world) {
return listContainsIgnoreCase(excludedWorlds, world.getName());
}
/**
* Checks if the world of the block held by {@code inventory}
* is excluded from any block protection functionality.
*
* @param holder The inventory we want to use. If it is not a known
* exception, we try to cast it to {@link BlockInventoryHolder}.
* @return True, if the world is excluded or the {@code holder} was
* unable to be cast to {@link BlockInventoryHolder} and we do not
* know how to extract the World information from it.
* This is done to prevent this plugin to, for example, interact
* with other plugins' inventories.
* @since 0.4.5
*/
public boolean isWorldExcluded(InventoryHolder holder) {
try {
if (holder instanceof DoubleChest) {
@Nullable World world = ((DoubleChest) holder).getWorld();
if (world == null) return true;
return listContainsIgnoreCase(excludedWorlds, world.getName());
}
return isWorldExcluded(((BlockInventoryHolder) holder).getBlock().getWorld());
} catch (ClassCastException e) {
return true;
}
}
/**
* Whether the lock on place setting should be enabled by default.
*
* @return Boolean for the default value of lock on place.
* @since 0.4.11
*/
public boolean lockOnPlaceByDefault() {
if (!this.config.contains("lock_on_place_by_default")) return true;
return this.config.getBoolean("lock_on_place_by_default");
}
/**
* Whether the public should be a friend by default.
*
* @return Boolean for the default value of public is friend.
* @since 1.1.15
*/
public boolean publicIsFriendByDefault() {
if (!this.config.contains("public_is_friend_by_default")) return false;
return this.config.getBoolean("public_is_friend_by_default");
}
/**
*
* @since 1.0.0
*/
@Nullable
public String getTranslationFallbackString() {
if (!this.config.contains("fallback_string")) return "";
return this.config.getString("fallback_string");
}
/**
* Gets the maximum amount of blocks a player is allowed to
* lock globally.
* @return The value or if no limit is set, null.
* @since 1.0.3
*/
@Nullable
public Integer getMaxLockedBlockCount() {
if (!this.config.contains("player_max_locked_block_count"))
return null;
int val = this.config.getInt("player_max_locked_block_count");
return val > 0 ? val : null;
}
/**
* JavaPlugin#reloadConfig sets the default values to the config inside
* the JAR, which are never edited by the player. We don't want this
* for the lists.
*
* @since 1.0.0
*/
public void removeBlockDefaults() {
Configuration defaults = this.config.getDefaults();
if (defaults != null) {
defaults.set("lockable_tile_entities", null);
defaults.set("lockable_shulker_boxes", null);
defaults.set("lockable_blocks", null);
defaults.set("lockable_doors", null);
this.config.setDefaults(defaults);
}
}
public long getLockHintCooldown() {
if (!config.contains("lock_hint_cooldown_in_seconds")) {
return 10;
}
return config.getLong("lock_hint_cooldown_in_seconds");
}
/**
* Gets the minimum percentage friend names have to match by the levenshtein distance.
* @since 1.1.6
*/
public double getFriendSearchSimilarityPercentage() {
if (!config.contains("friend_search_similarity")) {
return 0.5;
}
return config.getDouble("friend_search_similarity");
}
/**
* Returns if the friend functionality is fully disabled. This will
* no longer allow players to give other players access to their blocks, and
* current settings are ignored until re-activated.
* @since 1.1.16
*/
public boolean isFriendFunctionalityDisabled() {
if (!config.contains("disable_friend_functionality")) {
return false;
}
return config.getBoolean("disable_friend_functionality");
}
/**
* <p> Whether the given {@code type} is either a lockable block or a lockable tile entity.
*
* <p> Keep in mind, that only tile entities are lockable through this plugin after Spigot 1.16_R3.
*
* <p> To add to this, this merely checks the material from the config. This means that a server author
* might accidentally add a material which is not a block or tile entity.
*
* @param type The type to check for.
* @return True, if {@code type} is lockable.
* @since 0.3.3
*/
public boolean isLockable(Material type) {
return isLockableBlock(type) || isLockableTileEntity(type);
}
/**
* Whether the given {@code type} is a lockable block. Be aware, this only
* works after Spigot 1.16_R3 and the config might have some invalid values.
*
* @param type The material to check for.
* @return True, if {@code type} is a lockable block.
* @see #isLockable(Material)
* @since 0.3.3
*/
public boolean isLockableBlock(Material type) {
return lockableBlocks.contains(type);
}
/**
* Whether the given {@code type} is a lockable tile entity. Be aware,
* the config might have some invalid values.
*
* @param type The material to check for.
* @return True, if {@code type} is a lockable tile entity.
* @see #isLockable(Material)
* @since 0.3.3
*/
public boolean isLockableTileEntity(Material type) {
return lockableTileEntities.contains(type) || shulkerBoxes.contains(type);
}
public boolean isLockableDoor(Material type) {
return lockableDoors.contains(type);
}
public boolean isLockableShulkerBox(Material type) {
return shulkerBoxes.contains(type);
}
public boolean isLockableInventory(InventoryType type) {
return lockableInventories.contains(type);
}
public boolean isSimpleHopperProtection() {
return simpleHopperProtection;
}
}