Update some patches from Leaves
This commit is contained in:
@@ -3,6 +3,7 @@ package fun.bm.lophine.config.modules.misc;
|
||||
import me.earthme.luminol.config.EnumConfigCategory;
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.config.flags.TransformedConfig;
|
||||
|
||||
public class OldFeatureConfig implements IConfigModule {
|
||||
@ConfigInfo(baseName = "spawn_invulnerable_time")
|
||||
@@ -14,6 +15,10 @@ public class OldFeatureConfig implements IConfigModule {
|
||||
@ConfigInfo(baseName = "old_explosion_damage_calculator")
|
||||
public static boolean oldExplosionDamageCalculator = false;
|
||||
|
||||
@TransformedConfig(name = "give_bad_omen_when_kill_raid_captain", category = {"misc", "revert_raid_changes"}, transformComments = false)
|
||||
@ConfigInfo(baseName = "old_raid_behavior")
|
||||
public static boolean oldRaidBehavior = false;
|
||||
|
||||
@Override
|
||||
public EnumConfigCategory getCategory() {
|
||||
return EnumConfigCategory.MISC;
|
||||
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package fun.bm.lophine.config.modules.misc;
|
||||
|
||||
import me.earthme.luminol.config.EnumConfigCategory;
|
||||
import me.earthme.luminol.config.IConfigModule;
|
||||
import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
|
||||
public class RaidChangesConfig implements IConfigModule {
|
||||
@ConfigInfo(baseName = "allow_skip_cooldown", comments =
|
||||
"""
|
||||
Allow players with bad omen to skip a
|
||||
30-second cooldown and trigger attacks directly""")
|
||||
public static boolean trigger = false;
|
||||
|
||||
@ConfigInfo(baseName = "give_bad_omen_when_kill_raid_captain", comments =
|
||||
"""
|
||||
Enable players to obtain a bad omen
|
||||
effect when killing the raid captain""")
|
||||
public static boolean effect = false;
|
||||
|
||||
@ConfigInfo(baseName = "bad_omen_infinite", comments =
|
||||
"""
|
||||
Enable bad omen effect infinite time
|
||||
--- this config is not old version's function""")
|
||||
public static boolean infinite = false;
|
||||
|
||||
@ConfigInfo(baseName = "skip_height_check", comments =
|
||||
"""
|
||||
Disable y <= 96 check.
|
||||
If you enabled use_old_position_find, this config
|
||||
will useless and always behavior of enabled""")
|
||||
public static boolean heightCheck = false;
|
||||
|
||||
@ConfigInfo(baseName = "skip_self_raid_check", comments =
|
||||
"""
|
||||
Disable raid self check
|
||||
--- this config is not old version's function""")
|
||||
public static boolean selfCheck = false;
|
||||
|
||||
@ConfigInfo(baseName = "use_old_position_find", comments =
|
||||
"""
|
||||
Revert Old raid's find spawn position logic
|
||||
--- This revert MC-274911""")
|
||||
public static boolean posRevert = false;
|
||||
|
||||
@Override
|
||||
public EnumConfigCategory getCategory() {
|
||||
return EnumConfigCategory.MISC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBaseName() {
|
||||
return "revert_raid_changes";
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,6 @@ public class RedStoneConfig implements IConfigModule {
|
||||
Allows you to use the Shears to right-click to rotate the block.""")
|
||||
public static boolean shears = false;
|
||||
|
||||
@ConfigInfo(baseName = "vanilla_hopper")
|
||||
public static boolean vanillaHopper = false;
|
||||
|
||||
@Override
|
||||
public EnumConfigCategory getCategory() {
|
||||
return EnumConfigCategory.MISC;
|
||||
|
||||
@@ -6,6 +6,12 @@ import me.earthme.luminol.config.flags.ConfigInfo;
|
||||
import me.earthme.luminol.config.flags.TransformedConfig;
|
||||
|
||||
public class RemovedConfig implements IConfigModule {
|
||||
@TransformedConfig(name = "allow_skip_cooldown", category = {"misc", "revert_raid_changes"}, transform = false)
|
||||
@TransformedConfig(name = "bad_omen_infinite", category = {"misc", "revert_raid_changes"}, transform = false)
|
||||
@TransformedConfig(name = "skip_height_check", category = {"misc", "revert_raid_changes"}, transform = false)
|
||||
@TransformedConfig(name = "skip_self_raid_check", category = {"misc", "revert_raid_changes"}, transform = false)
|
||||
@TransformedConfig(name = "use_old_position_find", category = {"misc", "revert_raid_changes"}, transform = false)
|
||||
@TransformedConfig(name = "vanilla_hopper", category = {"misc", "redstone"}, transform = false)
|
||||
@TransformedConfig(name = "old_replaceable_by_mushrooms", category = {"misc", "old-feature"}, transform = false)
|
||||
@TransformedConfig(name = "old_nether_portal_collision", category = {"misc", "old-feature"}, transform = false)
|
||||
@TransformedConfig(name = "better_shulker_box", category = {"misc", "container_expansion"}, transform = false)
|
||||
|
||||
@@ -4,7 +4,10 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import fun.bm.lophine.config.modules.optimizations.LanguageConfig;
|
||||
import me.earthme.luminol.config.ConfigManager;
|
||||
import me.earthme.luminol.config.ConfigsInstance;
|
||||
import net.minecraft.DetectedVersion;
|
||||
import net.minecraft.locale.DeprecatedTranslationsInfo;
|
||||
import net.minecraft.locale.Language;
|
||||
@@ -12,8 +15,8 @@ import net.minecraft.network.chat.FormattedText;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
import net.minecraft.util.StringDecomposer;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -23,13 +26,13 @@ import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.file.*;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/*
|
||||
* authored by: Helvetica Volubi <suisuroru@blue-millennium.fun>
|
||||
@@ -37,30 +40,62 @@ import java.util.logging.Logger;
|
||||
* Some of diff form Leaves
|
||||
*/
|
||||
public class ServerI18nUtil {
|
||||
|
||||
private static final Logger logger = Logger.getLogger("LangLoader");
|
||||
private static final Logger logger = LogUtils.getClassLogger();
|
||||
private static final String VERSION = DetectedVersion.BUILT_IN.name();
|
||||
private static final String BASE_PATH = "cache/lophine/" + VERSION + "/";
|
||||
private static final String defaultLophineLangPath = "/assets/lophine/lang/en_us.json";
|
||||
private static final String manifestUrl = "https://launchermeta.mojang.com/mc/game/version_manifest.json";
|
||||
private static final String resourceBaseUrl = "https://resources.download.minecraft.net/";
|
||||
|
||||
// pre-load
|
||||
private static CompletableFuture<Void> preloadTask;
|
||||
// paths
|
||||
private static String langPath;
|
||||
private static String assetsPath;
|
||||
private static String versionPath;
|
||||
private static String manifestPath;
|
||||
private static String langJsonPath;
|
||||
private static String lophineLangPath;
|
||||
|
||||
public static void init() {
|
||||
if (Objects.equals(LanguageConfig.lang, "en_us")) {
|
||||
return;
|
||||
}
|
||||
langPath = BASE_PATH + "lang/" + LanguageConfig.lang + ".json";
|
||||
langJsonPath = "minecraft/lang/" + LanguageConfig.lang + ".json";
|
||||
lophineLangPath = "/assets/Lophine/lang/" + LanguageConfig.lang + ".json";
|
||||
logger.info("Starting load language: {}", LanguageConfig.lang);
|
||||
preloadTask.thenAcceptAsync(v -> loadI18n(LanguageConfig.lang, 2));
|
||||
}
|
||||
|
||||
public static void preInit() {
|
||||
assetsPath = BASE_PATH + "assets.json";
|
||||
versionPath = BASE_PATH + VERSION + ".json";
|
||||
manifestPath = BASE_PATH + "manifest.json";
|
||||
langJsonPath = "minecraft/lang/" + LanguageConfig.lang + ".json";
|
||||
logger.info("Starting load language: " + LanguageConfig.lang);
|
||||
CompletableFuture.runAsync(() -> loadI18n(LanguageConfig.lang, 2));
|
||||
preloadTask = CompletableFuture.runAsync(() -> preLoadI18n(2));
|
||||
}
|
||||
|
||||
private static void preLoadI18n(int retryTime) {
|
||||
try {
|
||||
if (!Files.exists(Path.of(assetsPath))) {
|
||||
downloadAssets(true);
|
||||
}
|
||||
} catch (UnsupportedLanguageException e) {
|
||||
logger.warn("Unsupported language: {}", LanguageConfig.lang);
|
||||
// Fallback to English
|
||||
final ConfigsInstance configsInstance = ConfigManager.configfiles.get("lophine");
|
||||
configsInstance.setConfig(new String[]{"optimizations", "lang"}, "en_us");
|
||||
configsInstance.reloadAsync();
|
||||
} catch (Exception e) {
|
||||
if (e instanceof MalformedJsonException malformedJson) {
|
||||
malformedJson.clean();
|
||||
}
|
||||
logger.warn("Failed to download language list file: ", e);
|
||||
if (retryTime > 0) {
|
||||
preLoadI18n(retryTime - 1);
|
||||
} else {
|
||||
logger.error("Failed to download language list file for many times, skip pre-load language.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadI18n(String lang, int retryTime) {
|
||||
@@ -69,15 +104,16 @@ public class ServerI18nUtil {
|
||||
downloadLang(true);
|
||||
}
|
||||
Language.inject(createLangInstance());
|
||||
logger.info("Successfully loaded language: " + lang);
|
||||
logger.info("Successfully loaded language: {}", lang);
|
||||
} catch (Exception e) {
|
||||
logger.warning("Failed to load language file for " + lang + "\n" + e);
|
||||
if (e instanceof MalformedJsonException malformedJson) {
|
||||
malformedJson.clean();
|
||||
}
|
||||
logger.warn("Failed to load language file for {}", lang, e);
|
||||
if (retryTime > 0) {
|
||||
cleanCache();
|
||||
loadI18n(lang, retryTime - 1);
|
||||
} else {
|
||||
logger.severe("Failed to load for many times, use default lang \"en_us\" instead");
|
||||
cleanCache();
|
||||
logger.error("Failed to load for many times, use default lang \"en_us\" instead");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,6 +130,10 @@ public class ServerI18nUtil {
|
||||
|
||||
JsonObject langEntry = json.getAsJsonObject("objects").getAsJsonObject(langJsonPath);
|
||||
|
||||
if (langEntry == null) {
|
||||
throw new UnsupportedLanguageException();
|
||||
}
|
||||
|
||||
String hash = langEntry.get("hash").getAsString();
|
||||
if (hash == null || hash.length() < 2) {
|
||||
throw new IllegalArgumentException("Invalid hash value");
|
||||
@@ -145,37 +185,31 @@ public class ServerI18nUtil {
|
||||
fetchAndSave(versionUrl, versionPath);
|
||||
}
|
||||
|
||||
private static String createHttpResponse(String path) throws IOException, InterruptedException {
|
||||
private static byte[] fetch(String urlString) throws IOException, InterruptedException {
|
||||
try {
|
||||
HttpResponse<String> response;
|
||||
try (HttpClient httpClient = HttpClient.newHttpClient()) {
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(path))
|
||||
.uri(URI.create(urlString))
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.build();
|
||||
|
||||
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
}
|
||||
|
||||
int responseCode = response.statusCode();
|
||||
if (responseCode != 200) {
|
||||
logger.info("Unexpected response code: " + responseCode);
|
||||
logger.info("Response body: " + response.body());
|
||||
logger.info("Unexpected response code: {}", responseCode);
|
||||
logger.info("Response body: {}", response.body());
|
||||
throw new UnsupportedEncodingException("Unexpected response code");
|
||||
} else {
|
||||
return response.body();
|
||||
return response.body().getBytes();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warning("Error in getting info: " + e.getMessage());
|
||||
logger.warn("Error in getting info!");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] fetch(String urlString) throws IOException, InterruptedException {
|
||||
String ret = createHttpResponse(urlString);
|
||||
return ret.getBytes();
|
||||
}
|
||||
|
||||
private static void fetchAndSave(String url, String savePath) throws IOException, InterruptedException {
|
||||
byte[] data = fetch(url);
|
||||
Path outputPath = Path.of(savePath);
|
||||
@@ -183,23 +217,15 @@ public class ServerI18nUtil {
|
||||
Files.write(outputPath, data, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
|
||||
}
|
||||
|
||||
private static void cleanCache() {
|
||||
try {
|
||||
FileUtils.deleteDirectory(Path.of(BASE_PATH).toFile());
|
||||
} catch (IOException e) {
|
||||
logger.severe("Cache cleanup failed: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonObject loadJson(String path) {
|
||||
try {
|
||||
byte[] data = Files.readAllBytes(Paths.get(path));
|
||||
return JsonParser.parseString(new String(data)).getAsJsonObject();
|
||||
} catch (JsonSyntaxException e) {
|
||||
logger.warning("Corrupt json file: " + e);
|
||||
throw e;
|
||||
logger.warn("Corrupt json file!");
|
||||
throw new MalformedJsonException(e, path);
|
||||
} catch (Exception e) {
|
||||
logger.warning("Failed to load local JSON: " + e);
|
||||
logger.warn("Failed to load local JSON!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -208,6 +234,7 @@ public class ServerI18nUtil {
|
||||
DeprecatedTranslationsInfo deprecatedTranslationsInfo = DeprecatedTranslationsInfo.loadFromDefaultResource();
|
||||
Map<String, String> map = new HashMap<>();
|
||||
parseTranslations(map::put);
|
||||
loadLophineI18n(map::put);
|
||||
deprecatedTranslationsInfo.applyToMap(map);
|
||||
final Map<String, String> map1 = Map.copyOf(map);
|
||||
return new Language() {
|
||||
@@ -237,16 +264,52 @@ public class ServerI18nUtil {
|
||||
};
|
||||
}
|
||||
|
||||
private static void loadLophineI18n(BiConsumer<String, String> bi) {
|
||||
if (Language.class.getResource(lophineLangPath) != null) {
|
||||
Language.parseTranslations(bi, lophineLangPath);
|
||||
} else {
|
||||
loadLophineI18nDefault(bi);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadLophineI18nDefault(BiConsumer<String, String> bi) {
|
||||
if (Language.class.getResource(defaultLophineLangPath) != null) {
|
||||
Language.parseTranslations(bi, defaultLophineLangPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseTranslations(BiConsumer<String, String> output) throws IOException {
|
||||
Path filePath = Path.of(langPath);
|
||||
try (InputStream fileStream = Files.newInputStream(filePath)) {
|
||||
Language.loadFromJson(fileStream, output);
|
||||
} catch (NoSuchFileException noSuchFileException) {
|
||||
logger.warning("Couldn't find language file: " + langPath);
|
||||
throw noSuchFileException;
|
||||
} catch (NoSuchFileException e) {
|
||||
logger.warn("Couldn't find language file: {}", langPath);
|
||||
throw e;
|
||||
} catch (JsonSyntaxException e) {
|
||||
throw new MalformedJsonException(e, langPath);
|
||||
} catch (Exception e) {
|
||||
logger.warning("Failed to load language from filesystem " + filePath + "\n" + e);
|
||||
logger.warn("Failed to load language from filesystem {}", filePath);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static class UnsupportedLanguageException extends Exception {
|
||||
}
|
||||
|
||||
private static class MalformedJsonException extends RuntimeException {
|
||||
private final Path path;
|
||||
|
||||
protected MalformedJsonException(Throwable root, String path) {
|
||||
super(root);
|
||||
this.path = Path.of(path);
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
try {
|
||||
Files.delete(path);
|
||||
} catch (IOException e) {
|
||||
logger.info("Failed to delete malformed JSON file: {}", path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*
|
||||
* Leaves is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Leaves 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.util;
|
||||
|
||||
import fun.bm.lophine.config.modules.misc.RedStoneConfig;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.piston.PistonBaseBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraft.world.level.block.state.properties.RailShape;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ShearsWrenchUtil {
|
||||
|
||||
public static InteractionResult tryApplyRotate(UseOnContext context, BlockState blockState) {
|
||||
Level level = context.getLevel();
|
||||
BlockPos clickedPos = context.getClickedPos();
|
||||
Block block = blockState.getBlock();
|
||||
if (!RedStoneConfig.shears || !(block instanceof ObserverBlock || block instanceof DispenserBlock || block instanceof PistonBaseBlock || block instanceof HopperBlock || block instanceof RepeaterBlock || block instanceof ComparatorBlock || block instanceof CrafterBlock || block instanceof LeverBlock || block instanceof CocoaBlock || block instanceof TrapDoorBlock || block instanceof FenceGateBlock || block instanceof LightningRodBlock || block instanceof CalibratedSculkSensorBlock || block instanceof BaseRailBlock)) {
|
||||
return null;
|
||||
}
|
||||
StateDefinition<Block, BlockState> blockstatelist = block.getStateDefinition();
|
||||
Property<?> iblockstate;
|
||||
if (block instanceof CrafterBlock) {
|
||||
iblockstate = blockstatelist.getProperty("orientation");
|
||||
} else if (block instanceof BaseRailBlock) {
|
||||
iblockstate = blockstatelist.getProperty("shape");
|
||||
} else {
|
||||
iblockstate = blockstatelist.getProperty("facing");
|
||||
}
|
||||
Player player = context.getPlayer();
|
||||
|
||||
if (iblockstate == null || player == null) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
if (block instanceof BaseRailBlock) {
|
||||
if (block instanceof RailBlock) {
|
||||
if (blockState.getValue(RailBlock.SHAPE).isSlope()) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
} else {
|
||||
if (getNameHelper(blockState, PoweredRailBlock.POWERED).equals("true")) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
if (blockState.getValue(PoweredRailBlock.SHAPE).isSlope()) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block instanceof PistonBaseBlock) {
|
||||
if (getNameHelper(blockState, PistonBaseBlock.EXTENDED).equals("true")) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (block instanceof RepeaterBlock || block instanceof ComparatorBlock) {
|
||||
if (getNameHelper(blockState, ComparatorBlock.POWERED).equals("true")) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
if (block instanceof RepeaterBlock) {
|
||||
if (getNameHelper(blockState, RepeaterBlock.LOCKED).equals("true")) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (block instanceof CrafterBlock) {
|
||||
if (getNameHelper(blockState, CrafterBlock.CRAFTING).equals("true")) {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
BlockState iblockdata1 = cycleState(blockState, iblockstate, player.isSecondaryUseActive());
|
||||
level.setBlock(clickedPos, iblockdata1, 18);
|
||||
message(player, Component.translatable("item.minecraft.debug_stick.update", iblockstate.getName(), getNameHelper(iblockdata1, iblockstate)));
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
|
||||
public static boolean shouldSkipPlace(BlockPlaceContext context) {
|
||||
return RedStoneConfig.shears &&
|
||||
context.getPlayer() != null &&
|
||||
context.getPlayer().getItemInHand(InteractionHand.MAIN_HAND).is(Items.SHEARS);
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> BlockState cycleState(BlockState state, Property<T> property, boolean inverse) {
|
||||
List<T> possibleValues = property.getPossibleValues();
|
||||
if (possibleValues.getFirst() instanceof RailShape) {
|
||||
boolean isRailBlock = state.getBlock() instanceof RailBlock;
|
||||
possibleValues = possibleValues.stream().filter(possibleValue -> {
|
||||
RailShape shape = (RailShape) possibleValue;
|
||||
if (isRailBlock) {
|
||||
return !shape.isSlope();
|
||||
}
|
||||
return !shape.isSlope() && shape != RailShape.NORTH_EAST && shape != RailShape.NORTH_WEST && shape != RailShape.SOUTH_EAST && shape != RailShape.SOUTH_WEST;
|
||||
}).toList();
|
||||
}
|
||||
return state.setValue(property, getRelative(possibleValues, state.getValue(property), inverse)); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
private static <T> T getRelative(Iterable<T> elements, T current, boolean inverse) {
|
||||
return inverse ? Util.findPreviousInIterable(elements, current) : Util.findNextInIterable(elements, current);
|
||||
}
|
||||
|
||||
private static void message(Player player, Component message) {
|
||||
((ServerPlayer) player).sendSystemMessage(message, true);
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> String getNameHelper(BlockState state, Property<T> property) {
|
||||
return property.getName(state.getValue(property));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user