Fix handling of CC: T's version

We never added back replacing of ${version} strings, which means that CC
was reporting incorrect version numbers in _HOST, the user agent and
network versions. This meant we would allow connections even on
mismatched versions (#464).

We shift all version handling into ComputerCraftAPI(Impl) - this now
relies on Forge code, so we don't want to run it in emulators.
This commit is contained in:
SquidDev 2020-06-19 18:49:19 +01:00
parent 58a2995bbc
commit 48edcde4ef
10 changed files with 66 additions and 43 deletions

View File

@ -202,8 +202,6 @@ task proguardMove(dependsOn: proguard) {
}
}
processResources {
inputs.property "version", mod_version
inputs.property "mcversion", mc_version

View File

@ -197,11 +197,6 @@ public ComputerCraft()
Config.load();
}
public static String getVersion()
{
return "${version}";
}
public static InputStream getResourceFile( String domain, String subPath )
{
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();

View File

@ -5,7 +5,6 @@
*/
package dan200.computercraft;
import com.google.common.collect.MapMaker;
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
@ -28,17 +27,15 @@
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import javax.annotation.Nonnull;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.Map;
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
@ -46,18 +43,20 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
{
public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl();
private String version;
private ComputerCraftAPIImpl()
{
}
private WeakReference<IReloadableResourceManager> currentResources;
private final Map<ResourceLocation, ResourceMount> mountCache = new MapMaker().weakValues().concurrencyLevel( 1 ).makeMap();
@Nonnull
@Override
public String getInstalledVersion()
{
return "${version}";
if( version != null ) return version;
return version = ModList.get().getModContainerById( ComputerCraft.MOD_ID )
.map( x -> x.getModInfo().getVersion().toString() )
.orElse( "unknown" );
}
@Override

View File

@ -43,9 +43,10 @@ public static String getInstalledVersion()
}
@Nonnull
@Deprecated
public static String getAPIVersion()
{
return "${version}";
return getInstalledVersion();
}
/**

View File

@ -84,7 +84,7 @@ public void channelActive( ChannelHandlerContext ctx ) throws Exception
}
if( !request.headers().contains( HttpHeaderNames.USER_AGENT ) )
{
request.headers().set( HttpHeaderNames.USER_AGENT, ComputerCraft.MOD_ID + "/" + ComputerCraft.getVersion() );
request.headers().set( HttpHeaderNames.USER_AGENT, this.request.environment().getComputerEnvironment().getUserAgent() );
}
request.headers().set( HttpHeaderNames.HOST, uri.getHost() );
request.headers().set( HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE );

View File

@ -8,6 +8,8 @@
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.InputStream;
public interface IComputerEnvironment
@ -20,13 +22,20 @@ public interface IComputerEnvironment
long getComputerSpaceLimit();
@Nonnull
String getHostString();
@Nonnull
String getUserAgent();
int assignNewID();
@Nullable
IWritableMount createSaveDirMount( String subPath, long capacity );
@Nullable
IMount createResourceMount( String domain, String subPath );
@Nullable
InputStream createResourceFile( String domain, String subPath );
}

View File

@ -30,6 +30,7 @@
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import net.minecraftforge.versions.mcp.MCPVersion;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.InputStream;
@ -341,10 +342,18 @@ public long getComputerSpaceLimit()
return ComputerCraft.computerSpaceLimit;
}
@Nonnull
@Override
public String getHostString()
{
return "ComputerCraft ${version} (Minecraft " + MCPVersion.getMCVersion() + ")";
return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), MCPVersion.getMCVersion() );
}
@Nonnull
@Override
public String getUserAgent()
{
return ComputerCraft.MOD_ID + "/" + ComputerCraftAPI.getInstalledVersion();
}
@Override

View File

@ -6,6 +6,7 @@
package dan200.computercraft.shared.network;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.shared.network.client.*;
import dan200.computercraft.shared.network.server.*;
import net.minecraft.entity.player.PlayerEntity;
@ -35,26 +36,26 @@ private NetworkHandler()
public static void setup()
{
String version = ComputerCraft.getVersion();
String version = ComputerCraftAPI.getInstalledVersion();
network = NetworkRegistry.ChannelBuilder.named( new ResourceLocation( ComputerCraft.MOD_ID, "network" ) )
.networkProtocolVersion( () -> version )
.clientAcceptedVersions( version::equals ).serverAcceptedVersions( version::equals )
.simpleChannel();
// Server messages
registerMainThread( 0, ComputerActionServerMessage::new );
registerMainThread( 1, QueueEventServerMessage::new );
registerMainThread( 2, RequestComputerMessage::new );
registerMainThread( 3, KeyEventServerMessage::new );
registerMainThread( 4, MouseEventServerMessage::new );
registerMainThread( 0, NetworkDirection.PLAY_TO_SERVER, ComputerActionServerMessage::new );
registerMainThread( 1, NetworkDirection.PLAY_TO_SERVER, QueueEventServerMessage::new );
registerMainThread( 2, NetworkDirection.PLAY_TO_SERVER, RequestComputerMessage::new );
registerMainThread( 3, NetworkDirection.PLAY_TO_SERVER, KeyEventServerMessage::new );
registerMainThread( 4, NetworkDirection.PLAY_TO_SERVER, MouseEventServerMessage::new );
// Client messages
registerMainThread( 10, ChatTableClientMessage::new );
registerMainThread( 11, ComputerDataClientMessage::new );
registerMainThread( 12, ComputerDeletedClientMessage::new );
registerMainThread( 13, ComputerTerminalClientMessage::new );
registerMainThread( 14, PlayRecordClientMessage.class, PlayRecordClientMessage::new );
registerMainThread( 15, MonitorClientMessage.class, MonitorClientMessage::new );
registerMainThread( 10, NetworkDirection.PLAY_TO_CLIENT, ChatTableClientMessage::new );
registerMainThread( 11, NetworkDirection.PLAY_TO_CLIENT, ComputerDataClientMessage::new );
registerMainThread( 12, NetworkDirection.PLAY_TO_CLIENT, ComputerDeletedClientMessage::new );
registerMainThread( 13, NetworkDirection.PLAY_TO_CLIENT, ComputerTerminalClientMessage::new );
registerMainThread( 14, NetworkDirection.PLAY_TO_CLIENT, PlayRecordClientMessage.class, PlayRecordClientMessage::new );
registerMainThread( 15, NetworkDirection.PLAY_TO_CLIENT, MonitorClientMessage.class, MonitorClientMessage::new );
}
public static void sendToPlayer( PlayerEntity player, NetworkMessage packet )
@ -90,13 +91,14 @@ public static void sendToAllTracking( NetworkMessage packet, Chunk chunk )
* /**
* Register packet, and a thread-unsafe handler for it.
*
* @param <T> The type of the packet to send.
* @param id The identifier for this packet type
* @param factory The factory for this type of packet.
* @param <T> The type of the packet to send.
* @param id The identifier for this packet type.
* @param direction A network direction which will be asserted before any processing of this message occurs.
* @param factory The factory for this type of packet.
*/
private static <T extends NetworkMessage> void registerMainThread( int id, Supplier<T> factory )
private static <T extends NetworkMessage> void registerMainThread( int id, NetworkDirection direction, Supplier<T> factory )
{
registerMainThread( id, getType( factory ), buf -> {
registerMainThread( id, direction, getType( factory ), buf -> {
T instance = factory.get();
instance.fromBytes( buf );
return instance;
@ -107,14 +109,15 @@ private static <T extends NetworkMessage> void registerMainThread( int id, Suppl
* /**
* Register packet, and a thread-unsafe handler for it.
*
* @param <T> The type of the packet to send.
* @param type The class of the type of packet to send.
* @param id The identifier for this packet type
* @param decoder The factory for this type of packet.
* @param <T> The type of the packet to send.
* @param type The class of the type of packet to send.
* @param id The identifier for this packet type.
* @param direction A network direction which will be asserted before any processing of this message occurs
* @param decoder The factory for this type of packet.
*/
private static <T extends NetworkMessage> void registerMainThread( int id, Class<T> type, Function<PacketBuffer, T> decoder )
private static <T extends NetworkMessage> void registerMainThread( int id, NetworkDirection direction, Class<T> type, Function<PacketBuffer, T> decoder )
{
network.messageBuilder( type, id )
network.messageBuilder( type, id, direction )
.encoder( NetworkMessage::toBytes )
.decoder( decoder )
.consumer( ( packet, contextSup ) -> {

View File

@ -11,8 +11,8 @@
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.common.ServerTerminal;
import dan200.computercraft.shared.common.TileGeneric;
import dan200.computercraft.shared.util.CapabilityUtil;
import dan200.computercraft.shared.network.client.TerminalState;
import dan200.computercraft.shared.util.CapabilityUtil;
import dan200.computercraft.shared.util.NamedTileEntityType;
import dan200.computercraft.shared.util.TickScheduler;
import net.minecraft.entity.player.PlayerEntity;

View File

@ -12,6 +12,7 @@
import dan200.computercraft.core.filesystem.JarMount;
import dan200.computercraft.core.filesystem.MemoryMount;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@ -73,10 +74,18 @@ public long getComputerSpaceLimit()
return ComputerCraft.computerSpaceLimit;
}
@Nonnull
@Override
public String getHostString()
{
return "ComputerCraft ${version} (Test environment)";
return "ComputerCraft 1.0 (Test environment)";
}
@Nonnull
@Override
public String getUserAgent()
{
return "ComputerCraft/1.0";
}
@Override