Skip to content

Commit

Permalink
Merge branch 'mc-1.16.x' into mc-1.18.x
Browse files Browse the repository at this point in the history
  • Loading branch information
SquidDev committed Jul 6, 2023
2 parents 1f3b781 + aa89e51 commit edf372a
Show file tree
Hide file tree
Showing 24 changed files with 368 additions and 160 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ kotlin.stdlib.default.dependency=false
kotlin.jvm.target.validation.mode=error

# Mod properties
modVersion=1.101.2
modVersion=1.101.3

# Minecraft properties: We want to configure this here so we can read it in settings.gradle
mcVersion=1.18.2
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
import com.google.common.net.InetAddresses;
import dan200.computercraft.ComputerCraft;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* A predicate on an address. Matches against a domain and an ip address.
Expand Down Expand Up @@ -135,13 +139,36 @@ final class PrivatePattern implements AddressPredicate
{
static final PrivatePattern INSTANCE = new PrivatePattern();

private static final Set<InetAddress> additionalAddresses = Arrays.stream( new String[] {
// Block various cloud providers internal IPs.
"100.100.100.200", // Alibaba
"192.0.0.192", // Oracle
} ).map( InetAddresses::forString ).collect( Collectors.toSet() );

@Override
public boolean matches( InetAddress socketAddress )
{
return socketAddress.isAnyLocalAddress()
|| socketAddress.isLoopbackAddress()
|| socketAddress.isLinkLocalAddress()
|| socketAddress.isSiteLocalAddress();
return socketAddress.isAnyLocalAddress() // 0.0.0.0, ::0
|| socketAddress.isLoopbackAddress() // 127.0.0.0/8, ::1
|| socketAddress.isLinkLocalAddress() // 169.254.0.0/16, fe80::/10
|| socketAddress.isSiteLocalAddress() // 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fec0::/10
|| socketAddress.isMulticastAddress() // 224.0.0.0/4, ff00::/8
|| isUniqueLocalAddress( socketAddress ) // fd00::/8
|| additionalAddresses.contains( socketAddress );
}

/**
* Determine if an IP address lives inside the ULA address range.
*
* @param address The IP address to test.
* @return Whether this address sits in the ULA address range.
* @see <a href="https://en.wikipedia.org/wiki/Unique_local_address">Unique local address on Wikipedia</a>
*/
private boolean isUniqueLocalAddress( InetAddress address )
{
// ULA is actually defined as fc00::/7 (so both fc00::/8 and fd00::/8). However, only the latter is actually
// defined right now, so let's be conservative.
return address instanceof Inet6Address && (address.getAddress()[0] & 0xff) == 0xfd;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.computer.ComputerSide;
import dan200.computercraft.core.metrics.Metrics;
import dan200.computercraft.shared.command.arguments.ComputersArgumentType;
import dan200.computercraft.shared.command.text.TableBuilder;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
Expand Down Expand Up @@ -200,7 +203,10 @@ else if( b.getLevel() == world )

.then( command( "queue" )
.requires( UserLevel.ANYONE )
.arg( "computer", manyComputers() )
.arg(
RequiredArgumentBuilder.<CommandSourceStack, ComputersArgumentType.ComputersSupplier>argument( "computer", manyComputers() )
.suggests( ( context, builder ) -> Suggestions.empty() )
)
.argManyValue( "args", StringArgumentType.string(), Collections.emptyList() )
.executes( ( ctx, args ) -> {
Collection<ServerComputer> computers = getComputersArgument( ctx, "computer" );
Expand Down
26 changes: 25 additions & 1 deletion src/main/java/dan200/computercraft/shared/command/UserLevel.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,36 @@ public boolean test( CommandSourceStack source )
return source.hasPermission( toLevel() );
}

/**
* Take the union of two {@link UserLevel}s.
* <p>
* This satisfies the property that for all sources {@code s}, {@code a.test(s) || b.test(s) == (a ∪ b).test(s)}.
*
* @param left The first user level to take the union of.
* @param right The second user level to take the union of.
* @return The union of two levels.
*/
public static UserLevel union( UserLevel left, UserLevel right )
{
if( left == right ) return left;

// x ∪ ANYONE = ANYONE
if( left == ANYONE || right == ANYONE ) return ANYONE;

// x ∪ OWNER = OWNER
if( left == OWNER ) return right;
if( right == OWNER ) return left;

// At this point, we have x != y and x, y ∈ { OP, OWNER_OP }.
return OWNER_OP;
}

private static boolean isOwner( CommandSourceStack source )
{
MinecraftServer server = source.getServer();
Entity sender = source.getEntity();
return server.isDedicatedServer()
? source.getEntity() == null && source.hasPermission( 4 ) && source.getTextName().equals( "Server" )
: sender instanceof Player player && player.getGameProfile().getName().equalsIgnoreCase( server.getServerModName() );
: sender instanceof Player player && server.isSingleplayerOwner( player.getGameProfile() );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,17 @@ public CommandBuilder<S> requires( Predicate<S> predicate )
return this;
}

public CommandBuilder<S> arg( String name, ArgumentType<?> type )
public CommandBuilder<S> arg( ArgumentBuilder<S, ?> arg )
{
args.add( RequiredArgumentBuilder.argument( name, type ) );
args.add( arg );
return this;
}

public CommandBuilder<S> arg( String name, ArgumentType<?> type )
{
return arg( RequiredArgumentBuilder.argument( name, type ) );
}

public <T> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argManyValue( String name, ArgumentType<T> type, List<T> empty )
{
return argMany( name, type, () -> empty );
Expand All @@ -84,7 +89,7 @@ private <T, U> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argMany( String nam

return command -> {
// The node for no arguments
ArgumentBuilder<S, ?> tail = tail( ctx -> command.run( ctx, empty.get() ) );
ArgumentBuilder<S, ?> tail = setupTail( ctx -> command.run( ctx, empty.get() ) );

// The node for one or more arguments
ArgumentBuilder<S, ?> moreArg = RequiredArgumentBuilder
Expand All @@ -93,7 +98,7 @@ private <T, U> CommandNodeBuilder<S, ArgCommand<S, List<T>>> argMany( String nam

// Chain all of them together!
tail.then( moreArg );
return link( tail );
return buildTail( tail );
};
}

Expand All @@ -106,22 +111,18 @@ private static <T> List<T> getList( CommandContext<?> context, String name )
@Override
public CommandNode<S> executes( Command<S> command )
{
if( args.isEmpty() ) throw new IllegalStateException( "Cannot have empty arg chain builder" );

return link( tail( command ) );
return buildTail( setupTail( command ) );
}

private ArgumentBuilder<S, ?> tail( Command<S> command )
private ArgumentBuilder<S, ?> setupTail( Command<S> command )
{
ArgumentBuilder<S, ?> defaultTail = args.get( args.size() - 1 );
defaultTail.executes( command );
if( requires != null ) defaultTail.requires( requires );
return defaultTail;
return args.get( args.size() - 1 ).executes( command );
}

private CommandNode<S> link( ArgumentBuilder<S, ?> tail )
private CommandNode<S> buildTail( ArgumentBuilder<S, ?> tail )
{
for( int i = args.size() - 2; i >= 0; i-- ) tail = args.get( i ).then( tail );
if( requires != null ) tail.requires( requires );
return tail.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import dan200.computercraft.shared.command.UserLevel;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.ClickEvent;
Expand All @@ -22,6 +23,10 @@
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static dan200.computercraft.shared.command.text.ChatHelpers.coloured;
import static dan200.computercraft.shared.command.text.ChatHelpers.translate;
Expand All @@ -44,6 +49,33 @@ public static HelpingArgumentBuilder choice( String literal )
return new HelpingArgumentBuilder( literal );
}


@Override
public LiteralArgumentBuilder<CommandSourceStack> requires( Predicate<CommandSourceStack> requirement )
{
throw new IllegalStateException( "Cannot use requires on a HelpingArgumentBuilder" );
}

@Override
public Predicate<CommandSourceStack> getRequirement()
{
// The requirement of this node is the union of all child's requirements.
List<Predicate<CommandSourceStack>> requirements = Stream.concat(
children.stream().map( ArgumentBuilder::getRequirement ),
getArguments().stream().map( CommandNode::getRequirement )
).collect( Collectors.toList() );

// If all requirements are a UserLevel, take the union of those instead.
UserLevel userLevel = UserLevel.OWNER;
for( Predicate<CommandSourceStack> requirement : requirements )
{
if( !(requirement instanceof UserLevel level) ) return x -> requirements.stream().anyMatch( y -> y.test( x ) );
userLevel = UserLevel.union( userLevel, level );
}

return userLevel;
}

@Override
public LiteralArgumentBuilder<CommandSourceStack> executes( final Command<CommandSourceStack> command )
{
Expand Down Expand Up @@ -99,9 +131,7 @@ private LiteralCommandNode<CommandSourceStack> buildImpl( String id, String comm
helpCommand.node = node;

// Set up a /... help command
LiteralArgumentBuilder<CommandSourceStack> helpNode = LiteralArgumentBuilder.<CommandSourceStack>literal( "help" )
.requires( x -> getArguments().stream().anyMatch( y -> y.getRequirement().test( x ) ) )
.executes( helpCommand );
LiteralArgumentBuilder<CommandSourceStack> helpNode = LiteralArgumentBuilder.<CommandSourceStack>literal( "help" ).executes( helpCommand );

// Add all normal command children to this and the help node
for( CommandNode<CommandSourceStack> child : getArguments() )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public void setPlacedBy( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull B
@Override
public float getExplosionResistance( BlockState state, BlockGetter world, BlockPos pos, Explosion explosion )
{
Entity exploder = explosion.getExploder();
Entity exploder = explosion == null ? null : explosion.getExploder();
if( getFamily() == ComputerFamily.ADVANCED || exploder instanceof LivingEntity || exploder instanceof AbstractHurtingProjectile )
{
return 2000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public TurtleModem( ResourceLocation id, ItemStack stack, boolean advanced )
}
else
{
leftOffModel = new ResourceLocation( ComputerCraft.MOD_ID, "turtle_modem_normal_off_left" );
leftOffModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_normal_off_left" );
rightOffModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_normal_off_right" );
leftOnModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_normal_on_left" );
rightOnModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_normal_on_right" );
Expand Down
16 changes: 13 additions & 3 deletions src/main/resources/data/computercraft/lua/rom/apis/gps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,22 @@ function locate(_nTimeout, _bDebug)
if tFix.nDistance == 0 then
pos1, pos2 = tFix.vPosition, nil
else
table.insert(tFixes, tFix)
-- Insert our new position in our table, with a maximum of three items. If this is close to a
-- previous position, replace that instead of inserting.
local insIndex = math.min(3, #tFixes + 1)
for i, older in pairs(tFixes) do
if (older.vPosition - tFix.vPosition):length() < 1 then
insIndex = i
break
end
end
tFixes[insIndex] = tFix

if #tFixes >= 3 then
if not pos1 then
pos1, pos2 = trilaterate(tFixes[1], tFixes[2], tFixes[#tFixes])
pos1, pos2 = trilaterate(tFixes[1], tFixes[2], tFixes[3])
else
pos1, pos2 = narrow(pos1, pos2, tFixes[#tFixes])
pos1, pos2 = narrow(pos1, pos2, tFixes[3])
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ function undefine(name)
details[name] = nil
end

local function set_value(name, value)
local new = reserialize(value)
local function set_value(name, new)
local old = values[name]
if old == nil then
local opt = details[name]
Expand Down Expand Up @@ -103,7 +102,7 @@ function set(name, value)
local opt = details[name]
if opt and opt.type then expect(2, value, opt.type) end

set_value(name, value)
set_value(name, reserialize(value))
end

--- Get the value of a setting.
Expand Down Expand Up @@ -214,7 +213,9 @@ function load(sPath)
if type(k) == "string" and (ty_v == "string" or ty_v == "number" or ty_v == "boolean" or ty_v == "table") then
local opt = details[k]
if not opt or not opt.type or ty_v == opt.type then
set_value(k, v)
-- This may fail if the table is recursive (or otherwise cannot be serialized).
local ok, v = pcall(reserialize, v)
if ok then set_value(k, v) end
end
end
end
Expand Down
11 changes: 9 additions & 2 deletions src/main/resources/data/computercraft/lua/rom/apis/textutils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,13 @@ local g_tLuaKeywords = {
["while"] = true,
}

--- A version of the ipairs iterator which ignores metamethods
local function inext(tbl, i)
i = (i or 0) + 1
local v = rawget(tbl, i)
if v == nil then return nil else return i, v end
end

local serialize_infinity = math.huge
local function serialize_impl(t, tracking, indent, opts)
local sType = type(t)
Expand All @@ -318,11 +325,11 @@ local function serialize_impl(t, tracking, indent, opts)

result = open
local seen_keys = {}
for k, v in ipairs(t) do
for k, v in inext, t do
seen_keys[k] = true
result = result .. sub_indent .. serialize_impl(v, tracking, sub_indent, opts) .. comma
end
for k, v in pairs(t) do
for k, v in next, t do
if not seen_keys[k] then
local sEntry
if type(k) == "string" and not g_tLuaKeywords[k] and string.match(k, "^[%a_][%a%d_]*$") then
Expand Down
Loading

0 comments on commit edf372a

Please sign in to comment.