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.util; 020 021import com.plotsquared.core.PlotSquared; 022import com.plotsquared.core.configuration.ConfigurationSection; 023import com.plotsquared.core.configuration.caption.TranslatableCaption; 024import com.plotsquared.core.player.ConsolePlayer; 025import com.plotsquared.core.plot.BlockBucket; 026import com.sk89q.worldedit.world.block.BlockState; 027import net.kyori.adventure.text.Component; 028import net.kyori.adventure.text.minimessage.tag.Tag; 029import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 030import org.apache.logging.log4j.LogManager; 031import org.apache.logging.log4j.Logger; 032import org.checkerframework.checker.nullness.qual.NonNull; 033 034import java.util.Collection; 035import java.util.HashMap; 036import java.util.List; 037import java.util.Map; 038 039/** 040 * Converts legacy configurations into the new (BlockBucket) format 041 */ 042@SuppressWarnings("unused") 043public final class LegacyConverter { 044 045 public static final String CONFIGURATION_VERSION = "post_flattening"; 046 private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + LegacyConverter.class.getSimpleName()); 047 private static final HashMap<String, ConfigurationType> TYPE_MAP = new HashMap<>(); 048 049 static { 050 TYPE_MAP.put("plot.filling", ConfigurationType.BLOCK_LIST); 051 TYPE_MAP.put("plot.floor", ConfigurationType.BLOCK_LIST); 052 TYPE_MAP.put("wall.filling", ConfigurationType.BLOCK); 053 TYPE_MAP.put("wall.block_claimed", ConfigurationType.BLOCK); 054 TYPE_MAP.put("wall.block", ConfigurationType.BLOCK); 055 TYPE_MAP.put("road.block", ConfigurationType.BLOCK); 056 } 057 058 private final ConfigurationSection configuration; 059 060 public LegacyConverter(final @NonNull ConfigurationSection configuration) { 061 this.configuration = configuration; 062 } 063 064 private BlockBucket blockToBucket(final @NonNull String block) { 065 final BlockState plotBlock = PlotSquared.platform().worldUtil().getClosestBlock(block).best; 066 return BlockBucket.withSingle(plotBlock); 067 } 068 069 private void setString( 070 final @NonNull ConfigurationSection section, 071 final @NonNull String string, final @NonNull BlockBucket blocks 072 ) { 073 if (!section.contains(string)) { 074 throw new IllegalArgumentException(String.format("No such key: %s", string)); 075 } 076 section.set(string, blocks.toString()); 077 } 078 079 private BlockBucket blockListToBucket(final @NonNull BlockState[] blocks) { 080 final Map<BlockState, Integer> counts = new HashMap<>(); 081 for (final BlockState block : blocks) { 082 counts.putIfAbsent(block, 0); 083 counts.put(block, counts.get(block) + 1); 084 } 085 boolean includeRatios = false; 086 for (final Integer integer : counts.values()) { 087 if (integer > 1) { 088 includeRatios = true; 089 break; 090 } 091 } 092 final BlockBucket bucket = new BlockBucket(); 093 if (includeRatios) { 094 for (final Map.Entry<BlockState, Integer> count : counts.entrySet()) { 095 bucket.addBlock(count.getKey(), count.getValue()); 096 } 097 } else { 098 counts.keySet().forEach(bucket::addBlock); 099 } 100 return bucket; 101 } 102 103 private BlockState[] splitBlockList(final @NonNull List<String> list) { 104 return list.stream().map(s -> PlotSquared.platform().worldUtil().getClosestBlock(s).best) 105 .toArray(BlockState[]::new); 106 } 107 108 private void convertBlock( 109 final @NonNull ConfigurationSection section, 110 final @NonNull String key, 111 final @NonNull String block 112 ) { 113 final BlockBucket bucket = this.blockToBucket(block); 114 this.setString(section, key, bucket); 115 ConsolePlayer.getConsole().sendMessage( 116 TranslatableCaption.of("legacyconfig.legacy_config_replaced"), 117 TagResolver.builder() 118 .tag("value1", Tag.inserting(Component.text(block))) 119 .tag("value2", Tag.inserting(Component.text(bucket.toString()))) 120 .build() 121 ); 122 } 123 124 private void convertBlockList( 125 final @NonNull ConfigurationSection section, 126 final @NonNull String key, 127 final @NonNull List<String> blockList 128 ) { 129 final BlockState[] blocks = this.splitBlockList(blockList); 130 final BlockBucket bucket = this.blockListToBucket(blocks); 131 this.setString(section, key, bucket); 132 ConsolePlayer.getConsole() 133 .sendMessage( 134 TranslatableCaption.of("legacyconfig.legacy_config_replaced"), 135 TagResolver.builder() 136 .tag("value1", Tag.inserting(Component.text(plotBlockArrayString(blocks)))) 137 .tag("value2", Tag.inserting(Component.text(bucket.toString()))) 138 .build() 139 ); 140 } 141 142 private String plotBlockArrayString(final @NonNull BlockState[] blocks) { 143 final StringBuilder builder = new StringBuilder(); 144 for (int i = 0; i < blocks.length; i++) { 145 builder.append(blocks[i].toString()); 146 if ((i + 1) < blocks.length) { 147 builder.append(","); 148 } 149 } 150 return builder.toString(); 151 } 152 153 public void convert() { 154 // Section is the "worlds" section 155 final Collection<String> worlds = this.configuration.getKeys(false); 156 for (final String world : worlds) { 157 final ConfigurationSection worldSection = configuration.getConfigurationSection(world); 158 for (final Map.Entry<String, ConfigurationType> entry : TYPE_MAP.entrySet()) { 159 if (worldSection.contains(entry.getKey())) { 160 if (entry.getValue() == ConfigurationType.BLOCK) { 161 this.convertBlock(worldSection, entry.getKey(), 162 worldSection.getString(entry.getKey()) 163 ); 164 } else { 165 this.convertBlockList(worldSection, entry.getKey(), 166 worldSection.getStringList(entry.getKey()) 167 ); 168 } 169 } 170 } 171 } 172 } 173 174 private enum ConfigurationType { 175 BLOCK, 176 BLOCK_LIST 177 } 178 179}