Merge branch 'master' into future

This commit is contained in:
gnembon committed 2021-10-12 23:24:41 -03:00
commit 6a03675b4f
16 files changed
+161 -36

No files matched your search

+10
View File
@@ -1,5 +1,13 @@
<img src="./src/main/resources/assets/carpet/icon.png" align="right" width="128px"/>
# Fabric Carpet
[![Development Builds](https://github.com/gnembon/fabric-carpet/workflows/Development%20Builds/badge.svg)](https://github.com/gnembon/fabric-carpet/actions?query=workflow%3A%22Development+Builds%22)
[![CurseForge downloads](http://cf.way2muchnoise.eu/full_349239_downloads.svg)](https://www.curseforge.com/minecraft/mc-mods/carpet)
[![GitHub downloads](https://img.shields.io/github/downloads/gnembon/fabric-carpet/total?label=Github%20downloads&logo=github)](https://github.com/gnembon/fabric-carpet/releases)
[![GitHub contributors](https://img.shields.io/github/contributors/gnembon/fabric-carpet?label=Contributors&logo=github)](https://github.com/gnembon/fabric-carpet/graphs/contributors)
[![Discord](https://badgen.net/discord/online-members/gn99m4QRY4?icon=discord&label=Discord&list=what)](https://discord.gg/gn99m4QRY4)
Cause all carpets are made of fabric?
This is the [Fabric](https://fabricmc.net/) version of Carpet Mod, for Minecraft 1.14.X, 1.15.X, 1.16.X and above.
@@ -15,6 +23,8 @@ Carpet Mod is a mod for vanilla Minecraft that allows you to take full control o
For core carpet functionality, this is the right place. Check available downloads on the [release page](https://github.com/gnembon/fabric-carpet/releases)
<img src="https://raw.githubusercontent.com/gnembon/carpet-extra/master/src/main/resources/assets/carpet-extra/icon.png" align="right" width="128px"/>
## carpet-extra
Check [carpet-extra](https://github.com/gnembon/carpet-extra/) add-on mod for more whacky and crazy features, including autocrafting, block-placing dispensers, and even chicken-shearing!
+13
View File
@@ -540,6 +540,8 @@ Returns server tick counter. Can be used to run certain operations every n-th ti
### `world_time()`
_**Deprecated**. Use `system_info('world_time')` instead._
Returns dimension-specific tick counter.
### `day_time(new_time?)`
@@ -549,6 +551,8 @@ to that value. Daytime clocks are shared between all dimensions.
### `last_tick_times()`
_**Deprecated**. Use `system_info('server_last_tick_times')` instead._
Returns a 100-long array of recent tick times, in milliseconds. First item on the list is the most recent tick
If called outside of the main tick (either throgh scheduled tasks, or async execution), then the first item on the
list may refer to the previous tick performance. In this case the last entry (tick 100) would refer to the most current
@@ -600,6 +604,9 @@ world-localized block, so not `block('stone')`, or a string representing a dimen
Throws `unknown_dimension` if provided dimension can't be found.
### `view_distance()`
_**Deprecated**. Use `system_info('server_view_distance')` instead._
Returns the view distance of the server.
### `get_mob_counts()`, `get_mob_counts(category)` 1.16+
@@ -659,6 +666,7 @@ Available options in the scarpet app space:
* `world_carpet_rules` - returns all Carpet rules in a map form (`rule`->`value`). Note that the values are always returned as strings, so you can't do boolean comparisons directly. Includes rules from extensions with their namespace (`namespace:rule`->`value`). You can later listen to rule changes with the `on_carpet_rule_changes(rule, newValue)` event.
* `world_gamerules` - returns all gamerules in a map form (`rule`->`value`). Like carpet rules, values are returned as strings, so you can use appropriate value conversions using `bool()` or `number()` to convert them to other values. Gamerules are read-only to discourage app programmers to mess up with the settings intentionally applied by server admins. Isn't that just super annoying when a datapack messes up with your gamerule settings? It is still possible to change them though using `run('gamerule ...`.
* `world_spawn_point` - world spawn point
* `world_time` - Returns dimension-specific tick counter.
Relevant gameplay related properties
* `game_difficulty` - current difficulty of the game: `'peaceful'`, `'easy'`, `'normal'`, or `'hard'`
@@ -686,6 +694,11 @@ Available options in the scarpet app space:
* `server_banned_ips` - list of banned IP addresses
* `server_dev_environment` - boolean indicating whether this server is in a development environment.
* `server_mods` - map with all loaded mods mapped to their versions as strings
* `server_last_tick_times` - Returns a 100-long array of recent tick times, in milliseconds. First item on the list is the most recent tick
If called outside of the main tick (either throgh scheduled tasks, or async execution), then the first item on the
list may refer to the previous tick performance. In this case the last entry (tick 100) would refer to the most current
tick. For all intent and purpose, `system_info('last_tick_times'):0` should be used as last tick execution time, but
individual tick times may vary greatly, and these need to be taken with the little grain of averaging.
System related properties
* `java_max_memory` - maximum allowed memory accessible by JVM
+3
View File
@@ -513,6 +513,9 @@ public class CarpetSettings
@Rule(desc = "placing blocks cause block updates", category = CREATIVE)
public static boolean interactionUpdates = true;
@Rule(desc = "Disables breaking of blocks caused by flowing liquids", category = CREATIVE)
public static boolean liquidDamageDisabled = false;
@Rule(
desc = "smooth client animations with low tps settings",
extra = "works only in SP, and will slow down players",
@@ -35,6 +35,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
@@ -46,6 +47,10 @@ public class PlayerCommand
// TODO: allow any order like execute
public static void register(CommandDispatcher<ServerCommandSource> dispatcher)
{
final String[] gamemodeStrings = Arrays.stream(GameMode.values())
.map(GameMode::getName)
.collect(Collectors.toList())
.toArray(new String[]{});
LiteralArgumentBuilder<ServerCommandSource> literalargumentbuilder = literal("player")
.requires((player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandPlayer))
.then(argument("player", StringArgumentType.word())
@@ -93,10 +98,18 @@ public class PlayerCommand
.then(literal("left").executes(c -> manipulate(c, ap -> ap.setStrafing(1))))
.then(literal("right").executes(c -> manipulate(c, ap -> ap.setStrafing(-1))))
).then(literal("spawn").executes(PlayerCommand::spawn)
.then(literal("in").requires((player) -> player.hasPermissionLevel(2))
.then(argument("gamemode", StringArgumentType.word())
.suggests( (c, b) -> suggestMatching(gamemodeStrings, b))
.executes(PlayerCommand::spawn)))
.then(literal("at").then(argument("position", Vec3ArgumentType.vec3()).executes(PlayerCommand::spawn)
.then(literal("facing").then(argument("direction", RotationArgumentType.rotation()).executes(PlayerCommand::spawn)
.then(literal("in").then(argument("dimension", DimensionArgumentType.dimension()).executes(PlayerCommand::spawn)))
))
.then(literal("in").then(argument("dimension", DimensionArgumentType.dimension()).executes(PlayerCommand::spawn)
.then(literal("in").requires((player) -> player.hasPermissionLevel(2))
.then(argument("gamemode", StringArgumentType.word()).suggests( (c, b) -> suggestMatching(gamemodeStrings, b))
.executes(PlayerCommand::spawn)
)))
)))
))
)
);
@@ -273,6 +286,20 @@ public class PlayerCommand
flying = player.getAbilities().flying;
}
catch (CommandSyntaxException ignored) {}
try {
String opGameMode = StringArgumentType.getString(context, "gamemode");
mode = GameMode.byName(opGameMode, null);
if(mode == null)
{
Messenger.m(context.getSource(), "rb Invalid game mode: "+opGameMode+".");
return 0;
}
} catch (IllegalArgumentException ignored) {}
if(mode == GameMode.SPECTATOR)
{
// Force override flying to true for spectator players, or they will fell out of the world.
flying = true;
}
String playerName = StringArgumentType.getString(context, "player");
if (playerName.length()>maxPlayerLength(source.getServer()))
{
@@ -0,0 +1,34 @@
package carpet.mixins;
import carpet.CarpetSettings;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.fluid.FlowableFluid;
import net.minecraft.fluid.Fluid;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(FlowableFluid.class)
public class FlowableFluid_liquidDamageDisabledMixin
{
@Inject(
method = "canFill",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/block/Material;blocksMovement()Z"
),
cancellable = true
)
private void stopBreakingBlock(BlockView world, BlockPos pos, BlockState state, Fluid fluid, CallbackInfoReturnable<Boolean> cir)
{
if (CarpetSettings.liquidDamageDisabled)
{
Material material = state.getMaterial();
cir.setReturnValue(material == Material.AIR || material.isLiquid());
}
}
}
@@ -6,9 +6,9 @@ import carpet.helpers.EntityPlayerActionPack;
import com.mojang.authlib.GameProfile;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.server.world.ServerWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -16,7 +16,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ServerPlayerEntity.class)
public abstract class ServerPlayerEntityMixin implements ServerPlayerEntityInterface
{
@Unique
public EntityPlayerActionPack actionPack;
@Override
public EntityPlayerActionPack getActionPack()
{
return actionPack;
@@ -41,15 +43,11 @@ public abstract class ServerPlayerEntityMixin implements ServerPlayerEntityInter
}
catch (StackOverflowError soe)
{
CarpetSettings.LOG.fatal("Caused stack overflow when performing player action");
CarpetSettings.LOG.fatal("Caused stack overflow when performing player action", soe);
}
catch (Throwable exc)
{
CarpetSettings.LOG.fatal("Error executing player tasks "+ exc.getMessage());
exc.printStackTrace();
CarpetSettings.LOG.fatal("Error executing player tasks", exc);
}
}
}
@@ -96,8 +96,7 @@ public abstract class StructureFeatureMixin<C extends FeatureConfig> implements
}
catch (Exception booboo)
{
CarpetSettings.LOG.error("Unknown Exception while plopping structure: "+booboo);
booboo.printStackTrace();
CarpetSettings.LOG.error("Unknown Exception while plopping structure: "+booboo, booboo);
return false;
}
finally
@@ -1174,7 +1174,7 @@ public class CarpetEventServer
}
catch (NullPointerException | InvalidCallbackException | IntegrityException error)
{
CarpetScriptServer.LOG.error("Got exception: "+error.getMessage());
CarpetScriptServer.LOG.error("Got exception when running event call ", error);
return CallbackResult.FAIL;
}
}
+1 -1
View File
@@ -377,7 +377,7 @@ public class Expression
if (exc instanceof ResolvedException)
return exc;
// unexpected really - should be caught earlier and converted to InternalExpressionException
exc.printStackTrace();
CarpetSettings.LOG.error("Unexpected exception while running Scarpet code", exc);
return new ExpressionException(c, e, token, "Error while evaluating expression: "+exc);
}
+11 -14
View File
@@ -21,6 +21,7 @@ import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ThrowStatement;
import carpet.script.exception.Throwables;
import carpet.script.utils.SnoopyCommandSource;
import carpet.script.utils.SystemInfo;
import carpet.script.utils.InputValidator;
import carpet.script.utils.ScarpetJsonDeserializer;
import carpet.script.utils.ShapeDispatcher;
@@ -655,8 +656,10 @@ public class Auxiliary {
expression.addContextFunction("tick_time", 0, (c, t, lv) ->
new NumericValue(((CarpetContext) c).s.getServer().getTicks()));
expression.addContextFunction("world_time", 0, (c, t, lv) ->
new NumericValue(((CarpetContext) c).s.getWorld().getTime()));
expression.addContextFunction("world_time", 0, (c, t, lv) -> {
c.host.issueDeprecation("world_time()");
return new NumericValue(((CarpetContext) c).s.getWorld().getTime());
});
expression.addContextFunction("day_time", -1, (c, t, lv) ->
{
@@ -672,16 +675,8 @@ public class Auxiliary {
expression.addContextFunction("last_tick_times", -1, (c, t, lv) ->
{
//assuming we are in the tick world section
// might be off one tick when run in the off tasks or asynchronously.
int currentReportedTick = ((CarpetContext) c).s.getServer().getTicks()-1;
List<Value> ticks = new ArrayList<>(100);
final long[] tickArray = ((CarpetContext) c).s.getServer().lastTickLengths;
for (int i=currentReportedTick+100; i > currentReportedTick; i--)
{
ticks.add(new NumericValue(((double)tickArray[i % 100])/1000000.0));
}
return ListValue.wrap(ticks);
c.host.issueDeprecation("last_tick_times()");
return SystemInfo.get("last_tick_times", (CarpetContext)c);
});
@@ -742,8 +737,10 @@ public class Auxiliary {
expression.addContextFunction("current_dimension", 0, (c, t, lv) ->
ValueConversions.of( ((CarpetContext)c).s.getWorld()));
expression.addContextFunction("view_distance", 0, (c, t, lv) ->
new NumericValue(((CarpetContext)c).s.getServer().getPlayerManager().getViewDistance()));
expression.addContextFunction("view_distance", 0, (c, t, lv) -> {
c.host.issueDeprecation("view_distance()");
return new NumericValue(((CarpetContext)c).s.getServer().getPlayerManager().getViewDistance());
});
// lazy due to passthrough and context changing ability
expression.addLazyFunction("in_dimension", 2, (c, t, lv) -> {
@@ -10,6 +10,7 @@ import carpet.script.utils.SimplexNoiseSampler;
import carpet.script.value.BooleanValue;
import carpet.script.value.FunctionValue;
import carpet.script.value.ListValue;
import carpet.script.value.MapValue;
import carpet.script.value.NullValue;
import carpet.script.value.NumericValue;
import carpet.script.value.StringValue;
@@ -56,6 +57,10 @@ public class Sys {
if (num.isInteger()) return new NumericValue(num.getLong());
return new NumericValue(num.getDouble());
}
if (v instanceof ListValue || v instanceof MapValue)
{
return new NumericValue(v.length());
}
try
{
return new NumericValue(v.getString());
@@ -23,9 +23,11 @@ import net.minecraft.world.WorldProperties;
import java.lang.management.ManagementFactory;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
@@ -58,6 +60,7 @@ public class SystemInfo {
WorldProperties prop = c.s.getServer().getOverworld().getLevelProperties();
return ListValue.of(NumericValue.of(prop.getSpawnX()), NumericValue.of(prop.getSpawnY()), NumericValue.of(prop.getSpawnZ()));
});
put("world_time", c -> new NumericValue(c.s.getWorld().getTime()));
put("game_difficulty", c -> StringValue.of(c.s.getServer().getSaveProperties().getDifficulty().getName()));
put("game_hardcore", c -> BooleanValue.of(c.s.getServer().getSaveProperties().isHardcore()));
@@ -114,6 +117,18 @@ public class SystemInfo {
ret.put(new StringValue(mod.getMetadata().getName()), new StringValue(mod.getMetadata().getVersion().getFriendlyString()));
return MapValue.wrap(ret);
});
put("server_last_tick_times", c -> {
//assuming we are in the tick world section
// might be off one tick when run in the off tasks or asynchronously.
int currentReportedTick = c.s.getServer().getTicks()-1;
List<Value> ticks = new ArrayList<>(100);
final long[] tickArray = c.s.getServer().lastTickLengths;
for (int i=currentReportedTick+100; i > currentReportedTick; i--)
{
ticks.add(new NumericValue(((double)tickArray[i % 100])/1000000.0));
}
return ListValue.wrap(ticks);
});
put("java_max_memory", c -> new NumericValue(Runtime.getRuntime().maxMemory()));
put("java_allocated_memory", c -> new NumericValue(Runtime.getRuntime().totalMemory()));
+2 -1
View File
@@ -1,5 +1,6 @@
package carpet.script.value;
import carpet.CarpetSettings;
import carpet.script.exception.InternalExpressionException;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
@@ -42,7 +43,7 @@ public abstract class Value implements Comparable<Value>, Cloneable
catch (CloneNotSupportedException e)
{
// should not happen
e.printStackTrace();
CarpetSettings.LOG.catching(e);
throw new InternalExpressionException("Variable of type "+getTypeString()+" is not cloneable. Tell gnembon about it, this shoudn't happen");
}
copy.boundVariable = var;
@@ -13,6 +13,8 @@ import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.player.PlayerEntity;
@@ -35,15 +37,19 @@ import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static carpet.utils.Translations.tr;
import static carpet.script.CarpetEventServer.Event.CARPET_RULE_CHANGES;
@@ -315,8 +321,7 @@ public class SettingsManager
}
catch (IOException e)
{
e.printStackTrace();
CarpetSettings.LOG.error("[CM]: failed write "+identifier+".conf config file");
CarpetSettings.LOG.error("[CM]: failed write "+identifier+".conf config file", e);
}
///todo is it really needed? resendCommandTree();
}
@@ -474,7 +479,7 @@ public class SettingsManager
}
catch (IOException e)
{
e.printStackTrace();
CarpetSettings.LOG.error("Exception while loading Carpet rules from config", e);
return new ConfigReadResult(new HashMap<>(), false);
}
}
@@ -544,6 +549,20 @@ public class SettingsManager
return rule;
}
static CompletableFuture<Suggestions> suggestMatchingContains(Stream<String> stream, SuggestionsBuilder suggestionsBuilder) {
String query = suggestionsBuilder.getRemaining().toLowerCase(Locale.ROOT);
var filteredSuggestionList = stream.filter((listItem) -> { //Regex camelCase Search
var words = Arrays.stream(listItem.split("(?<!^)(?=[A-Z])")).map(s -> s.toLowerCase(Locale.ROOT)).collect(Collectors.toList());
var prefixes = new ArrayList<String>(words.size());
for (int i = 0; i < words.size(); i++)
prefixes.add(String.join("",words.subList(i, words.size())));
return prefixes.stream().anyMatch(s -> s.startsWith(query));
});
Objects.requireNonNull(suggestionsBuilder);
filteredSuggestionList.forEach(suggestionsBuilder::suggest);
return suggestionsBuilder.buildFuture();
}
/**
* Registers the the settings command for this {@link SettingsManager}.<br>
* It is handled automatically by Carpet.
@@ -576,17 +595,17 @@ public class SettingsManager
then(literal("removeDefault").
requires(s -> !locked).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(getRules().stream().map(r -> r.name), b)).
suggests( (c, b) -> suggestMatchingContains(getRules().stream().map(r -> r.name), b)).
executes((c) -> removeDefault(c.getSource(), contextRule(c))))).
then(literal("setDefault").
requires(s -> !locked).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(getRules().stream().map(r -> r.name), b)).
suggests( (c, b) -> suggestMatchingContains(getRules().stream().map(r -> r.name), b)).
then(argument("value", StringArgumentType.greedyString()).
suggests((c, b)-> suggestMatching(contextRule(c).options, b)).
executes((c) -> setDefault(c.getSource(), contextRule(c), StringArgumentType.getString(c, "value")))))).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(getRules().stream().map(r -> r.name), b)).
suggests( (c, b) -> suggestMatchingContains(getRules().stream().map(r -> r.name), b)).
requires(s -> !locked ).
executes( (c) -> displayRuleMenu(c.getSource(), contextRule(c))).
then(argument("value", StringArgumentType.greedyString()).
@@ -36,6 +36,8 @@ import net.minecraft.world.gen.feature.StructureFeature;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;
import carpet.CarpetSettings;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -462,7 +464,7 @@ public class SpawnReporter
}
catch (Exception exception)
{
exception.printStackTrace();
CarpetSettings.LOG.warn("Exception while creating mob for spawn reporter", exception);
return rep;
}
@@ -519,7 +521,7 @@ public class SpawnReporter
}
catch (Exception exception)
{
exception.printStackTrace();
CarpetSettings.LOG.warn("Exception while creating mob for spawn reporter", exception);
return rep;
}
}
+2
View File
@@ -26,6 +26,8 @@
"Structure_fillUpdatesMixin",
"ServerPlayNetworkHandler_interactionUpdatesMixin",
"FlowableFluid_liquidDamageDisabledMixin",
"ServerMetadata_motdMixin",
"MinecraftServer_pingPlayerSampleLimit",