mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-08-28 16:22:18 +00:00
Merge branch 'mc-1.18.x/stable' into mc-1.18.x/dev
This commit is contained in:
commit
7f368727f4
38
README.md
38
README.md
@ -2,21 +2,25 @@
|
|||||||
|
|
||||||
[](https://github.com/cc-tweaked/cc-restitched/actions "Current build status")
|
[](https://github.com/cc-tweaked/cc-restitched/actions "Current build status")
|
||||||
[](https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched on CurseForge")
|
[](https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched on CurseForge")
|
||||||
[](https://gitpod.io/#https://github.com/cc-tweaked/cc-restitched/tree/1.17)
|
[](https://gitpod.io/#https://github.com/cc-tweaked/cc-restitched/tree/1.17.1)
|
||||||
|
|
||||||
# CC: R Version VS CC: T Version
|
# What is CC: Restitched?
|
||||||
CC: R Strives to maintain perfect pairity with CC: T, however in some cases this is not possible, so CC: R might have a "newer" version than what CC: T has, these newer versions will be primarily bugfixes and the like because [Fabric](https://fabricmc.net/) is "weird" when porting a Forge mod.
|
This is a fabric port of [SquidDev-CC/CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked). The work is a continuation of [Zundrel/cc-tweaked-fabric](https://github.com/Zundrel/cc-tweaked-fabric).
|
||||||
|
|
||||||
## What is CC: Restiched
|
## CC: Restitched vs. CC: Tweaked
|
||||||
This is an fork of [Zundrel/cc-tweaked-fabric](https://github.com/Zundrel/cc-tweaked-fabric) who's goal was to port [SquidDev-CC/CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked) to the [Fabric](https://fabricmc.net/) modloader. I picked up maintaining the mod because the team working on Zundrel's fork can no longer mantain it so, I picked it up to make it as equal as possible with CC: T.
|
CC: R tries to maintain parity with CC: T, but may be behind or divergent in some areas. If you notice a disparity please open an issue. CC: R major and minor version numbers indicate parity with the major features of that version of CC: T. Patch version numbers will not align.
|
||||||
|
|
||||||
## Resource Packs
|
## Resource Packs
|
||||||
This mod includes textures that are more in-line with the style of Mojang's new texture-artist, Jappa. If you prefer the original textures, enable the "Classic" resource pack.
|
This mod includes textures by [Jummit](https://github.com/Jummit) that are more in line with the style of Mojang's new texture-artist, Jappa. If you prefer the original textures, enable the "Classic" resource pack.
|
||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/3prm3/cc-pack/main/pack.png" alt="CC: Restitched" width="16" height="16"/> [3prm3/cc-pack](https://github.com/3prm3/cc-pack/)
|
<img src="https://raw.githubusercontent.com/3prm3/cc-pack/main/pack.png" alt="CC: Restitched" width="16" height="16"/> We also have a second resourcepack made by [3prm3](https://github.com/3prm3), it features a complete overhaul and can be enabled by enabling the `overhaul` resource pack, go check out his resource pack over [here](https://github.com/3prm3/cc-pack/)!
|
||||||
We also have a second resourcepack made by [3prm3](https://github.com/3prm3), it features a complete overhaul and can be enabled by enabling the `overhaul` resource pack, go check out his resource pack over here!
|
|
||||||
|
|
||||||
# Does this work with shaders/[Sodium?](https://github.com/CaffeineMC/sodium-fabric)
|
## Contributing
|
||||||
|
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping develop CC: R there are a few rules;
|
||||||
|
1) Make sure your code follows the checkstyle rules. You can test this by running `./gradle build` or `./gradle check`.
|
||||||
|
2) Do not alter the lua code unless those changes are taken directly from CC: Tweaked. If you wish to contribute changes to the in game rom please contribute upstream at [CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked).
|
||||||
|
|
||||||
|
# Does this work Fabric's many rendering mods?
|
||||||
* [ YES ] Sodium
|
* [ YES ] Sodium
|
||||||
* [ YES ] Optifine
|
* [ YES ] Optifine
|
||||||
* Works with VBO Rendering (automatically set)
|
* Works with VBO Rendering (automatically set)
|
||||||
@ -58,17 +62,5 @@ Bleeding edge builds can be found [here](https://github.com/cc-tweaked/cc-restit
|
|||||||
## Community
|
## Community
|
||||||
If you need help getting started with CC: Restitched, want to show off your latest project, or just want to chat about ComputerCraft, here is the [Forum](https://forums.computercraft.cc/) and the [Discord](https://discord.gg/H2UyJXe).
|
If you need help getting started with CC: Restitched, want to show off your latest project, or just want to chat about ComputerCraft, here is the [Forum](https://forums.computercraft.cc/) and the [Discord](https://discord.gg/H2UyJXe).
|
||||||
|
|
||||||
## Known Bugs/Issues
|
## Perpheral mods
|
||||||
Main Known issue
|
Unfortunately, CC: Restitched does not have as many peripherals mods available as CC: Tweaked. If you're an interested mod developer, please check out our `api` package. If you've already made a mod with CC: R peripheral support OR if you're a player who found a mod with ComputerCraft integration, please open an [issue here](https://github.com/cc-tweaked/cc-restitched/issues/new?assignees=&labels=peripheralShoutout&template=peripheral_shoutout.md) to let us know and we'll add it to the list!
|
||||||
* Mods that add blocks that can be used as peripherals for CC: T on Forge, don't work with CC: R.
|
|
||||||
* This is because of the differences between Forge and [Fabric](https://fabricmc.net/), and that mod devs, to my knowledge have not agreed upon a standard method in which to implement cross compatibility between mods,
|
|
||||||
* Occasionally a computer will say "File not found" when running a built in program, this is normal just hold `crtl+r` to reboot it.
|
|
||||||
* We do not know what causes it directly, however it happens when the world is `/reload`ed, and currently running programs are not affected so nothing *should break*
|
|
||||||
|
|
||||||
## Perpherals
|
|
||||||
Unfortunately, unlike the original CC: Tweaked project, CC: Restitched, does not have any actual peripheral mods, currently the only one we have is an example for mod devs to get started with making/adding the peripheral API to their mods!
|
|
||||||
|
|
||||||
If you're a mod dev, made a mod with CC: R peripheral support OR if you're a player who found a mod with CC: R support, please open an [issue here](https://github.com/cc-tweaked/cc-restitched/issues/new?assignees=&labels=peripheralShoutout&template=peripheral_shoutout.md) to let us know so we can add it to the list!
|
|
||||||
|
|
||||||
*  [CC Peripheral Test [1.16.5]](https://github.com/Toad-Dev/cc-peripheral-test)
|
|
||||||
* This is an example mod for how to make peripherals that work as a block, or as a turtle upgrade!
|
|
||||||
|
@ -237,13 +237,7 @@ task licenseFormatAPI(type: LicenseFormat)
|
|||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
mavenJava(MavenPublication) {
|
mavenJava(MavenPublication) {
|
||||||
// add all the jars that should be included when publishing to maven
|
from components.java
|
||||||
artifact(remapJar) {
|
|
||||||
builtBy remapJar
|
|
||||||
}
|
|
||||||
artifact(sourcesJar) {
|
|
||||||
builtBy remapSourcesJar
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
org.gradle.jvmargs=-Xmx1G
|
org.gradle.jvmargs=-Xmx1G
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
mod_version=1.99.1
|
mod_version=1.99.2-alpha1
|
||||||
|
|
||||||
# Minecraft properties
|
# Minecraft properties
|
||||||
mc_version=1.18.1
|
mc_version=1.18.1
|
||||||
|
@ -8,4 +8,4 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.name = "cc-restiched"
|
rootProject.name = "cc-restitched"
|
||||||
|
@ -3,73 +3,138 @@
|
|||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dan200.computercraft.fabric.mixin;
|
package dan200.computercraft.fabric.mixin;
|
||||||
|
|
||||||
|
import dan200.computercraft.fabric.util.ServerTranslationEntry;
|
||||||
|
import net.minecraft.util.StringDecomposer;
|
||||||
|
import net.minecraft.util.FormattedCharSequence;
|
||||||
|
import net.minecraft.network.chat.FormattedText;
|
||||||
|
import net.minecraft.network.chat.Style;
|
||||||
|
import net.minecraft.locale.Language;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.fabricmc.loader.api.ModContainer;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
import dan200.computercraft.shared.peripheral.generic.data.ItemData;
|
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
|
||||||
import net.minecraft.locale.Language;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all mods en_us lang file into the default Language instance on the dedicated server.
|
* Loads all mods' en_us lang file into the Language instance on the dedicated server with a basic strategy for
|
||||||
* Needed so that lua code running on the server can access the display name of items.
|
* resolving collisions.
|
||||||
*
|
|
||||||
* @see ItemData#fill
|
|
||||||
*/
|
*/
|
||||||
@Mixin( Language.class )
|
@Mixin( Language.class )
|
||||||
public class MixinLanguage
|
public class MixinLanguage
|
||||||
{
|
{
|
||||||
@Shadow
|
@Shadow
|
||||||
|
@Final
|
||||||
private static Logger LOGGER;
|
private static Logger LOGGER;
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private static String DEFAULT;
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
public static void loadFromJson( InputStream inputStream, BiConsumer<String, String> entryConsumer )
|
private static void loadFromJson( InputStream inputStream, BiConsumer<String, String> entryConsumer )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadModLangFile( String modId, BiConsumer<String, String> biConsumer )
|
private static void loadModLangFile( ModContainer modContainer, BiConsumer<String, String> biConsumer )
|
||||||
{
|
{
|
||||||
String path = "/assets/" + modId + "/lang/en_us.json";
|
Path path = modContainer.getPath( "assets/" + modContainer.getMetadata().getId() + "/lang/" + DEFAULT + ".json" );
|
||||||
|
if ( !Files.exists( path ) ) return;
|
||||||
|
|
||||||
try( InputStream inputStream = Language.class.getResourceAsStream( path ) )
|
try ( InputStream inputStream = Files.newInputStream( path ) )
|
||||||
{
|
{
|
||||||
if( inputStream == null ) return;
|
|
||||||
loadFromJson( inputStream, biConsumer );
|
loadFromJson( inputStream, biConsumer );
|
||||||
}
|
}
|
||||||
catch( JsonParseException | IOException e )
|
catch ( JsonParseException | IOException e )
|
||||||
{
|
{
|
||||||
LOGGER.error( "Couldn't read strings from " + path, e );
|
LOGGER.error( "Couldn't read strings from " + path, e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject( method = "loadDefault", locals = LocalCapture.CAPTURE_FAILSOFT, at = @At( value = "INVOKE", remap = false, target = "Lcom/google/common/collect/ImmutableMap$Builder;build()Lcom/google/common/collect/ImmutableMap;" ) )
|
@Inject( method = "loadDefault", cancellable = true, at = @At( "HEAD" ) )
|
||||||
private static void loadDefault( CallbackInfoReturnable<Language> cir, ImmutableMap.Builder<String, String> builder )
|
private static void loadDefault( CallbackInfoReturnable<Language> cir )
|
||||||
{
|
{
|
||||||
/* We must ensure that the keys are de-duplicated because we can't catch the error that might otherwise
|
Map<String, List<ServerTranslationEntry>> translations = new HashMap<>();
|
||||||
* occur when the injected function calls build() on the ImmutableMap builder. So we use our own hash map and
|
|
||||||
* exclude "minecraft", as the injected function has already loaded those keys at this point.
|
|
||||||
*/
|
|
||||||
HashMap<String, String> translations = new HashMap<>();
|
|
||||||
|
|
||||||
FabricLoader.getInstance().getAllMods().stream().map( modContainer -> modContainer.getMetadata().getId() )
|
for ( ModContainer mod : FabricLoader.getInstance().getAllMods() )
|
||||||
.filter( id -> !id.equals( "minecraft" ) ).forEach( id -> {
|
{
|
||||||
loadModLangFile( id, translations::put );
|
loadModLangFile( mod, ( k, v ) -> {
|
||||||
|
if ( !translations.containsKey( k ) ) translations.put( k, new ArrayList<>() );
|
||||||
|
translations.get( k ).add( new ServerTranslationEntry( mod.getMetadata(), k, v ) );
|
||||||
} );
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
builder.putAll( translations );
|
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
|
||||||
|
|
||||||
|
for ( Map.Entry<String, List<ServerTranslationEntry>> keyEntry : translations.entrySet() )
|
||||||
|
{
|
||||||
|
if ( keyEntry.getValue().size() == 1 )
|
||||||
|
{
|
||||||
|
// Only one value provided for this key
|
||||||
|
builder.put( keyEntry.getKey(), keyEntry.getValue().get( 0 ).value() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Collision occurred for this key.
|
||||||
|
// Strategy: Resolve collision by choosing value provided by the mod that depends on the greatest number
|
||||||
|
// of other mods in this collision cluster, according to mod metadata.
|
||||||
|
// Rationale: The mod that intends to overwrite another mod's keys is more likely to declare the
|
||||||
|
// overwritee as a dependency.
|
||||||
|
Set<String> clusterIds = keyEntry.getValue().stream().map( ServerTranslationEntry::getModId ).collect( Collectors.toSet() );
|
||||||
|
ServerTranslationEntry pickedEntry = Collections.max( keyEntry.getValue(),
|
||||||
|
Comparator.comparingInt( entry -> entry.getDependencyIntersectionSize( clusterIds ) ) );
|
||||||
|
builder.put( keyEntry.getKey(), pickedEntry.value() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, String> map = builder.build();
|
||||||
|
cir.setReturnValue( new Language()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public String getOrDefault( String key )
|
||||||
|
{
|
||||||
|
return map.getOrDefault( key, key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean has( String key )
|
||||||
|
{
|
||||||
|
return map.containsKey( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDefaultRightToLeft()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FormattedCharSequence getVisualOrder( @NotNull FormattedText text )
|
||||||
|
{
|
||||||
|
return visitor -> text.visit( ( style, string ) -> StringDecomposer.iterateFormatted( string, style, visitor ) ? Optional.empty() : FormattedText.STOP_ITERATION, Style.EMPTY ).isPresent();
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
||||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
|
||||||
*/
|
|
||||||
package dan200.computercraft.fabric.mixin;
|
|
||||||
|
|
||||||
import dan200.computercraft.shared.common.TileGeneric;
|
|
||||||
import net.minecraft.world.level.Level;
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Horrible bodge to ensure a {@link BlockEntity}'s world is always present when setting a TE during another TE's tick.
|
|
||||||
*
|
|
||||||
* Forge does this, this is just a bodge to get Fabric in line with that behaviour.
|
|
||||||
*/
|
|
||||||
@Mixin( Level.class )
|
|
||||||
public class MixinLevel
|
|
||||||
{
|
|
||||||
@Shadow
|
|
||||||
protected boolean tickingBlockEntities;
|
|
||||||
|
|
||||||
@Inject( method = "setBlockEntity", at = @At( "HEAD" ) )
|
|
||||||
public void setBlockEntity( @Nullable BlockEntity entity, CallbackInfo info )
|
|
||||||
{
|
|
||||||
if( entity != null && !entity.isRemoved() && entity.getLevel() != null && entity.getLevel().isInWorldBounds( entity.getBlockPos() ) && tickingBlockEntities )
|
|
||||||
{
|
|
||||||
setWorld( entity, this );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void setWorld( BlockEntity entity, Object world )
|
|
||||||
{
|
|
||||||
if( entity.getLevel() != world && entity instanceof TileGeneric )
|
|
||||||
{
|
|
||||||
entity.setLevel( (Level) world ); //TODO why?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Inject( method = "addBlockEntities", at = @At( "HEAD" ) )
|
|
||||||
public void addBlockEntities( Collection<BlockEntity> entities, CallbackInfo info )
|
|
||||||
{
|
|
||||||
if( tickingBlockEntities )
|
|
||||||
{
|
|
||||||
for( BlockEntity entity : entities )
|
|
||||||
{
|
|
||||||
setWorld( entity, this );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.fabric.util;
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.metadata.ModDependency;
|
||||||
|
import net.fabricmc.loader.api.metadata.ModMetadata;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
// A utility class for holding translation mappings prior collision resolution.
|
||||||
|
public record ServerTranslationEntry(ModMetadata providingModMetadata, String key, String value )
|
||||||
|
{
|
||||||
|
public String getModId()
|
||||||
|
{
|
||||||
|
return providingModMetadata.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getDependencyIds()
|
||||||
|
{
|
||||||
|
Set<String> deps = providingModMetadata.getDependencies().stream().map( ModDependency::getModId ) .collect( Collectors.toSet() );
|
||||||
|
// For the purposes of handling key collisions, all mods should depend on minecraft
|
||||||
|
if ( !getModId().equals( "minecraft" ) ) deps.add( "minecraft" );
|
||||||
|
return deps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDependencyIntersectionSize( Set<String> idSet )
|
||||||
|
{
|
||||||
|
Set<String> intersection = getDependencyIds();
|
||||||
|
intersection.retainAll( idSet );
|
||||||
|
return intersection.size();
|
||||||
|
}
|
||||||
|
}
|
@ -45,11 +45,13 @@ import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
|||||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||||
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
||||||
import dan200.computercraft.shared.turtle.upgrades.*;
|
import dan200.computercraft.shared.turtle.upgrades.TurtleCraftingTable;
|
||||||
|
import dan200.computercraft.shared.turtle.upgrades.TurtleModem;
|
||||||
|
import dan200.computercraft.shared.turtle.upgrades.TurtleSpeaker;
|
||||||
|
import dan200.computercraft.shared.turtle.upgrades.TurtleTool;
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||||
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.cauldron.CauldronInteraction;
|
import net.minecraft.core.cauldron.CauldronInteraction;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
@ -107,14 +109,14 @@ public final class Registry
|
|||||||
public static final BlockMonitor MONITOR_ADVANCED =
|
public static final BlockMonitor MONITOR_ADVANCED =
|
||||||
register( "monitor_advanced", new BlockMonitor( properties(), () -> ModBlockEntities.MONITOR_ADVANCED ) );
|
register( "monitor_advanced", new BlockMonitor( properties(), () -> ModBlockEntities.MONITOR_ADVANCED ) );
|
||||||
|
|
||||||
public static final BlockComputer COMPUTER_NORMAL =
|
public static final BlockComputer<TileComputer> COMPUTER_NORMAL =
|
||||||
register( "computer_normal", new BlockComputer( properties(), ComputerFamily.NORMAL, () -> ModBlockEntities.COMPUTER_NORMAL ) );
|
register( "computer_normal", new BlockComputer<>( properties(), ComputerFamily.NORMAL, () -> ModBlockEntities.COMPUTER_NORMAL ) );
|
||||||
|
|
||||||
public static final BlockComputer COMPUTER_ADVANCED =
|
public static final BlockComputer<TileComputer> COMPUTER_ADVANCED =
|
||||||
register( "computer_advanced", new BlockComputer( properties(), ComputerFamily.ADVANCED, () -> ModBlockEntities.COMPUTER_ADVANCED ) );
|
register( "computer_advanced", new BlockComputer<>( properties(), ComputerFamily.ADVANCED, () -> ModBlockEntities.COMPUTER_ADVANCED ) );
|
||||||
|
|
||||||
public static final BlockComputer COMPUTER_COMMAND =
|
public static final BlockComputer<TileCommandComputer> COMPUTER_COMMAND =
|
||||||
register( "computer_command", new BlockComputer( FabricBlockSettings.copyOf( Blocks.STONE ).strength( -1, 6000000.0F ), ComputerFamily.COMMAND, () -> ModBlockEntities.COMPUTER_COMMAND ) );
|
register( "computer_command", new BlockComputer<>( FabricBlockSettings.copyOf( Blocks.STONE ).strength( -1, 6000000.0F ), ComputerFamily.COMMAND, () -> ModBlockEntities.COMPUTER_COMMAND ) );
|
||||||
|
|
||||||
public static final BlockTurtle TURTLE_NORMAL =
|
public static final BlockTurtle TURTLE_NORMAL =
|
||||||
register( "turtle_normal", new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, () -> ModBlockEntities.TURTLE_NORMAL ) );
|
register( "turtle_normal", new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, () -> ModBlockEntities.TURTLE_NORMAL ) );
|
||||||
@ -155,7 +157,7 @@ public final class Registry
|
|||||||
|
|
||||||
private static BlockBehaviour.Properties modemProperties()
|
private static BlockBehaviour.Properties modemProperties()
|
||||||
{
|
{
|
||||||
return FabricBlockSettings.copyOf( Blocks.STONE ).breakByHand( true ).breakByTool( FabricToolTags.PICKAXES ).strength( 1.5f );
|
return FabricBlockSettings.copyOf( Blocks.STONE ).breakByHand( true ).strength( 1.5f );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +303,7 @@ public final class Registry
|
|||||||
{
|
{
|
||||||
public static final EntityType<TurtlePlayer> TURTLE_PLAYER =
|
public static final EntityType<TurtlePlayer> TURTLE_PLAYER =
|
||||||
net.minecraft.core.Registry.register( net.minecraft.core.Registry.ENTITY_TYPE, new ResourceLocation( MOD_ID, "turtle_player" ),
|
net.minecraft.core.Registry.register( net.minecraft.core.Registry.ENTITY_TYPE, new ResourceLocation( MOD_ID, "turtle_player" ),
|
||||||
EntityType.Builder.<TurtlePlayer>createNothing( MobCategory.MISC ).noSave().noSummon().sized( 0, 0 ).build( ComputerCraft.MOD_ID + ":turtle_player" ) );
|
EntityType.Builder.<TurtlePlayer>createNothing( MobCategory.MISC ).noSave().noSummon().sized( 0, 0 ).build( ComputerCraft.MOD_ID + ":turtle_player" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ModContainers
|
public static class ModContainers
|
||||||
|
@ -340,7 +340,7 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput
|
|||||||
@Override
|
@Override
|
||||||
public String getHostString()
|
public String getHostString()
|
||||||
{
|
{
|
||||||
return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), SharedConstants.VERSION_STRING );
|
return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), SharedConstants.getCurrentVersion().getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -15,11 +15,12 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
|||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.fabric.api.network.ClientSidePacketRegistry;
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
||||||
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
||||||
@ -27,6 +28,7 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.level.ServerChunkCache;
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
@ -50,12 +52,8 @@ public final class NetworkHandler
|
|||||||
|
|
||||||
public static void setup()
|
public static void setup()
|
||||||
{
|
{
|
||||||
ServerSidePacketRegistry.INSTANCE.register( ID, NetworkHandler::receive );
|
ServerPlayNetworking.registerGlobalReceiver( ID, NetworkHandler::receive );
|
||||||
if( FabricLoader.getInstance()
|
if( FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT ) ClientHandler.setup();
|
||||||
.getEnvironmentType() == EnvType.CLIENT )
|
|
||||||
{
|
|
||||||
ClientSidePacketRegistry.INSTANCE.register( ID, NetworkHandler::receive );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server messages
|
// Server messages
|
||||||
registerMainThread( 0, ComputerActionServerMessage.class, ComputerActionServerMessage::new );
|
registerMainThread( 0, ComputerActionServerMessage.class, ComputerActionServerMessage::new );
|
||||||
@ -80,18 +78,16 @@ public final class NetworkHandler
|
|||||||
registerMainThread( 20, UploadResultMessage.class, UploadResultMessage::new );
|
registerMainThread( 20, UploadResultMessage.class, UploadResultMessage::new );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void receive( PacketContext context, FriendlyByteBuf buffer )
|
private static void receive( MinecraftServer server, ServerPlayer player, ServerGamePacketListenerImpl handler, FriendlyByteBuf buffer, PacketSender sender )
|
||||||
{
|
{
|
||||||
int type = buffer.readByte();
|
int type = buffer.readByte();
|
||||||
packetReaders.get( type )
|
packetReaders.get( type ).accept( new PacketContext( player, server ), buffer );
|
||||||
.accept( context, buffer );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" )
|
||||||
private static <T> Class<T> getType( Supplier<T> supplier )
|
private static <T> Class<T> getType( Supplier<T> supplier )
|
||||||
{
|
{
|
||||||
return (Class<T>) supplier.get()
|
return (Class<T>) supplier.get().getClass();
|
||||||
.getClass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FriendlyByteBuf encode( NetworkMessage message )
|
private static FriendlyByteBuf encode( NetworkMessage message )
|
||||||
@ -126,23 +122,37 @@ public final class NetworkHandler
|
|||||||
public static void sendToAllTracking( NetworkMessage packet, LevelChunk chunk )
|
public static void sendToAllTracking( NetworkMessage packet, LevelChunk chunk )
|
||||||
{
|
{
|
||||||
Consumer<ServerPlayer> sender = p -> p.connection.send( new ClientboundCustomPayloadPacket( ID, encode( packet ) ) );
|
Consumer<ServerPlayer> sender = p -> p.connection.send( new ClientboundCustomPayloadPacket( ID, encode( packet ) ) );
|
||||||
((ServerChunkCache)chunk.getLevel().getChunkSource()).chunkMap.getPlayers( chunk.getPos(), false ).forEach( sender );
|
((ServerChunkCache) chunk.getLevel().getChunkSource()).chunkMap.getPlayers( chunk.getPos(), false ).forEach( sender );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register packet, and a thread-unsafe handler for it.
|
* Register packet, and a thread-unsafe handler for it.
|
||||||
*
|
*
|
||||||
* @param <T> The type of the packet to send.
|
* @param <T> The type of the packet to send.
|
||||||
* @param type The class of the type of packet to send.
|
* @param type The class of the type of packet to send.
|
||||||
* @param id The identifier for this packet type.
|
* @param id The identifier for this packet type.
|
||||||
* @param decoder The factory for this type of packet.
|
* @param decoder The factory for this type of packet.
|
||||||
*/
|
*/
|
||||||
private static <T extends NetworkMessage> void registerMainThread( int id, Class<T> type, Function<FriendlyByteBuf, T> decoder )
|
private static <T extends NetworkMessage> void registerMainThread( int id, Class<T> type, Function<FriendlyByteBuf, T> decoder )
|
||||||
{
|
{
|
||||||
packetIds.put( type, id );
|
packetIds.put( type, id );
|
||||||
packetReaders.put( id, ( context, buf ) -> {
|
packetReaders.put( id, ( context, buf ) -> {
|
||||||
T result = decoder.apply( buf );
|
T result = decoder.apply( buf );
|
||||||
context.getTaskQueue().execute( () -> result.handle( context ) );
|
context.executor().execute( () -> result.handle( context ) );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ClientHandler
|
||||||
|
{
|
||||||
|
static void setup()
|
||||||
|
{
|
||||||
|
ClientPlayNetworking.registerGlobalReceiver( ID, ClientHandler::receive );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void receive( Minecraft client, ClientPacketListener handler, FriendlyByteBuf buffer, PacketSender responseSender )
|
||||||
|
{
|
||||||
|
int type = buffer.readByte();
|
||||||
|
packetReaders.get( type ).accept( new PacketContext( client.player, client ), buffer );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.network;
|
package dan200.computercraft.shared.network;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.shared.network;
|
||||||
|
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public record PacketContext(Player player, Executor executor)
|
||||||
|
{
|
||||||
|
public Player getPlayer()
|
||||||
|
{
|
||||||
|
return player();
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,7 @@ package dan200.computercraft.shared.network.client;
|
|||||||
import dan200.computercraft.client.ClientTableFormatter;
|
import dan200.computercraft.client.ClientTableFormatter;
|
||||||
import dan200.computercraft.shared.command.text.TableBuilder;
|
import dan200.computercraft.shared.command.text.TableBuilder;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ package dan200.computercraft.shared.network.client;
|
|||||||
|
|
||||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
package dan200.computercraft.shared.network.client;
|
package dan200.computercraft.shared.network.client;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
public class ComputerDeletedClientMessage extends ComputerClientMessage
|
public class ComputerDeletedClientMessage extends ComputerClientMessage
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.network.client;
|
package dan200.computercraft.shared.network.client;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
package dan200.computercraft.shared.network.client;
|
package dan200.computercraft.shared.network.client;
|
||||||
|
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.player.LocalPlayer;
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
package dan200.computercraft.shared.network.client;
|
package dan200.computercraft.shared.network.client;
|
||||||
|
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Registry;
|
import net.minecraft.core.Registry;
|
||||||
|
@ -7,9 +7,9 @@ package dan200.computercraft.shared.network.client;
|
|||||||
|
|
||||||
import dan200.computercraft.client.sound.SpeakerManager;
|
import dan200.computercraft.client.sound.SpeakerManager;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
@ -7,9 +7,9 @@ package dan200.computercraft.shared.network.client;
|
|||||||
|
|
||||||
import dan200.computercraft.client.sound.SpeakerManager;
|
import dan200.computercraft.client.sound.SpeakerManager;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
@ -7,9 +7,9 @@ package dan200.computercraft.shared.network.client;
|
|||||||
|
|
||||||
import dan200.computercraft.client.sound.SpeakerManager;
|
import dan200.computercraft.client.sound.SpeakerManager;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -9,7 +9,7 @@ import dan200.computercraft.client.gui.ComputerScreenBase;
|
|||||||
import dan200.computercraft.client.gui.OptionScreen;
|
import dan200.computercraft.client.gui.OptionScreen;
|
||||||
import dan200.computercraft.shared.computer.upload.UploadResult;
|
import dan200.computercraft.shared.computer.upload.UploadResult;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screens.Screen;
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
@ -7,7 +7,7 @@ package dan200.computercraft.shared.network.server;
|
|||||||
|
|
||||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -9,7 +9,7 @@ import dan200.computercraft.ComputerCraft;
|
|||||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -7,7 +7,7 @@ package dan200.computercraft.shared.network.server;
|
|||||||
|
|
||||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ package dan200.computercraft.shared.network.server;
|
|||||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.InputState;
|
import dan200.computercraft.shared.computer.core.InputState;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -8,7 +8,7 @@ package dan200.computercraft.shared.network.server;
|
|||||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.InputState;
|
import dan200.computercraft.shared.computer.core.InputState;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -7,8 +7,8 @@ package dan200.computercraft.shared.network.server;
|
|||||||
|
|
||||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import dan200.computercraft.shared.util.NBTUtil;
|
import dan200.computercraft.shared.util.NBTUtil;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ package dan200.computercraft.shared.network.server;
|
|||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||||
import dan200.computercraft.shared.network.NetworkMessage;
|
import dan200.computercraft.shared.network.NetworkMessage;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
@ -11,8 +11,8 @@ import dan200.computercraft.shared.computer.core.ServerComputer;
|
|||||||
import dan200.computercraft.shared.computer.upload.FileSlice;
|
import dan200.computercraft.shared.computer.upload.FileSlice;
|
||||||
import dan200.computercraft.shared.computer.upload.FileUpload;
|
import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||||
import dan200.computercraft.shared.network.NetworkHandler;
|
import dan200.computercraft.shared.network.NetworkHandler;
|
||||||
|
import dan200.computercraft.shared.network.PacketContext;
|
||||||
import io.netty.handler.codec.DecoderException;
|
import io.netty.handler.codec.DecoderException;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
|||||||
for( Direction facing : DirectionUtil.FACINGS )
|
for( Direction facing : DirectionUtil.FACINGS )
|
||||||
{
|
{
|
||||||
BlockPos offset = current.relative( facing );
|
BlockPos offset = current.relative( facing );
|
||||||
if( !world.hasChunkAt( offset ) )
|
if( !world.isLoaded( offset ) )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,11 @@ import javax.annotation.Nonnull;
|
|||||||
public class TurtleCraftingTable extends AbstractTurtleUpgrade
|
public class TurtleCraftingTable extends AbstractTurtleUpgrade
|
||||||
{
|
{
|
||||||
@Environment( EnvType.CLIENT )
|
@Environment( EnvType.CLIENT )
|
||||||
private ModelResourceLocation leftModel;
|
private static class Models
|
||||||
@Environment( EnvType.CLIENT )
|
{
|
||||||
private ModelResourceLocation rightModel;
|
private static final ModelResourceLocation leftModel = new ModelResourceLocation( "computercraft:turtle_crafting_table_left", "inventory" );
|
||||||
|
private static final ModelResourceLocation rightModel = new ModelResourceLocation( "computercraft:turtle_crafting_table_right", "inventory" );
|
||||||
|
}
|
||||||
|
|
||||||
public TurtleCraftingTable( ResourceLocation id, ItemStack stack )
|
public TurtleCraftingTable( ResourceLocation id, ItemStack stack )
|
||||||
{
|
{
|
||||||
@ -42,17 +44,6 @@ public class TurtleCraftingTable extends AbstractTurtleUpgrade
|
|||||||
@Environment( EnvType.CLIENT )
|
@Environment( EnvType.CLIENT )
|
||||||
public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side )
|
public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side )
|
||||||
{
|
{
|
||||||
loadModelLocations();
|
return TransformedModel.of( side == TurtleSide.LEFT ? Models.leftModel : Models.rightModel );
|
||||||
return TransformedModel.of( side == TurtleSide.LEFT ? leftModel : rightModel );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Environment( EnvType.CLIENT )
|
|
||||||
private void loadModelLocations()
|
|
||||||
{
|
|
||||||
if( leftModel == null )
|
|
||||||
{
|
|
||||||
leftModel = new ModelResourceLocation( "computercraft:turtle_crafting_table_left", "inventory" );
|
|
||||||
rightModel = new ModelResourceLocation( "computercraft:turtle_crafting_table_right", "inventory" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,16 +61,30 @@ public class TurtleModem extends AbstractTurtleUpgrade
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Environment( EnvType.CLIENT )
|
||||||
|
private class Models
|
||||||
|
{
|
||||||
|
private final ModelResourceLocation leftOffModel = advanced ?
|
||||||
|
new ModelResourceLocation( "computercraft:turtle_modem_advanced_off_left", "inventory" ) :
|
||||||
|
new ModelResourceLocation( "computercraft:turtle_modem_normal_off_left", "inventory" );
|
||||||
|
|
||||||
|
private final ModelResourceLocation rightOffModel = advanced ?
|
||||||
|
new ModelResourceLocation( "computercraft:turtle_modem_advanced_off_right", "inventory" ) :
|
||||||
|
new ModelResourceLocation( "computercraft:turtle_modem_normal_off_right", "inventory" );
|
||||||
|
|
||||||
|
private final ModelResourceLocation leftOnModel = advanced ?
|
||||||
|
new ModelResourceLocation( "computercraft:turtle_modem_advanced_on_left", "inventory" ) :
|
||||||
|
new ModelResourceLocation( "computercraft:turtle_modem_normal_on_left", "inventory" );
|
||||||
|
|
||||||
|
private final ModelResourceLocation rightOnModel = advanced ?
|
||||||
|
new ModelResourceLocation( "computercraft:turtle_modem_advanced_on_right", "inventory" ) :
|
||||||
|
new ModelResourceLocation( "computercraft:turtle_modem_normal_on_right", "inventory" );
|
||||||
|
}
|
||||||
|
|
||||||
private final boolean advanced;
|
private final boolean advanced;
|
||||||
|
|
||||||
@Environment( EnvType.CLIENT )
|
@Environment( EnvType.CLIENT )
|
||||||
private ModelResourceLocation leftOffModel;
|
private Models models;
|
||||||
@Environment( EnvType.CLIENT )
|
|
||||||
private ModelResourceLocation rightOffModel;
|
|
||||||
@Environment( EnvType.CLIENT )
|
|
||||||
private ModelResourceLocation leftOnModel;
|
|
||||||
@Environment( EnvType.CLIENT )
|
|
||||||
private ModelResourceLocation rightOnModel;
|
|
||||||
|
|
||||||
public TurtleModem( ResourceLocation id, ItemStack stack, boolean advanced )
|
public TurtleModem( ResourceLocation id, ItemStack stack, boolean advanced )
|
||||||
{
|
{
|
||||||
@ -96,7 +110,7 @@ public class TurtleModem extends AbstractTurtleUpgrade
|
|||||||
@Environment( EnvType.CLIENT )
|
@Environment( EnvType.CLIENT )
|
||||||
public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side )
|
public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side )
|
||||||
{
|
{
|
||||||
loadModelLocations();
|
if( models == null ) models = new Models();
|
||||||
|
|
||||||
boolean active = false;
|
boolean active = false;
|
||||||
if( turtle != null )
|
if( turtle != null )
|
||||||
@ -106,32 +120,8 @@ public class TurtleModem extends AbstractTurtleUpgrade
|
|||||||
}
|
}
|
||||||
|
|
||||||
return side == TurtleSide.LEFT
|
return side == TurtleSide.LEFT
|
||||||
? TransformedModel.of( active ? leftOnModel : leftOffModel )
|
? TransformedModel.of( active ? models.leftOnModel : models.leftOffModel )
|
||||||
: TransformedModel.of( active ? rightOnModel : rightOffModel );
|
: TransformedModel.of( active ? models.rightOnModel : models.rightOffModel );
|
||||||
}
|
|
||||||
|
|
||||||
// This exists separate from the constructor because we can't use the class ModelResourceLocation on the dedicated
|
|
||||||
// server.
|
|
||||||
@Environment( EnvType.CLIENT )
|
|
||||||
private void loadModelLocations()
|
|
||||||
{
|
|
||||||
if( leftOffModel == null )
|
|
||||||
{
|
|
||||||
if( advanced )
|
|
||||||
{
|
|
||||||
leftOffModel = new ModelResourceLocation( "computercraft:turtle_modem_advanced_off_left", "inventory" );
|
|
||||||
rightOffModel = new ModelResourceLocation( "computercraft:turtle_modem_advanced_off_right", "inventory" );
|
|
||||||
leftOnModel = new ModelResourceLocation( "computercraft:turtle_modem_advanced_on_left", "inventory" );
|
|
||||||
rightOnModel = new ModelResourceLocation( "computercraft:turtle_modem_advanced_on_right", "inventory" );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
leftOffModel = new ModelResourceLocation( "computercraft:turtle_modem_normal_off_left", "inventory" );
|
|
||||||
rightOffModel = new ModelResourceLocation( "computercraft:turtle_modem_normal_off_right", "inventory" );
|
|
||||||
leftOnModel = new ModelResourceLocation( "computercraft:turtle_modem_normal_on_left", "inventory" );
|
|
||||||
rightOnModel = new ModelResourceLocation( "computercraft:turtle_modem_normal_on_right", "inventory" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,9 +26,11 @@ import javax.annotation.Nonnull;
|
|||||||
public class TurtleSpeaker extends AbstractTurtleUpgrade
|
public class TurtleSpeaker extends AbstractTurtleUpgrade
|
||||||
{
|
{
|
||||||
@Environment( EnvType.CLIENT )
|
@Environment( EnvType.CLIENT )
|
||||||
private ModelResourceLocation leftModel;
|
private static class Models
|
||||||
@Environment( EnvType.CLIENT )
|
{
|
||||||
private ModelResourceLocation rightModel;
|
private static ModelResourceLocation leftModel = new ModelResourceLocation( "computercraft:turtle_speaker_upgrade_left", "inventory" );
|
||||||
|
private static ModelResourceLocation rightModel = new ModelResourceLocation( "computercraft:turtle_speaker_upgrade_right", "inventory" );
|
||||||
|
}
|
||||||
|
|
||||||
private static class Peripheral extends UpgradeSpeakerPeripheral
|
private static class Peripheral extends UpgradeSpeakerPeripheral
|
||||||
{
|
{
|
||||||
@ -76,18 +78,7 @@ public class TurtleSpeaker extends AbstractTurtleUpgrade
|
|||||||
@Environment( EnvType.CLIENT )
|
@Environment( EnvType.CLIENT )
|
||||||
public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side )
|
public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side )
|
||||||
{
|
{
|
||||||
loadModelLocations();
|
return TransformedModel.of( side == TurtleSide.LEFT ? Models.leftModel : Models.rightModel );
|
||||||
return TransformedModel.of( side == TurtleSide.LEFT ? leftModel : rightModel );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Environment( EnvType.CLIENT )
|
|
||||||
private void loadModelLocations()
|
|
||||||
{
|
|
||||||
if( leftModel == null )
|
|
||||||
{
|
|
||||||
leftModel = new ModelResourceLocation( "computercraft:turtle_speaker_upgrade_left", "inventory" );
|
|
||||||
rightModel = new ModelResourceLocation( "computercraft:turtle_speaker_upgrade_right", "inventory" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -17,7 +17,7 @@ import dan200.computercraft.core.apis.http.options.Action;
|
|||||||
import dan200.computercraft.core.apis.http.options.AddressRuleConfig;
|
import dan200.computercraft.core.apis.http.options.AddressRuleConfig;
|
||||||
import dan200.computercraft.fabric.mixin.LevelResourceAccess;
|
import dan200.computercraft.fabric.mixin.LevelResourceAccess;
|
||||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||||
import net.fabricmc.loader.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.world.level.storage.LevelResource;
|
import net.minecraft.world.level.storage.LevelResource;
|
||||||
@ -47,7 +47,7 @@ public final class Config
|
|||||||
private static final String serverFileName = "computercraft-server.toml";
|
private static final String serverFileName = "computercraft-server.toml";
|
||||||
|
|
||||||
private static Path serverPath = null;
|
private static Path serverPath = null;
|
||||||
private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve( "computercraft-client.toml" );
|
private static final Path clientPath = FabricLoader.getInstance().getConfigDir().resolve( "computercraft-client.toml" );
|
||||||
|
|
||||||
private Config()
|
private Config()
|
||||||
{
|
{
|
||||||
|
@ -42,27 +42,20 @@ public final class InventoryUtil
|
|||||||
public static Container getInventory( Level world, BlockPos pos, Direction side )
|
public static Container getInventory( Level world, BlockPos pos, Direction side )
|
||||||
{
|
{
|
||||||
// Look for tile with inventory
|
// Look for tile with inventory
|
||||||
int y = pos.getY();
|
BlockEntity tileEntity = world.getBlockEntity( pos );
|
||||||
if( y >= 0 && y < world.getHeight() )
|
if( tileEntity != null )
|
||||||
{
|
{
|
||||||
// Check if block is InventoryProvider
|
Container inventory = getInventory( tileEntity );
|
||||||
BlockState blockState = world.getBlockState( pos );
|
if( inventory != null )
|
||||||
Block block = blockState.getBlock();
|
|
||||||
if( block instanceof WorldlyContainerHolder containerHolder )
|
|
||||||
{
|
{
|
||||||
return containerHolder.getContainer( blockState, world, pos );
|
return inventory;
|
||||||
}
|
}
|
||||||
// Check if block is BlockEntity w/ Inventory
|
}
|
||||||
if( blockState.hasBlockEntity() )
|
|
||||||
{
|
|
||||||
BlockEntity tileEntity = world.getBlockEntity( pos );
|
|
||||||
|
|
||||||
Container inventory = getInventory( tileEntity );
|
BlockState block = world.getBlockState( pos );
|
||||||
if( inventory != null )
|
if( block.getBlock() instanceof WorldlyContainerHolder containerHolder )
|
||||||
{
|
{
|
||||||
return inventory;
|
return containerHolder.getContainer( block, world, pos );
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for entity with inventory
|
// Look for entity with inventory
|
||||||
@ -97,9 +90,9 @@ public final class InventoryUtil
|
|||||||
if( tileEntity instanceof Container )
|
if( tileEntity instanceof Container )
|
||||||
{
|
{
|
||||||
Container inventory = (Container) tileEntity;
|
Container inventory = (Container) tileEntity;
|
||||||
if( inventory instanceof ChestBlockEntity && block instanceof ChestBlock )
|
if( inventory instanceof ChestBlockEntity && block instanceof ChestBlock chestBlock )
|
||||||
{
|
{
|
||||||
return ChestBlock.getContainer( (ChestBlock) block, blockState, world, pos, true );
|
return ChestBlock.getContainer( chestBlock, blockState, world, pos, true );
|
||||||
}
|
}
|
||||||
return inventory;
|
return inventory;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ package dan200.computercraft.shared.util;
|
|||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import net.minecraft.nbt.*;
|
import net.minecraft.nbt.*;
|
||||||
import org.apache.commons.codec.binary.Hex;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -177,7 +176,7 @@ public final class NBTUtil
|
|||||||
DataOutput output = new DataOutputStream( new DigestOutputStream( digest ) );
|
DataOutput output = new DataOutputStream( new DigestOutputStream( digest ) );
|
||||||
NbtIo.write( tag, output );
|
NbtIo.write( tag, output );
|
||||||
byte[] hash = digest.digest();
|
byte[] hash = digest.digest();
|
||||||
return new String( Hex.encodeHex( hash ) );
|
return encodeHex( hash );
|
||||||
}
|
}
|
||||||
catch( NoSuchAlgorithmException | IOException e )
|
catch( NoSuchAlgorithmException | IOException e )
|
||||||
{
|
{
|
||||||
@ -186,6 +185,13 @@ public final class NBTUtil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String encodeHex( byte[] bytes )
|
||||||
|
{
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for ( byte b : bytes ) result.append( String.format( "%02x", b ) );
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private static final class DigestOutputStream extends OutputStream
|
private static final class DigestOutputStream extends OutputStream
|
||||||
{
|
{
|
||||||
private final MessageDigest digest;
|
private final MessageDigest digest;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
View the source code at https://github.com/cc-tweaked/cc-restiched
|
View the source code at https://github.com/cc-tweaked/cc-restitched
|
||||||
View the documentation at https://wiki.computercraft.cc
|
View the documentation at https://wiki.computercraft.cc
|
||||||
Visit the forum at https://forums.computercraft.cc
|
Visit the forum at https://forums.computercraft.cc
|
||||||
You can disable these messages by running "set motd.enable false"
|
You can disable these messages by running "set motd.enable false"
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"MixinBlock",
|
"MixinBlock",
|
||||||
"MixinChunkMap",
|
"MixinChunkMap",
|
||||||
"MixinEntity",
|
"MixinEntity",
|
||||||
"MixinLevel",
|
|
||||||
"MixinMatrix4f",
|
"MixinMatrix4f",
|
||||||
"MixinServerLevel",
|
"MixinServerLevel",
|
||||||
"MixinServerPlayerGameMode"
|
"MixinServerPlayerGameMode"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user