1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-11-21 07:44:49 +00:00

Compare commits

...

18 Commits

Author SHA1 Message Date
Jonathan Coates
7c373c6e06 Merge branch 'mc-1.17.x' into mc-1.18.x 2021-12-11 07:50:18 +00:00
Jonathan Coates
6196aae488 Merge branch 'mc-1.16.x' into mc-1.17.x 2021-12-11 07:49:33 +00:00
Jonathan Coates
92a0ef2b75 Bump CC:T version 2021-12-11 07:37:10 +00:00
Jonathan Coates
57c5d19f95 Update to Forge 1.18.1 2021-12-11 07:31:41 +00:00
Jonathan Coates
1f6e0f287d Ensure the origin monitor is valid too
Blurh, still not sure if this is Correct or anything, but have no clue
what's causing this. Fixes #985. Hopefully.
2021-12-10 13:13:31 +00:00
Jonathan Coates
0e4b7a5a75 Prevent terminal buttons stealing focus
I have shutdown my computer by accident far too many times now.
2021-12-08 23:16:53 +00:00
Jonathan Coates
47ad7a35dc Fix NPE when pulling an event with no type
I assume people have broken coroutine dispatchers - I didn't think it
was possible to queue an actual event with no type.

See cc-tweaked/cc-restitched#31. Will fix it too once merged downstream!
2021-12-08 22:47:21 +00:00
Jonathan Coates
3eab2a9b57 Add support for a zero-copy Lua table
The API is entirely designed for the needs of the speaker right now, so
doesn't do much else.
2021-12-07 18:27:29 +00:00
Jonathan Coates
c4024a4c4c Use an admonition instead 2021-12-02 22:41:58 +00:00
Jonathan Coates
f5fb82cd7d Merge pull request #977 from MCJack123/patch-9
Add package.searchpath
2021-12-02 12:34:07 +00:00
Jonathan Coates
23c17075be save -> saveAdditional
Also add in a janky workabround for handleUpdateTag not being called.
Being an early porter is always fun :D:.
2021-12-02 09:20:06 +00:00
MCJack123
e18ba8a2c2 Add package.searchpath 2021-12-01 18:55:24 -05:00
Jonathan Coates
87988a705b Exclude Jetbrains annotations from testModExtra
testModExtra must /strictly/ be the set of dependencies which are not
present in implementation - there can't be any duplicates.

Yes, it's stupid, but the whole lazyToken("minecraft_classpath") thing
wasn't really built with this in mind, so not much we can do :)
2021-12-01 20:40:46 +00:00
Jonathan Coates
422bfdb60d Add 1.18 and remove 1.15 from the issue template
No, we're not pushing it to Curse yet, but while I remember.
2021-12-01 20:24:37 +00:00
Jonathan Coates
1851ed31cd Release keys when opening the offhand pocket computer screen
Opening a screen KeyBinding.releaseAll(), which forces all inputs to be
considered released. However, our init() function then calls
grabMouse(), which calls Keybinding.setAll(), undoing this work.

The fix we're going for here is to call releaseAll() one more time[^1]
after grabbing the mouse. I think if this becomes any more of a problem,
we should roll our own grabMouse which _doesn't_ implement any specific
behaviour.

Fixes #975

[^1]: Obvious problem here is that we do minecraft.screen=xyz rather
      than setScreen. We need to - otherwise we'd just hit a stack
      overflow - but it's not great.
2021-12-01 20:09:38 +00:00
Jonathan Coates
179da1d8cf Update to MC 1.18
- Build fails right now due to module issues, so this won't be pushed
   to GitHub.
 - Monitors render transparently when loaded into the world. I don't
   think this is a 1.17 bug, so not sure what's going on here!
2021-11-30 22:48:38 +00:00
Jonathan Coates
92fd93c0e0 Merge branch 'mc-1.16.x' into mc-1.17.x 2021-11-30 22:37:07 +00:00
Jonathan Coates
3929dba4a5 Only send update packets on the TEs which need it
More bits of #658
2021-11-30 22:01:09 +00:00
89 changed files with 783 additions and 242 deletions

View File

@@ -8,9 +8,9 @@ body:
label: Minecraft Version label: Minecraft Version
description: What version of Minecraft are you using? description: What version of Minecraft are you using?
options: options:
- 1.15.x
- 1.16.x - 1.16.x
- 1.17.x - 1.17.x
- 1.18.x
validations: validations:
required: true required: true
- type: input - type: input

View File

@@ -5,7 +5,7 @@ buildscript {
maven { url = 'https://maven.parchmentmc.org' } maven { url = 'https://maven.parchmentmc.org' }
} }
dependencies { dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:5.1.24' classpath 'net.minecraftforge.gradle:ForgeGradle:5.1.+'
classpath 'org.parchmentmc:librarian:1.+' classpath 'org.parchmentmc:librarian:1.+'
} }
} }
@@ -29,7 +29,7 @@ version = mod_version
group = "org.squiddev" group = "org.squiddev"
archivesBaseName = "cc-tweaked-${mc_version}" archivesBaseName = "cc-tweaked-${mc_version}"
def javaVersion = JavaLanguageVersion.of(16) def javaVersion = JavaLanguageVersion.of(17)
java { java {
toolchain { toolchain {
languageVersion = javaVersion languageVersion = javaVersion
@@ -47,6 +47,7 @@ tasks.withType(JavaExec).configureEach {
sourceSets { sourceSets {
main.java { main.java {
exclude 'dan200/computercraft/shared/integration/jei/**'
exclude 'dan200/computercraft/shared/integration/morered/**' exclude 'dan200/computercraft/shared/integration/morered/**'
} }
main.resources { main.resources {
@@ -122,7 +123,8 @@ minecraft {
} }
} }
mappings channel: 'parchment', version: "${mapping_version}-${mc_version}" // mappings channel: 'parchment', version: "${mapping_version}-${mc_version}"
mappings channel: 'official', version: mc_version
accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg') accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg') accessTransformer file('src/testMod/resources/META-INF/accesstransformer.cfg')
@@ -151,10 +153,8 @@ dependencies {
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}" minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
compileOnly fg.deobf("mezz.jei:jei-1.17.1:8.0.0.14:api") // compileOnly fg.deobf("mezz.jei:jei-1.17.1:8.0.0.14:api")
// compileOnly fg.deobf("commoble.morered:morered-1.16.5:2.1.1.0") // runtimeOnly fg.deobf("mezz.jei:jei-1.17.1:8.0.0.14")
runtimeOnly fg.deobf("mezz.jei:jei-1.17.1:8.0.0.14")
shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT' shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT'
@@ -166,7 +166,9 @@ dependencies {
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
testModImplementation sourceSets.main.output testModImplementation sourceSets.main.output
testModExtra 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.21' testModExtra('org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.0') {
exclude group: "org.jetbrains", module: "annotations"
}
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.2' cctJavadoc 'cc.tweaked:cct-javadoc:1.4.2'
} }

View File

@@ -1,10 +1,10 @@
org.gradle.jvmargs=-Xmx3G org.gradle.jvmargs=-Xmx3G
# Mod properties # Mod properties
mod_version=1.99.0 mod_version=1.99.1
# Minecraft properties (update mods.toml when changing) # Minecraft properties (update mods.toml when changing)
mc_version=1.17.1 mc_version=1.18.1
mapping_version=2021.09.05 mapping_version=2021.09.05
forge_version=37.0.85 forge_version=39.0.0
# NO SERIOUSLY, UPDATE mods.toml WHEN CHANGING # NO SERIOUSLY, UPDATE mods.toml WHEN CHANGING

View File

@@ -38,7 +38,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; import net.minecraftforge.server.ServerLifecycleHooks;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.io.File; import java.io.File;

View File

@@ -183,6 +183,24 @@ public interface IArguments
return (Map<?, ?>) value; return (Map<?, ?>) value;
} }
/**
* Get an argument as a table in an unsafe manner.
*
* Classes implementing this interface may choose to implement a more optimised version which does not copy the
* table, instead returning a wrapper version, making it more efficient. However, the caller must guarantee that
* they do not access off the computer thread (and so should not be used with main-thread functions) or once the
* function call has finished (for instance, in callbacks).
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not a table.
*/
@Nonnull
default LuaTable<?, ?> getTableUnsafe( int index ) throws LuaException
{
return new ObjectLuaTable( getTable( index ) );
}
/** /**
* Get an argument as a double. * Get an argument as a double.
* *
@@ -314,6 +332,27 @@ public interface IArguments
return Optional.of( (Map<?, ?>) value ); return Optional.of( (Map<?, ?>) value );
} }
/**
* Get an argument as a table in an unsafe manner.
*
* Classes implementing this interface may choose to implement a more optimised version which does not copy the
* table, instead returning a wrapper version, making it more efficient. However, the caller must guarantee that
* they do not access off the computer thread (and so should not be used with main-thread functions) or once the
* function call has finished (for instance, in callbacks).
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a table.
*/
@Nonnull
default Optional<LuaTable<?, ?>> optTableUnsafe( int index ) throws LuaException
{
Object value = get( index );
if( value == null ) return Optional.empty();
if( !(value instanceof Map) ) throw LuaValues.badArgumentOf( index, "map", value );
return Optional.of( new ObjectLuaTable( (Map<?, ?>) value ) );
}
/** /**
* Get an argument as a double. * Get an argument as a double.
* *
@@ -404,4 +443,13 @@ public interface IArguments
{ {
return optTable( index ).orElse( def ); return optTable( index ).orElse( def );
} }
/**
* This is called when the current function finishes, before any main thread tasks have run.
*
* Called when the current function returns, and so some values are no longer guaranteed to be safe to access.
*/
default void releaseImmediate()
{
}
} }

View File

@@ -51,8 +51,17 @@ public @interface LuaFunction
* Run this function on the main server thread. This should be specified for any method which interacts with * Run this function on the main server thread. This should be specified for any method which interacts with
* Minecraft in a thread-unsafe manner. * Minecraft in a thread-unsafe manner.
* *
* @return Whether this functi * @return Whether this function should be run on the main thread.
* @see ILuaContext#issueMainThreadTask(ILuaTask) * @see ILuaContext#issueMainThreadTask(ILuaTask)
*/ */
boolean mainThread() default false; boolean mainThread() default false;
/**
* Allow using "unsafe" arguments, such {@link IArguments#getTableUnsafe(int)}.
*
* This is incompatible with {@link #mainThread()}.
*
* @return Whether this function supports unsafe arguments.
*/
boolean unsafe() default false;
} }

View File

@@ -0,0 +1,114 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nonnull;
import java.util.Map;
import static dan200.computercraft.api.lua.LuaValues.*;
public interface LuaTable<K, V> extends Map<K, V>
{
/**
* Compute the length of the array part of this table.
*
* @return This table's length.
*/
default int length()
{
int size = 0;
while( containsKey( (double) (size + 1) ) ) size++;
return size;
}
/**
* Get an array entry as an integer.
*
* @param index The index in the table, starting at 1.
* @return The table's value.
* @throws LuaException If the value is not an integer.
*/
default long getLong( int index ) throws LuaException
{
Object value = get( (double) index );
if( !(value instanceof Number) ) throw badTableItem( index, "number", getType( value ) );
Number number = (Number) value;
double asDouble = number.doubleValue();
if( !Double.isFinite( asDouble ) ) throw badTableItem( index, "number", getNumericType( asDouble ) );
return number.longValue();
}
/**
* Get a table entry as an integer.
*
* @param key The name of the field in the table.
* @return The table's value.
* @throws LuaException If the value is not an integer.
*/
default long getLong( String key ) throws LuaException
{
Object value = get( key );
if( !(value instanceof Number) ) throw badField( key, "number", getType( value ) );
Number number = (Number) value;
double asDouble = number.doubleValue();
if( !Double.isFinite( asDouble ) ) throw badField( key, "number", getNumericType( asDouble ) );
return number.longValue();
}
/**
* Get an array entry as an integer.
*
* @param index The index in the table, starting at 1.
* @return The table's value.
* @throws LuaException If the value is not an integer.
*/
default int getInt( int index ) throws LuaException
{
return (int) getLong( index );
}
/**
* Get a table entry as an integer.
*
* @param key The name of the field in the table.
* @return The table's value.
* @throws LuaException If the value is not an integer.
*/
default int getInt( String key ) throws LuaException
{
return (int) getLong( key );
}
@Nullable
@Override
default V put( K o, V o2 )
{
throw new UnsupportedOperationException( "Cannot modify LuaTable" );
}
@Override
default V remove( Object o )
{
throw new UnsupportedOperationException( "Cannot modify LuaTable" );
}
@Override
default void putAll( @Nonnull Map<? extends K, ? extends V> map )
{
throw new UnsupportedOperationException( "Cannot modify LuaTable" );
}
@Override
default void clear()
{
throw new UnsupportedOperationException( "Cannot modify LuaTable" );
}
}

View File

@@ -102,6 +102,34 @@ public final class LuaValues
return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" ); return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" );
} }
/**
* Construct a table item exception, from an expected and actual type.
*
* @param index The index into the table, starting from 1.
* @param expected The expected type for this table item.
* @param actual The provided type for this table item.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badTableItem( int index, @Nonnull String expected, @Nonnull String actual )
{
return new LuaException( "table item #" + index + " is not " + expected + " (got " + actual + ")" );
}
/**
* Construct a field exception, from an expected and actual type.
*
* @param key The name of the field.
* @param expected The expected type for this table item.
* @param actual The provided type for this table item.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badField( String key, @Nonnull String expected, @Nonnull String actual )
{
return new LuaException( "field " + key + " is not " + expected + " (got " + actual + ")" );
}
/** /**
* Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}. * Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}.
* *

View File

@@ -98,7 +98,10 @@ public final class MethodResult
{ {
Objects.requireNonNull( callback, "callback cannot be null" ); Objects.requireNonNull( callback, "callback cannot be null" );
return new MethodResult( new Object[] { filter }, results -> { return new MethodResult( new Object[] { filter }, results -> {
if( results.length >= 1 && results[0].equals( "terminate" ) ) throw new LuaException( "Terminated", 0 ); if( results.length >= 1 && Objects.equals( results[0], "terminate" ) )
{
throw new LuaException( "Terminated", 0 );
}
return callback.resume( results ); return callback.resume( results );
} ); } );
} }

View File

@@ -5,10 +5,12 @@
*/ */
package dan200.computercraft.api.lua; package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
/** /**
* An implementation of {@link IArguments} which wraps an array of {@link Object}. * An implementation of {@link IArguments} which wraps an array of {@link Object}.
@@ -16,6 +18,8 @@ import java.util.Objects;
public final class ObjectArguments implements IArguments public final class ObjectArguments implements IArguments
{ {
private static final IArguments EMPTY = new ObjectArguments(); private static final IArguments EMPTY = new ObjectArguments();
private boolean released = false;
private final List<Object> args; private final List<Object> args;
@Deprecated @Deprecated
@@ -63,4 +67,34 @@ public final class ObjectArguments implements IArguments
{ {
return args.toArray(); return args.toArray();
} }
@Nonnull
@Override
public LuaTable<?, ?> getTableUnsafe( int index ) throws LuaException
{
if( released )
{
throw new IllegalStateException( "Cannot use getTableUnsafe after IArguments has been released" );
}
return IArguments.super.getTableUnsafe( index );
}
@Nonnull
@Override
public Optional<LuaTable<?, ?>> optTableUnsafe( int index ) throws LuaException
{
if( released )
{
throw new IllegalStateException( "Cannot use optTableUnsafe after IArguments has been released" );
}
return IArguments.super.optTableUnsafe( index );
}
@Override
public void releaseImmediate()
{
released = true;
}
} }

View File

@@ -0,0 +1,73 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
public class ObjectLuaTable implements LuaTable<Object, Object>
{
private final Map<Object, Object> map;
public ObjectLuaTable( Map<?, ?> map )
{
this.map = Collections.unmodifiableMap( map );
}
@Override
public int size()
{
return map.size();
}
@Override
public boolean isEmpty()
{
return map.isEmpty();
}
@Override
public boolean containsKey( Object o )
{
return map.containsKey( o );
}
@Override
public boolean containsValue( Object o )
{
return map.containsKey( o );
}
@Override
public Object get( Object o )
{
return map.get( o );
}
@Nonnull
@Override
public Set<Object> keySet()
{
return map.keySet();
}
@Nonnull
@Override
public Collection<Object> values()
{
return map.values();
}
@Nonnull
@Override
public Set<Entry<Object, Object>> entrySet()
{
return map.entrySet();
}
}

View File

@@ -32,7 +32,7 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ColorHandlerEvent; import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.client.event.EntityRenderersEvent; import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ForgeModelBakery;
import net.minecraftforge.client.model.ModelLoaderRegistry; import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
@@ -76,7 +76,7 @@ public final class ClientRegistry
ModelLoaderRegistry.registerLoader( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ), TurtleModelLoader.INSTANCE ); ModelLoaderRegistry.registerLoader( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ), TurtleModelLoader.INSTANCE );
for( String model : EXTRA_MODELS ) for( String model : EXTRA_MODELS )
{ {
ModelLoader.addSpecialModel( new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ) ); ForgeModelBakery.addSpecialModel( new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ) );
} }
} }

View File

@@ -8,6 +8,7 @@ package dan200.computercraft.client.gui;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.ComputerSidebar; import dan200.computercraft.client.gui.widgets.ComputerSidebar;
import dan200.computercraft.client.gui.widgets.DynamicImageButton;
import dan200.computercraft.client.gui.widgets.WidgetTerminal; import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
@@ -102,6 +103,16 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
renderTooltip( stack, mouseX, mouseY ); renderTooltip( stack, mouseX, mouseY );
} }
@Override
public boolean mouseClicked( double x, double y, int button )
{
boolean changed = super.mouseClicked( x, y, button );
// Clicking the terminate/shutdown button steals focus, which means then pressing "enter" will click the button
// again. Restore the focus to the terminal in these cases.
if( getFocused() instanceof DynamicImageButton ) setFocused( terminal );
return changed;
}
@Override @Override
public final boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) public final boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{ {

View File

@@ -10,6 +10,7 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal; import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.MenuAccess; import net.minecraft.client.gui.screens.inventory.MenuAccess;
@@ -44,8 +45,11 @@ public class NoTermComputerScreen<T extends ContainerComputerBase> extends Scree
protected void init() protected void init()
{ {
passEvents = true; // Pass mouse vents through to the game's mouse handler. passEvents = true; // Pass mouse vents through to the game's mouse handler.
// First ensure we're still grabbing the mouse, so the user can look around. Then reset bits of state that
// grabbing unsets.
minecraft.mouseHandler.grabMouse(); minecraft.mouseHandler.grabMouse();
minecraft.screen = this; minecraft.screen = this;
KeyMapping.releaseAll();
super.init(); super.init();
minecraft.keyboardHandler.setSendRepeatsToGui( true ); minecraft.keyboardHandler.setSendRepeatsToGui( true );

View File

@@ -71,12 +71,12 @@ public class DynamicImageButton extends Button
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();
int yTex = yTexStart; int yTex = yTexStart;
if( isHovered() ) yTex += yDiffTex; if( isHoveredOrFocused() ) yTex += yDiffTex;
blit( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight ); blit( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight );
RenderSystem.enableDepthTest(); RenderSystem.enableDepthTest();
if( isHovered() ) renderToolTip( stack, mouseX, mouseY ); if( isHovered ) renderToolTip( stack, mouseX, mouseY );
} }
@Nonnull @Nonnull

View File

@@ -45,8 +45,8 @@ public final class CableHighlightRenderer
{ {
BlockHitResult hit = event.getTarget(); BlockHitResult hit = event.getTarget();
BlockPos pos = hit.getBlockPos(); BlockPos pos = hit.getBlockPos();
Level world = event.getInfo().getEntity().getCommandSenderWorld(); Level world = event.getCamera().getEntity().getCommandSenderWorld();
Camera info = event.getInfo(); Camera info = event.getCamera();
BlockState state = world.getBlockState( pos ); BlockState state = world.getBlockState( pos );
@@ -67,9 +67,9 @@ public final class CableHighlightRenderer
double yOffset = pos.getY() - cameraPos.y(); double yOffset = pos.getY() - cameraPos.y();
double zOffset = pos.getZ() - cameraPos.z(); double zOffset = pos.getZ() - cameraPos.z();
VertexConsumer buffer = event.getBuffers().getBuffer( RenderType.lines() ); VertexConsumer buffer = event.getMultiBufferSource().getBuffer( RenderType.lines() );
Matrix4f matrix4f = event.getMatrix().last().pose(); Matrix4f matrix4f = event.getPoseStack().last().pose();
Matrix3f normal = event.getMatrix().last().normal(); Matrix3f normal = event.getPoseStack().last().normal();
// TODO: Can we just accesstransformer out LevelRenderer.renderShape? // TODO: Can we just accesstransformer out LevelRenderer.renderShape?
shape.forAllEdges( ( x1, y1, z1, x2, y2, z2 ) -> { shape.forAllEdges( ( x1, y1, z1, x2, y2, z2 ) -> {
float xDelta = (float) (x2 - x1); float xDelta = (float) (x2 - x1);

View File

@@ -48,7 +48,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
event.setCanceled( true ); event.setCanceled( true );
INSTANCE.renderItemFirstPerson( INSTANCE.renderItemFirstPerson(
event.getMatrixStack(), event.getBuffers(), event.getLight(), event.getPoseStack(), event.getMultiBufferSource(), event.getPackedLight(),
event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack()
); );
} }

View File

@@ -45,7 +45,7 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
event.setCanceled( true ); event.setCanceled( true );
INSTANCE.renderItemFirstPerson( INSTANCE.renderItemFirstPerson(
event.getMatrixStack(), event.getBuffers(), event.getLight(), event.getPoseStack(), event.getMultiBufferSource(), event.getPackedLight(),
event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack()
); );
} }
@@ -63,11 +63,11 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
@SubscribeEvent @SubscribeEvent
public static void onRenderInFrame( RenderItemInFrameEvent event ) public static void onRenderInFrame( RenderItemInFrameEvent event )
{ {
ItemStack stack = event.getItem(); ItemStack stack = event.getItemStack();
if( !(stack.getItem() instanceof ItemPrintout) ) return; if( !(stack.getItem() instanceof ItemPrintout) ) return;
event.setCanceled( true ); event.setCanceled( true );
PoseStack transform = event.getMatrix(); PoseStack transform = event.getPoseStack();
// Move a little bit forward to ensure we're not clipping with the frame // Move a little bit forward to ensure we're not clipping with the frame
transform.translate( 0.0f, 0.0f, -0.001f ); transform.translate( 0.0f, 0.0f, -0.001f );
@@ -75,8 +75,8 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
transform.scale( 0.95f, 0.95f, -0.95f ); transform.scale( 0.95f, 0.95f, -0.95f );
transform.translate( -0.5f, -0.5f, 0.0f ); transform.translate( -0.5f, -0.5f, 0.0f );
int light = event.getEntityItemFrame().getType() == EntityType.GLOW_ITEM_FRAME ? 0xf000d2 : event.getLight(); // See getLightVal. int light = event.getItemFrameEntity().getType() == EntityType.GLOW_ITEM_FRAME ? 0xf000d2 : event.getPackedLight(); // See getLightVal.
drawPrintout( transform, event.getBuffers(), stack, light ); drawPrintout( transform, event.getMultiBufferSource(), stack, light );
} }
private static void drawPrintout( PoseStack transform, MultiBufferSource render, ItemStack stack, int light ) private static void drawPrintout( PoseStack transform, MultiBufferSource render, ItemStack stack, int light )

View File

@@ -41,9 +41,9 @@ public final class MonitorHighlightRenderer
public static void drawHighlight( DrawSelectionEvent.HighlightBlock event ) public static void drawHighlight( DrawSelectionEvent.HighlightBlock event )
{ {
// Preserve normal behaviour when crouching. // Preserve normal behaviour when crouching.
if( event.getInfo().getEntity().isCrouching() ) return; if( event.getCamera().getEntity().isCrouching() ) return;
Level world = event.getInfo().getEntity().getCommandSenderWorld(); Level world = event.getCamera().getEntity().getCommandSenderWorld();
BlockPos pos = event.getTarget().getBlockPos(); BlockPos pos = event.getTarget().getBlockPos();
BlockEntity tile = world.getBlockEntity( pos ); BlockEntity tile = world.getBlockEntity( pos );
@@ -60,13 +60,13 @@ public final class MonitorHighlightRenderer
if( monitor.getYIndex() != 0 ) faces.remove( monitor.getDown().getOpposite() ); if( monitor.getYIndex() != 0 ) faces.remove( monitor.getDown().getOpposite() );
if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() ); if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() );
PoseStack transformStack = event.getMatrix(); PoseStack transformStack = event.getPoseStack();
Vec3 cameraPos = event.getInfo().getPosition(); Vec3 cameraPos = event.getCamera().getPosition();
transformStack.pushPose(); transformStack.pushPose();
transformStack.translate( pos.getX() - cameraPos.x(), pos.getY() - cameraPos.y(), pos.getZ() - cameraPos.z() ); transformStack.translate( pos.getX() - cameraPos.x(), pos.getY() - cameraPos.y(), pos.getZ() - cameraPos.z() );
// I wish I could think of a better way to do this // I wish I could think of a better way to do this
VertexConsumer buffer = event.getBuffers().getBuffer( RenderType.lines() ); VertexConsumer buffer = event.getMultiBufferSource().getBuffer( RenderType.lines() );
Matrix4f transform = transformStack.last().pose(); Matrix4f transform = transformStack.last().pose();
Matrix3f normal = transformStack.last().normal(); Matrix3f normal = transformStack.last().normal();
if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, transform, normal, 0, 0, 0, UP ); if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, transform, normal, 0, 0, 0, UP );

View File

@@ -130,8 +130,6 @@ public final class Generator<T>
private void addMethod( List<NamedMethod<T>> methods, Method method, LuaFunction annotation, PeripheralType genericType, T instance ) private void addMethod( List<NamedMethod<T>> methods, Method method, LuaFunction annotation, PeripheralType genericType, T instance )
{ {
if( annotation.mainThread() ) instance = wrap.apply( instance );
String[] names = annotation.value(); String[] names = annotation.value();
boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread(); boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread();
if( names.length == 0 ) if( names.length == 0 )
@@ -183,6 +181,13 @@ public final class Generator<T>
} }
} }
LuaFunction annotation = method.getAnnotation( LuaFunction.class );
if( annotation.unsafe() && annotation.mainThread() )
{
ComputerCraft.log.error( "Lua Method {} cannot use unsafe and mainThread", name );
return Optional.empty();
}
// We have some rather ugly handling of static methods in both here and the main generate function. Static methods // We have some rather ugly handling of static methods in both here and the main generate function. Static methods
// only come from generic sources, so this should be safe. // only come from generic sources, so this should be safe.
Class<?> target = Modifier.isStatic( modifiers ) ? method.getParameterTypes()[0] : method.getDeclaringClass(); Class<?> target = Modifier.isStatic( modifiers ) ? method.getParameterTypes()[0] : method.getDeclaringClass();
@@ -190,11 +195,13 @@ public final class Generator<T>
try try
{ {
String className = method.getDeclaringClass().getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement(); String className = method.getDeclaringClass().getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement();
byte[] bytes = generate( className, target, method ); byte[] bytes = generate( className, target, method, annotation.unsafe() );
if( bytes == null ) return Optional.empty(); if( bytes == null ) return Optional.empty();
Class<?> klass = DeclaringClassLoader.INSTANCE.define( className, bytes, method.getDeclaringClass().getProtectionDomain() ); Class<?> klass = DeclaringClassLoader.INSTANCE.define( className, bytes, method.getDeclaringClass().getProtectionDomain() );
return Optional.of( klass.asSubclass( base ).getDeclaredConstructor().newInstance() );
T instance = klass.asSubclass( base ).getDeclaredConstructor().newInstance();
return Optional.of( annotation.mainThread() ? wrap.apply( instance ) : instance );
} }
catch( ReflectiveOperationException | ClassFormatError | RuntimeException e ) catch( ReflectiveOperationException | ClassFormatError | RuntimeException e )
{ {
@@ -205,7 +212,7 @@ public final class Generator<T>
} }
@Nullable @Nullable
private byte[] generate( String className, Class<?> target, Method method ) private byte[] generate( String className, Class<?> target, Method method, boolean unsafe )
{ {
String internalName = className.replace( ".", "/" ); String internalName = className.replace( ".", "/" );
@@ -238,7 +245,7 @@ public final class Generator<T>
int argIndex = 0; int argIndex = 0;
for( java.lang.reflect.Type genericArg : method.getGenericParameterTypes() ) for( java.lang.reflect.Type genericArg : method.getGenericParameterTypes() )
{ {
Boolean loadedArg = loadArg( mw, target, method, genericArg, argIndex ); Boolean loadedArg = loadArg( mw, target, method, unsafe, genericArg, argIndex );
if( loadedArg == null ) return null; if( loadedArg == null ) return null;
if( loadedArg ) argIndex++; if( loadedArg ) argIndex++;
} }
@@ -285,7 +292,7 @@ public final class Generator<T>
return cw.toByteArray(); return cw.toByteArray();
} }
private Boolean loadArg( MethodVisitor mw, Class<?> target, Method method, java.lang.reflect.Type genericArg, int argIndex ) private Boolean loadArg( MethodVisitor mw, Class<?> target, Method method, boolean unsafe, java.lang.reflect.Type genericArg, int argIndex )
{ {
if( genericArg == target ) if( genericArg == target )
{ {
@@ -324,7 +331,7 @@ public final class Generator<T>
return true; return true;
} }
String name = Reflect.getLuaName( Primitives.unwrap( klass ) ); String name = Reflect.getLuaName( Primitives.unwrap( klass ), unsafe );
if( name != null ) if( name != null )
{ {
mw.visitVarInsn( ALOAD, 2 + context.size() ); mw.visitVarInsn( ALOAD, 2 + context.size() );
@@ -344,7 +351,7 @@ public final class Generator<T>
return true; return true;
} }
String name = arg == Object.class ? "" : Reflect.getLuaName( arg ); String name = arg == Object.class ? "" : Reflect.getLuaName( arg, unsafe );
if( name != null ) if( name != null )
{ {
if( Reflect.getRawType( method, genericArg, false ) == null ) return null; if( Reflect.getRawType( method, genericArg, false ) == null ) return null;

View File

@@ -6,6 +6,7 @@
package dan200.computercraft.core.asm; package dan200.computercraft.core.asm;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.LuaTable;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -25,7 +26,7 @@ final class Reflect
} }
@Nullable @Nullable
static String getLuaName( Class<?> klass ) static String getLuaName( Class<?> klass, boolean unsafe )
{ {
if( klass.isPrimitive() ) if( klass.isPrimitive() )
{ {
@@ -39,6 +40,7 @@ final class Reflect
if( klass == Map.class ) return "Table"; if( klass == Map.class ) return "Table";
if( klass == String.class ) return "String"; if( klass == String.class ) return "String";
if( klass == ByteBuffer.class ) return "Bytes"; if( klass == ByteBuffer.class ) return "Bytes";
if( klass == LuaTable.class && unsafe ) return "TableUnsafe";
} }
return null; return null;

View File

@@ -59,6 +59,10 @@ class BasicFunction extends VarArgFunction
} }
throw new LuaError( "Java Exception Thrown: " + t, 0 ); throw new LuaError( "Java Exception Thrown: " + t, 0 );
} }
finally
{
arguments.releaseImmediate();
}
if( results.getCallback() != null ) if( results.getCallback() != null )
{ {

View File

@@ -15,6 +15,7 @@ import dan200.computercraft.core.tracking.Tracking;
import dan200.computercraft.core.tracking.TrackingField; import dan200.computercraft.core.tracking.TrackingField;
import dan200.computercraft.shared.util.ThreadUtils; import dan200.computercraft.shared.util.ThreadUtils;
import org.squiddev.cobalt.*; import org.squiddev.cobalt.*;
import org.squiddev.cobalt.LuaTable;
import org.squiddev.cobalt.compiler.CompileException; import org.squiddev.cobalt.compiler.CompileException;
import org.squiddev.cobalt.compiler.LoadState; import org.squiddev.cobalt.compiler.LoadState;
import org.squiddev.cobalt.debug.DebugFrame; import org.squiddev.cobalt.debug.DebugFrame;

View File

@@ -69,6 +69,10 @@ class ResultInterpreterFunction extends ResumableVarArgFunction<ResultInterprete
} }
throw new LuaError( "Java Exception Thrown: " + t, 0 ); throw new LuaError( "Java Exception Thrown: " + t, 0 );
} }
finally
{
arguments.releaseImmediate();
}
ILuaCallback callback = results.getCallback(); ILuaCallback callback = results.getCallback();
Varargs ret = machine.toValues( results.getResult() ); Varargs ret = machine.toValues( results.getResult() );

View File

@@ -0,0 +1,141 @@
/*
* 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.core.lua;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaValues;
import org.squiddev.cobalt.*;
import javax.annotation.Nonnull;
import java.util.*;
import static dan200.computercraft.api.lua.LuaValues.badTableItem;
import static dan200.computercraft.api.lua.LuaValues.getNumericType;
class TableImpl implements dan200.computercraft.api.lua.LuaTable<Object, Object>
{
private final VarargArguments arguments;
private final LuaTable table;
private Map<Object, Object> backingMap;
TableImpl( VarargArguments arguments, LuaTable table )
{
this.arguments = arguments;
this.table = table;
}
@Override
public int size()
{
checkValid();
try
{
return table.keyCount();
}
catch( LuaError e )
{
throw new IllegalStateException( e );
}
}
@Override
public int length()
{
return table.length();
}
@Override
public long getLong( int index ) throws LuaException
{
LuaValue value = table.rawget( index );
if( !(value instanceof LuaNumber) ) throw LuaValues.badTableItem( index, "number", value.typeName() );
if( value instanceof LuaInteger ) return value.toInteger();
double number = value.toDouble();
if( !Double.isFinite( number ) ) throw badTableItem( index, "number", getNumericType( number ) );
return (long) number;
}
@Override
public boolean isEmpty()
{
checkValid();
try
{
return table.next( Constants.NIL ).first().isNil();
}
catch( LuaError e )
{
throw new IllegalStateException( e );
}
}
@Nonnull
private LuaValue getImpl( Object o )
{
checkValid();
if( o instanceof String ) return table.rawget( (String) o );
if( o instanceof Integer ) return table.rawget( (Integer) o );
return Constants.NIL;
}
@Override
public boolean containsKey( Object o )
{
return !getImpl( o ).isNil();
}
@Override
public Object get( Object o )
{
return CobaltLuaMachine.toObject( getImpl( o ), null );
}
@Nonnull
private Map<Object, Object> getBackingMap()
{
checkValid();
if( backingMap != null ) return backingMap;
return backingMap = Collections.unmodifiableMap(
Objects.requireNonNull( (Map<?, ?>) CobaltLuaMachine.toObject( table, null ) )
);
}
@Override
public boolean containsValue( Object o )
{
return getBackingMap().containsKey( o );
}
@Nonnull
@Override
public Set<Object> keySet()
{
return getBackingMap().keySet();
}
@Nonnull
@Override
public Collection<Object> values()
{
return getBackingMap().values();
}
@Nonnull
@Override
public Set<Entry<Object, Object>> entrySet()
{
return getBackingMap().entrySet();
}
private void checkValid()
{
if( arguments.released )
{
throw new IllegalStateException( "Cannot use LuaTable after IArguments has been released" );
}
}
}

View File

@@ -19,6 +19,7 @@ class VarargArguments implements IArguments
{ {
static final IArguments EMPTY = new VarargArguments( Constants.NONE ); static final IArguments EMPTY = new VarargArguments( Constants.NONE );
boolean released;
private final Varargs varargs; private final Varargs varargs;
private Object[] cache; private Object[] cache;
@@ -98,4 +99,39 @@ class VarargArguments implements IArguments
LuaString str = ((LuaBaseString) value).strvalue(); LuaString str = ((LuaBaseString) value).strvalue();
return Optional.of( ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer() ); return Optional.of( ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer() );
} }
@Nonnull
@Override
public dan200.computercraft.api.lua.LuaTable<?, ?> getTableUnsafe( int index ) throws LuaException
{
if( released )
{
throw new IllegalStateException( "Cannot use getTableUnsafe after IArguments has been released" );
}
LuaValue value = varargs.arg( index + 1 );
if( !(value instanceof LuaTable) ) throw LuaValues.badArgument( index, "table", value.typeName() );
return new TableImpl( this, (LuaTable) value );
}
@Nonnull
@Override
public Optional<dan200.computercraft.api.lua.LuaTable<?, ?>> optTableUnsafe( int index ) throws LuaException
{
if( released )
{
throw new IllegalStateException( "Cannot use optTableUnsafe after IArguments has been released" );
}
LuaValue value = varargs.arg( index + 1 );
if( value.isNil() ) return Optional.empty();
if( !(value instanceof LuaTable) ) throw LuaValues.badArgument( index, "table", value.typeName() );
return Optional.of( new TableImpl( this, (LuaTable) value ) );
}
@Override
public void releaseImmediate()
{
released = true;
}
} }

View File

@@ -26,7 +26,7 @@ import net.minecraft.world.level.storage.loot.predicates.AlternativeLootItemCond
import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition; import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition;
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraftforge.fmllegacy.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;

View File

@@ -28,11 +28,11 @@ import net.minecraft.world.level.storage.loot.entries.LootTableReference;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraftforge.event.*; import net.minecraftforge.event.*;
import net.minecraftforge.event.entity.player.PlayerContainerEvent; import net.minecraftforge.event.entity.player.PlayerContainerEvent;
import net.minecraftforge.event.server.ServerStartedEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
import net.minecraftforge.event.server.ServerStoppedEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fmlserverevents.FMLServerStartedEvent;
import net.minecraftforge.fmlserverevents.FMLServerStartingEvent;
import net.minecraftforge.fmlserverevents.FMLServerStoppedEvent;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
@@ -84,7 +84,7 @@ public final class CommonHooks
} }
@SubscribeEvent @SubscribeEvent
public static void onServerStarting( FMLServerStartingEvent event ) public static void onServerStarting( ServerStartingEvent event )
{ {
MinecraftServer server = event.getServer(); MinecraftServer server = event.getServer();
if( server instanceof DedicatedServer dediServer && dediServer.getProperties().enableJmxMonitoring ) if( server instanceof DedicatedServer dediServer && dediServer.getProperties().enableJmxMonitoring )
@@ -94,7 +94,7 @@ public final class CommonHooks
} }
@SubscribeEvent @SubscribeEvent
public static void onServerStarted( FMLServerStartedEvent event ) public static void onServerStarted( ServerStartedEvent event )
{ {
ComputerCraft.serverComputerRegistry.reset(); ComputerCraft.serverComputerRegistry.reset();
WirelessNetwork.resetNetworks(); WirelessNetwork.resetNetworks();
@@ -104,7 +104,7 @@ public final class CommonHooks
} }
@SubscribeEvent @SubscribeEvent
public static void onServerStopped( FMLServerStoppedEvent event ) public static void onServerStopped( ServerStoppedEvent event )
{ {
ComputerCraft.serverComputerRegistry.reset(); ComputerCraft.serverComputerRegistry.reset();
WirelessNetwork.resetNetworks(); WirelessNetwork.resetNetworks();

View File

@@ -96,11 +96,11 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fmllegacy.RegistryObject;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryBuilder; import net.minecraftforge.registries.RegistryBuilder;
import net.minecraftforge.registries.RegistryObject;
import java.util.function.BiFunction; import java.util.function.BiFunction;

View File

@@ -13,7 +13,7 @@ import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ClientChatEvent; import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; import net.minecraftforge.server.ServerLifecycleHooks;
import java.io.File; import java.io.File;

View File

@@ -19,7 +19,7 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraftforge.fmllegacy.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -12,11 +12,11 @@ import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraftforge.common.util.Constants;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -36,7 +36,7 @@ public abstract class TileGeneric extends BlockEntity
setChanged(); setChanged();
BlockPos pos = getBlockPos(); BlockPos pos = getBlockPos();
BlockState state = getBlockState(); BlockState state = getBlockState();
getLevel().sendBlockUpdated( pos, state, state, Constants.BlockFlags.DEFAULT ); getLevel().sendBlockUpdated( pos, state, state, Block.UPDATE_ALL );
} }
@Nonnull @Nonnull
@@ -73,42 +73,15 @@ public abstract class TileGeneric extends BlockEntity
player.distanceToSqr( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ) <= range * range; player.distanceToSqr( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ) <= range * range;
} }
protected void writeDescription( @Nonnull CompoundTag nbt )
{
}
protected void readDescription( @Nonnull CompoundTag nbt )
{
}
@Nonnull
@Override
public final ClientboundBlockEntityDataPacket getUpdatePacket()
{
CompoundTag nbt = new CompoundTag();
writeDescription( nbt );
return new ClientboundBlockEntityDataPacket( worldPosition, 0, nbt );
}
@Override @Override
public final void onDataPacket( Connection net, ClientboundBlockEntityDataPacket packet ) public final void onDataPacket( Connection net, ClientboundBlockEntityDataPacket packet )
{ {
if( packet.getType() == 0 ) readDescription( packet.getTag() ); var tag = packet.getTag();
} if( tag != null ) handleUpdateTag( tag );
@Nonnull
@Override
public CompoundTag getUpdateTag()
{
CompoundTag tag = super.getUpdateTag();
writeDescription( tag );
return tag;
} }
@Override @Override
public void handleUpdateTag( @Nonnull CompoundTag tag ) public void handleUpdateTag( @Nonnull CompoundTag tag )
{ {
super.handleUpdateTag( tag );
readDescription( tag );
} }
} }

View File

@@ -18,7 +18,7 @@ import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraftforge.fmllegacy.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -32,7 +32,7 @@ import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fmllegacy.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -119,7 +119,7 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
@Nonnull @Nonnull
@Override @Override
public ItemStack getPickBlock( BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player ) public ItemStack getCloneItemStack( BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player )
{ {
BlockEntity tile = world.getBlockEntity( pos ); BlockEntity tile = world.getBlockEntity( pos );
if( tile instanceof TileComputerBase ) if( tile instanceof TileComputerBase )
@@ -128,7 +128,7 @@ public abstract class BlockComputerBase<T extends TileComputerBase> extends Bloc
if( !result.isEmpty() ) return result; if( !result.isEmpty() ) return result;
} }
return super.getPickBlock( state, target, world, pos, player ); return super.getCloneItemStack( state, target, world, pos, player );
} }
@Override @Override

View File

@@ -24,6 +24,7 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.MenuProvider; import net.minecraft.world.MenuProvider;
@@ -187,16 +188,15 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
protected abstract void updateBlockState( ComputerState newState ); protected abstract void updateBlockState( ComputerState newState );
@Nonnull
@Override @Override
public CompoundTag save( @Nonnull CompoundTag nbt ) public void saveAdditional( @Nonnull CompoundTag nbt )
{ {
// Save ID, label and power state // Save ID, label and power state
if( computerID >= 0 ) nbt.putInt( NBT_ID, computerID ); if( computerID >= 0 ) nbt.putInt( NBT_ID, computerID );
if( label != null ) nbt.putString( NBT_LABEL, label ); if( label != null ) nbt.putString( NBT_LABEL, label );
nbt.putBoolean( NBT_ON, on ); nbt.putBoolean( NBT_ON, on );
return super.save( nbt ); super.saveAdditional( nbt );
} }
@Override @Override
@@ -383,18 +383,27 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
// Networking stuff // Networking stuff
@Nonnull
@Override @Override
protected void writeDescription( @Nonnull CompoundTag nbt ) public final ClientboundBlockEntityDataPacket getUpdatePacket()
{ {
super.writeDescription( nbt ); return ClientboundBlockEntityDataPacket.create( this );
}
@Nonnull
@Override
public CompoundTag getUpdateTag()
{
// We need this for pick block on the client side.
CompoundTag nbt = super.getUpdateTag();
if( label != null ) nbt.putString( NBT_LABEL, label ); if( label != null ) nbt.putString( NBT_LABEL, label );
if( computerID >= 0 ) nbt.putInt( NBT_ID, computerID ); if( computerID >= 0 ) nbt.putInt( NBT_ID, computerID );
return nbt;
} }
@Override @Override
protected void readDescription( @Nonnull CompoundTag nbt ) public void handleUpdateTag( @Nonnull CompoundTag nbt )
{ {
super.readDescription( nbt );
label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null;
computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1;
} }

View File

@@ -28,7 +28,7 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; import net.minecraftforge.server.ServerLifecycleHooks;
import net.minecraftforge.versions.mcp.MCPVersion; import net.minecraftforge.versions.mcp.MCPVersion;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -16,11 +16,11 @@ 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;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fmllegacy.network.NetworkDirection; import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.fmllegacy.network.NetworkRegistry; import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.fmllegacy.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.fmllegacy.network.simple.SimpleChannel; import net.minecraftforge.network.simple.SimpleChannel;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;

View File

@@ -6,7 +6,7 @@
package dan200.computercraft.shared.network; package dan200.computercraft.shared.network;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -10,7 +10,7 @@ import dan200.computercraft.shared.command.text.TableBuilder;
import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.NetworkMessage;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -9,7 +9,7 @@ import dan200.computercraft.shared.computer.core.ComputerState;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -7,7 +7,7 @@ package dan200.computercraft.shared.network.client;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
public class ComputerDeletedClientMessage extends ComputerClientMessage public class ComputerDeletedClientMessage extends ComputerClientMessage
{ {

View File

@@ -6,7 +6,7 @@
package dan200.computercraft.shared.network.client; package dan200.computercraft.shared.network.client;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -12,7 +12,7 @@ import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -13,7 +13,7 @@ import net.minecraft.network.chat.TextComponent;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -11,7 +11,7 @@ import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.UUID; import java.util.UUID;

View File

@@ -12,7 +12,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.UUID; import java.util.UUID;

View File

@@ -10,7 +10,7 @@ import dan200.computercraft.shared.network.NetworkMessage;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.UUID; import java.util.UUID;

View File

@@ -17,7 +17,7 @@ import dan200.computercraft.shared.UpgradeManager;
import dan200.computercraft.shared.network.NetworkMessage; import dan200.computercraft.shared.network.NetworkMessage;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryManager; import net.minecraftforge.registries.RegistryManager;

View File

@@ -13,7 +13,7 @@ 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;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -12,16 +12,16 @@ import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.MenuType;
import net.minecraftforge.common.extensions.IForgeContainerType; import net.minecraftforge.common.extensions.IForgeMenuType;
import net.minecraftforge.fmllegacy.network.IContainerFactory; import net.minecraftforge.network.IContainerFactory;
import net.minecraftforge.fmllegacy.network.NetworkHooks; import net.minecraftforge.network.NetworkHooks;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
/** /**
* An extension over the basic {@link IForgeContainerType}/{@link NetworkHooks#openGui(ServerPlayer, MenuProvider, Consumer)} * An extension over the basic {@link IForgeMenuType}/{@link NetworkHooks#openGui(ServerPlayer, MenuProvider, Consumer)}
* hooks, with a more convenient way of reading and writing data. * hooks, with a more convenient way of reading and writing data.
*/ */
public interface ContainerData public interface ContainerData
@@ -35,7 +35,7 @@ public interface ContainerData
static <C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> toType( Function<FriendlyByteBuf, T> reader, Factory<C, T> factory ) static <C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> toType( Function<FriendlyByteBuf, T> reader, Factory<C, T> factory )
{ {
return IForgeContainerType.create( ( id, player, data ) -> factory.create( id, player, reader.apply( data ) ) ); return IForgeMenuType.create( ( id, player, data ) -> factory.create( id, player, reader.apply( data ) ) );
} }
static <C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> toType( Function<FriendlyByteBuf, T> reader, FixedFactory<C, T> factory ) static <C extends AbstractContainerMenu, T extends ContainerData> MenuType<C> toType( Function<FriendlyByteBuf, T> reader, FixedFactory<C, T> factory )
@@ -60,7 +60,7 @@ public interface ContainerData
private FixedPointContainerFactory( Function<FriendlyByteBuf, T> reader, FixedFactory<C, T> factory ) private FixedPointContainerFactory( Function<FriendlyByteBuf, T> reader, FixedFactory<C, T> factory )
{ {
MenuType<C> type = this.type = IForgeContainerType.create( this ); MenuType<C> type = this.type = IForgeMenuType.create( this );
impl = ( id, player, data ) -> factory.create( type, id, player, reader.apply( data ) ); impl = ( id, player, data ) -> factory.create( type, id, player, reader.apply( data ) );
} }

View File

@@ -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.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -10,7 +10,7 @@ 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.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -9,7 +9,7 @@ import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -9,7 +9,7 @@ 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.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -9,7 +9,7 @@ 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.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -10,7 +10,7 @@ import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.util.NBTUtil; import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -9,7 +9,7 @@ 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.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;

View File

@@ -14,7 +14,7 @@ import dan200.computercraft.shared.network.NetworkHandler;
import io.netty.handler.codec.DecoderException; import io.netty.handler.codec.DecoderException;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.fmllegacy.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;

View File

@@ -37,9 +37,9 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fmllegacy.network.NetworkHooks;
import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.InvWrapper; import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.network.NetworkHooks;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -137,9 +137,8 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
} }
} }
@Nonnull
@Override @Override
public CompoundTag save( @Nonnull CompoundTag nbt ) public void saveAdditional( @Nonnull CompoundTag nbt )
{ {
if( customName != null ) nbt.putString( NBT_NAME, Component.Serializer.toJson( customName ) ); if( customName != null ) nbt.putString( NBT_NAME, Component.Serializer.toJson( customName ) );
@@ -149,7 +148,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
diskStack.save( item ); diskStack.save( item );
nbt.put( NBT_ITEM, item ); nbt.put( NBT_ITEM, item );
} }
return super.save( nbt ); super.saveAdditional( nbt );
} }
void serverTick() void serverTick()

View File

@@ -60,9 +60,9 @@ public class ItemData
data.put( "maxDamage", stack.getMaxDamage() ); data.put( "maxDamage", stack.getMaxDamage() );
} }
if( stack.getItem().showDurabilityBar( stack ) ) if( stack.getItem().isBarVisible( stack ) )
{ {
data.put( "durability", stack.getItem().getDurabilityForDisplay( stack ) ); data.put( "durability", stack.getItem().getBarWidth( stack ) / 13.0 );
} }
data.put( "tags", DataHelpers.getTags( stack.getItem().getTags() ) ); data.put( "tags", DataHelpers.getTags( stack.getItem().getTags() ) );

View File

@@ -98,7 +98,7 @@ public class BlockCable extends BlockGeneric implements SimpleWaterloggedBlock
} }
@Override @Override
public boolean removedByPlayer( BlockState state, Level world, BlockPos pos, Player player, boolean willHarvest, FluidState fluid ) public boolean onDestroyedByPlayer( BlockState state, Level world, BlockPos pos, Player player, boolean willHarvest, FluidState fluid )
{ {
if( state.getValue( CABLE ) && state.getValue( MODEM ).getFacing() != null ) if( state.getValue( CABLE ) && state.getValue( MODEM ).getFacing() != null )
{ {
@@ -140,12 +140,12 @@ public class BlockCable extends BlockGeneric implements SimpleWaterloggedBlock
} }
} }
return super.removedByPlayer( state, world, pos, player, willHarvest, fluid ); return super.onDestroyedByPlayer( state, world, pos, player, willHarvest, fluid );
} }
@Nonnull @Nonnull
@Override @Override
public ItemStack getPickBlock( BlockState state, HitResult hit, BlockGetter world, BlockPos pos, Player player ) public ItemStack getCloneItemStack( BlockState state, HitResult hit, BlockGetter world, BlockPos pos, Player player )
{ {
Direction modem = state.getValue( MODEM ).getFacing(); Direction modem = state.getValue( MODEM ).getFacing();
boolean cable = state.getValue( CABLE ); boolean cable = state.getValue( CABLE );

View File

@@ -292,13 +292,12 @@ public class TileCable extends TileGeneric
peripheral.read( nbt, "" ); peripheral.read( nbt, "" );
} }
@Nonnull
@Override @Override
public CompoundTag save( CompoundTag nbt ) public void saveAdditional( CompoundTag nbt )
{ {
nbt.putBoolean( NBT_PERIPHERAL_ENABLED, peripheralAccessAllowed ); nbt.putBoolean( NBT_PERIPHERAL_ENABLED, peripheralAccessAllowed );
peripheral.write( nbt, "" ); peripheral.write( nbt, "" );
return super.save( nbt ); super.saveAdditional( nbt );
} }
private void updateBlockState() private void updateBlockState()
@@ -346,7 +345,7 @@ public class TileCable extends TileGeneric
for( Direction facing : DirectionUtil.FACINGS ) for( Direction facing : DirectionUtil.FACINGS )
{ {
BlockPos offset = current.relative( facing ); BlockPos offset = current.relative( facing );
if( !world.isAreaLoaded( offset, 0 ) ) continue; if( !world.isLoaded( offset ) ) continue;
LazyOptional<IWiredElement> element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); LazyOptional<IWiredElement> element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() );
if( !element.isPresent() ) continue; if( !element.isPresent() ) continue;

View File

@@ -241,13 +241,12 @@ public class TileWiredModemFull extends TileGeneric
for( int i = 0; i < peripherals.length; i++ ) peripherals[i].read( nbt, Integer.toString( i ) ); for( int i = 0; i < peripherals.length; i++ ) peripherals[i].read( nbt, Integer.toString( i ) );
} }
@Nonnull
@Override @Override
public CompoundTag save( CompoundTag nbt ) public void saveAdditional( CompoundTag nbt )
{ {
nbt.putBoolean( NBT_PERIPHERAL_ENABLED, peripheralAccessAllowed ); nbt.putBoolean( NBT_PERIPHERAL_ENABLED, peripheralAccessAllowed );
for( int i = 0; i < peripherals.length; i++ ) peripherals[i].write( nbt, Integer.toString( i ) ); for( int i = 0; i < peripherals.length; i++ ) peripherals[i].write( nbt, Integer.toString( i ) );
return super.save( nbt ); super.saveAdditional( nbt );
} }
private void updateBlockState() private void updateBlockState()
@@ -306,7 +305,7 @@ public class TileWiredModemFull extends TileGeneric
for( Direction facing : DirectionUtil.FACINGS ) for( Direction facing : DirectionUtil.FACINGS )
{ {
BlockPos offset = current.relative( facing ); BlockPos offset = current.relative( facing );
if( !world.isAreaLoaded( offset, 0 ) ) continue; if( !world.isLoaded( offset ) ) continue;
LazyOptional<IWiredElement> element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); LazyOptional<IWiredElement> element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() );
if( !element.isPresent() ) continue; if( !element.isPresent() ) continue;

View File

@@ -25,7 +25,7 @@ import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.fmllegacy.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -21,7 +21,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fmllegacy.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -94,9 +94,12 @@ class Expander
if( !isPositive ) if( !isPositive )
{ {
BlockEntity otherOrigin = level.getBlockEntity( otherMonitor.toWorldPos( 0, 0 ) ); BlockEntity otherOrigin = level.getBlockEntity( otherMonitor.toWorldPos( 0, 0 ) );
if( otherOrigin == null || !origin.isCompatible( (TileMonitor) otherOrigin ) ) return false; if( !(otherOrigin instanceof TileMonitor originMonitor) || !origin.isCompatible( originMonitor ) )
{
return false;
}
origin = (TileMonitor) otherOrigin; origin = originMonitor;
} }
this.width = width; this.width = width;

View File

@@ -101,7 +101,7 @@ public final class MonitorWatcher
if( !(world instanceof ServerLevel) ) continue; if( !(world instanceof ServerLevel) ) continue;
LevelChunk chunk = world.getChunkAt( pos ); LevelChunk chunk = world.getChunkAt( pos );
if( ((ServerLevel) world).getChunkSource().chunkMap.getPlayers( chunk.getPos(), false ).findAny().isEmpty() ) if( ((ServerLevel) world).getChunkSource().chunkMap.getPlayers( chunk.getPos(), false ).isEmpty() )
{ {
continue; continue;
} }

View File

@@ -17,6 +17,7 @@ import dan200.computercraft.shared.util.TickScheduler;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
@@ -126,15 +127,14 @@ public class TileMonitor extends TileGeneric
return InteractionResult.PASS; return InteractionResult.PASS;
} }
@Nonnull
@Override @Override
public CompoundTag save( CompoundTag tag ) public void saveAdditional( CompoundTag tag )
{ {
tag.putInt( NBT_X, xIndex ); tag.putInt( NBT_X, xIndex );
tag.putInt( NBT_Y, yIndex ); tag.putInt( NBT_Y, yIndex );
tag.putInt( NBT_WIDTH, width ); tag.putInt( NBT_WIDTH, width );
tag.putInt( NBT_HEIGHT, height ); tag.putInt( NBT_HEIGHT, height );
return super.save( tag ); super.saveAdditional( tag );
} }
@Override @Override
@@ -236,7 +236,6 @@ public class TileMonitor extends TileGeneric
{ {
// Otherwise fetch the origin and attempt to get its monitor // Otherwise fetch the origin and attempt to get its monitor
// Note this may load chunks, but we don't really have a choice here. // Note this may load chunks, but we don't really have a choice here.
BlockPos pos = getBlockPos();
BlockEntity te = level.getBlockEntity( toWorldPos( 0, 0 ) ); BlockEntity te = level.getBlockEntity( toWorldPos( 0, 0 ) );
if( !(te instanceof TileMonitor) ) return null; if( !(te instanceof TileMonitor) ) return null;
@@ -249,7 +248,6 @@ public class TileMonitor extends TileGeneric
{ {
if( clientMonitor != null ) return clientMonitor; if( clientMonitor != null ) return clientMonitor;
BlockPos pos = getBlockPos();
BlockEntity te = level.getBlockEntity( toWorldPos( 0, 0 ) ); BlockEntity te = level.getBlockEntity( toWorldPos( 0, 0 ) );
if( !(te instanceof TileMonitor) ) return null; if( !(te instanceof TileMonitor) ) return null;
@@ -258,20 +256,29 @@ public class TileMonitor extends TileGeneric
// Networking stuff // Networking stuff
@Nonnull
@Override @Override
protected void writeDescription( @Nonnull CompoundTag nbt ) public final ClientboundBlockEntityDataPacket getUpdatePacket()
{ {
super.writeDescription( nbt ); return ClientboundBlockEntityDataPacket.create( this );
}
@Nonnull
@Override
public final CompoundTag getUpdateTag()
{
CompoundTag nbt = super.getUpdateTag();
nbt.putInt( NBT_X, xIndex ); nbt.putInt( NBT_X, xIndex );
nbt.putInt( NBT_Y, yIndex ); nbt.putInt( NBT_Y, yIndex );
nbt.putInt( NBT_WIDTH, width ); nbt.putInt( NBT_WIDTH, width );
nbt.putInt( NBT_HEIGHT, height ); nbt.putInt( NBT_HEIGHT, height );
return nbt;
} }
@Override @Override
protected final void readDescription( @Nonnull CompoundTag nbt ) public final void handleUpdateTag( @Nonnull CompoundTag nbt )
{ {
super.readDescription( nbt ); super.handleUpdateTag( nbt );
int oldXIndex = xIndex; int oldXIndex = xIndex;
int oldYIndex = yIndex; int oldYIndex = yIndex;
@@ -390,7 +397,7 @@ public class TileMonitor extends TileGeneric
BlockPos pos = toWorldPos( x, y ); BlockPos pos = toWorldPos( x, y );
Level world = getLevel(); Level world = getLevel();
if( world == null || !world.isAreaLoaded( pos, 0 ) ) return MonitorState.UNLOADED; if( world == null || !world.isLoaded( pos ) ) return MonitorState.UNLOADED;
BlockEntity tile = world.getBlockEntity( pos ); BlockEntity tile = world.getBlockEntity( pos );
if( !(tile instanceof TileMonitor monitor) ) return MonitorState.MISSING; if( !(tile instanceof TileMonitor monitor) ) return MonitorState.MISSING;

View File

@@ -31,10 +31,10 @@ import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fmllegacy.network.NetworkHooks;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.InvWrapper; import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.items.wrapper.SidedInvWrapper; import net.minecraftforge.items.wrapper.SidedInvWrapper;
import net.minecraftforge.network.NetworkHooks;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -113,9 +113,8 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
ContainerHelper.loadAllItems( nbt, inventory ); ContainerHelper.loadAllItems( nbt, inventory );
} }
@Nonnull
@Override @Override
public CompoundTag save( @Nonnull CompoundTag nbt ) public void saveAdditional( @Nonnull CompoundTag nbt )
{ {
if( customName != null ) nbt.putString( NBT_NAME, Component.Serializer.toJson( customName ) ); if( customName != null ) nbt.putString( NBT_NAME, Component.Serializer.toJson( customName ) );
@@ -130,7 +129,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
// Write inventory // Write inventory
ContainerHelper.saveAllItems( nbt, inventory ); ContainerHelper.saveAllItems( nbt, inventory );
return super.save( nbt ); super.saveAdditional( nbt );
} }
boolean isPrinting() boolean isPrinting()

View File

@@ -9,8 +9,7 @@ import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.shared.network.NetworkHandler; import dan200.computercraft.shared.network.NetworkHandler;
import dan200.computercraft.shared.network.client.SpeakerStopClientMessage; import dan200.computercraft.shared.network.client.SpeakerStopClientMessage;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.server.ServerLifecycleHooks;
import net.minecraftforge.fmllegacy.LogicalSidedProvider;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.UUID; import java.util.UUID;
@@ -34,7 +33,7 @@ public abstract class UpgradeSpeakerPeripheral extends SpeakerPeripheral
public void detach( @Nonnull IComputerAccess computer ) public void detach( @Nonnull IComputerAccess computer )
{ {
// We could be in the process of shutting down the server, so we can't send packets in this case. // We could be in the process of shutting down the server, so we can't send packets in this case.
MinecraftServer server = LogicalSidedProvider.INSTANCE.get( LogicalSide.SERVER ); MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
if( server == null || server.isStopped() ) return; if( server == null || server.isStopped() ) return;
NetworkHandler.sendToAllPlayers( new SpeakerStopClientMessage( source ) ); NetworkHandler.sendToAllPlayers( new SpeakerStopClientMessage( source ) );

View File

@@ -42,7 +42,7 @@ import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.fmllegacy.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@@ -289,9 +289,8 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
brain.readFromNBT( nbt ); brain.readFromNBT( nbt );
} }
@Nonnull
@Override @Override
public CompoundTag save( @Nonnull CompoundTag nbt ) public void saveAdditional( @Nonnull CompoundTag nbt )
{ {
// Write inventory // Write inventory
ListTag nbttaglist = new ListTag(); ListTag nbttaglist = new ListTag();
@@ -310,7 +309,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
// Write brain // Write brain
nbt = brain.writeToNBT( nbt ); nbt = brain.writeToNBT( nbt );
return super.save( nbt ); super.saveAdditional( nbt );
} }
@Override @Override
@@ -504,17 +503,19 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
// Networking stuff // Networking stuff
@Nonnull
@Override @Override
protected void writeDescription( @Nonnull CompoundTag nbt ) public CompoundTag getUpdateTag()
{ {
super.writeDescription( nbt ); CompoundTag nbt = super.getUpdateTag();
brain.writeDescription( nbt ); brain.writeDescription( nbt );
return nbt;
} }
@Override @Override
protected void readDescription( @Nonnull CompoundTag nbt ) public void handleUpdateTag( @Nonnull CompoundTag nbt )
{ {
super.readDescription( nbt ); super.handleUpdateTag( nbt );
brain.readDescription( nbt ); brain.readDescription( nbt );
} }

View File

@@ -304,7 +304,7 @@ public class TurtleBrain implements ITurtleAccess
} }
// Ensure the chunk is loaded // Ensure the chunk is loaded
if( !world.isAreaLoaded( pos, 0 ) ) return false; if( !world.isLoaded( pos ) ) return false;
// Ensure we're inside the world border // Ensure we're inside the world border
if( !world.getWorldBorder().isWithinBounds( pos ) ) return false; if( !world.getWorldBorder().isWithinBounds( pos ) ) return false;

View File

@@ -137,7 +137,7 @@ public class TurtleMoveCommand implements ITurtleCommand
return TurtleCommandResult.failure( "Cannot enter protected area" ); return TurtleCommandResult.failure( "Cannot enter protected area" );
} }
if( !world.isAreaLoaded( position, 0 ) ) return TurtleCommandResult.failure( "Cannot leave loaded world" ); if( !world.isLoaded( position ) ) return TurtleCommandResult.failure( "Cannot leave loaded world" );
if( !world.getWorldBorder().isWithinBounds( position ) ) if( !world.getWorldBorder().isWithinBounds( position ) )
{ {
return TurtleCommandResult.failure( "Cannot pass the world border" ); return TurtleCommandResult.failure( "Cannot pass the world border" );

View File

@@ -27,13 +27,13 @@ import net.minecraft.world.item.*;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.Event.Result; import net.minecraftforge.eventbus.api.Event.Result;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@@ -321,7 +321,7 @@ public class TurtlePlaceCommand implements ITurtleCommand
} }
} }
signTile.setChanged(); signTile.setChanged();
world.sendBlockUpdated( tile.getBlockPos(), tile.getBlockState(), tile.getBlockState(), Constants.BlockFlags.DEFAULT ); world.sendBlockUpdated( tile.getBlockPos(), tile.getBlockState(), tile.getBlockState(), Block.UPDATE_ALL );
} }
private static class ErrorMessage private static class ErrorMessage

View File

@@ -17,7 +17,7 @@ import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.fmllegacy.hooks.BasicEventHooks; import net.minecraftforge.event.ForgeEventFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -91,7 +91,7 @@ public class TurtleInventoryCrafting extends CraftingContainer
results.add( result ); results.add( result );
result.onCraftedBy( world, player, result.getCount() ); result.onCraftedBy( world, player, result.getCount() );
BasicEventHooks.firePlayerCraftingEvent( player, result, this ); ForgeEventFactory.firePlayerCraftingEvent( player, result, this );
ForgeHooks.setCraftingPlayer( player ); ForgeHooks.setCraftingPlayer( player );
NonNullList<ItemStack> remainders = recipe.getRemainingItems( this ); NonNullList<ItemStack> remainders = recipe.getRemainingItems( this );

View File

@@ -255,7 +255,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
// Destroy the block // Destroy the block
boolean canHarvest = state.canHarvestBlock( world, blockPosition, turtlePlayer ); boolean canHarvest = state.canHarvestBlock( world, blockPosition, turtlePlayer );
boolean canBreak = state.removedByPlayer( world, blockPosition, turtlePlayer, canHarvest, fluidState ); boolean canBreak = state.onDestroyedByPlayer( world, blockPosition, turtlePlayer, canHarvest, fluidState );
if( canBreak ) state.getBlock().destroy( world, blockPosition, state ); if( canBreak ) state.getBlock().destroy( world, blockPosition, state );
if( canHarvest && canBreak ) if( canHarvest && canBreak )
{ {

View File

@@ -11,7 +11,7 @@ import com.google.gson.reflect.TypeToken;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.storage.LevelResource; import net.minecraft.world.level.storage.LevelResource;
import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; import net.minecraftforge.server.ServerLifecycleHooks;
import java.io.File; import java.io.File;
import java.io.Reader; import java.io.Reader;

View File

@@ -10,7 +10,8 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.common.TileGeneric;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.TickList; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -21,7 +22,7 @@ import java.util.Iterator;
import java.util.Set; import java.util.Set;
/** /**
* A thread-safe version of {@link TickList#scheduleTick(BlockPos, Object, int)}. * A thread-safe version of {@link LevelAccessor#scheduleTick(BlockPos, Block, int)}.
* *
* We use this when modems and other peripherals change a block in a different thread. * We use this when modems and other peripherals change a block in a different thread.
*/ */
@@ -58,9 +59,9 @@ public final class TickScheduler
Level world = tile.getLevel(); Level world = tile.getLevel();
BlockPos pos = tile.getBlockPos(); BlockPos pos = tile.getBlockPos();
if( world != null && pos != null && world.isAreaLoaded( pos, 0 ) && world.getBlockEntity( pos ) == tile ) if( world != null && pos != null && world.isLoaded( pos ) && world.getBlockEntity( pos ) == tile )
{ {
world.getBlockTicks().scheduleTick( pos, tile.getBlockState().getBlock(), 0 ); world.scheduleTick( pos, tile.getBlockState().getBlock(), 0 );
} }
} }
} }

View File

@@ -48,7 +48,7 @@ public final class WaterloggableHelpers
{ {
if( state.getValue( WATERLOGGED ) ) if( state.getValue( WATERLOGGED ) )
{ {
world.getLiquidTicks().scheduleTick( pos, Fluids.WATER, Fluids.WATER.getTickDelay( world ) ); world.scheduleTick( pos, Fluids.WATER, Fluids.WATER.getTickDelay( world ) );
} }
} }

View File

@@ -1,5 +1,5 @@
modLoader="javafml" modLoader="javafml"
loaderVersion="[37,38)" loaderVersion="[39,40)"
issueTrackerURL="https://github.com/cc-tweaked/CC-Tweaked/issues" issueTrackerURL="https://github.com/cc-tweaked/CC-Tweaked/issues"
logoFile="pack.png" logoFile="pack.png"
@@ -21,6 +21,6 @@ CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles a
[[dependencies.computercraft]] [[dependencies.computercraft]]
modId="forge" modId="forge"
mandatory=true mandatory=true
versionRange="[37.0.85,38)" versionRange="[39.0.0,40)"
ordering="NONE" ordering="NONE"
side="BOTH" side="BOTH"

View File

@@ -28,9 +28,11 @@ Once you have the name of a peripheral, you can call functions on it using the
@{peripheral.call} function. This takes the name of our peripheral, the name of @{peripheral.call} function. This takes the name of our peripheral, the name of
the function we want to call, and then its arguments. the function we want to call, and then its arguments.
> Some bits of the peripheral API call peripheral functions *methods* instead :::info
> (for example, the @{peripheral.getMethods} function). Don't worry, they're the Some bits of the peripheral API call peripheral functions *methods* instead
> same thing! (for example, the @{peripheral.getMethods} function). Don't worry, they're the
same thing!
:::
Let's say we have a monitor above our computer (and so "top") and want to Let's say we have a monitor above our computer (and so "top") and want to
@{monitor.write|write some text to it}. We'd write the following: @{monitor.write|write some text to it}. We'd write the following:

View File

@@ -1,3 +1,14 @@
# New features in CC: Tweaked 1.99.1
* Add package.searchpath to the cc.require API. (MCJack123)
* Provide a more efficient way for the Java API to consume Lua tables in certain restricted cases.
Several bug fixes:
* Fix keys being "sticky" when opening the off-hand pocket computer GUI.
* Correctly handle broken coroutine managers resuming Java code with a `nil` event.
* Prevent computer buttons stealing focus from the terminal.
* Fix a class cast exception when a monitor is malformed in ways I do not quite understand.
# New features in CC: Tweaked 1.99.0 # New features in CC: Tweaked 1.99.0
* Pocket computers in their offhand will open without showing a terminal. You can look around and interact with the world, but your keyboard will be forwarded to the computer. (Wojbie, MagGen-hub). * Pocket computers in their offhand will open without showing a terminal. You can look around and interact with the world, but your keyboard will be forwarded to the computer. (Wojbie, MagGen-hub).

View File

@@ -1,32 +1,12 @@
New features in CC: Tweaked 1.99.0 New features in CC: Tweaked 1.99.1
* Pocket computers in their offhand will open without showing a terminal. You can look around and interact with the world, but your keyboard will be forwarded to the computer. (Wojbie, MagGen-hub). * Add package.searchpath to the cc.require API. (MCJack123)
* Peripherals can now have multiple types. `peripheral.getType` now returns multiple values, and `peripheral.hasType` checks if a peripheral has a specific type. * Provide a more efficient way for the Java API to consume Lua tables in certain restricted cases.
* Add several missing keys to the `keys` table. (ralphgod3)
* Add feature introduction/changed version information to the documentation. (MCJack123)
* Increase the file upload limit to 512KiB.
* Rednet can now handle computer IDs larger than 65535. (Ale32bit)
* Optimise deduplication of rednet messages (MCJack123)
* Make `term.blit` colours case insensitive. (Ocawesome101)
* Add a new `about` program for easier version identification. (MCJack123)
* Optimise peripheral calls in `rednet.run`. (xAnavrins)
* Add dimension parameter to `commands.getBlockInfo`.
* Add `cc.pretty.pretty_print` helper function (Lupus590).
* Add back JEI integration.
* Turtle and pocket computer upgrades can now be added and modified with data packs.
* Various translation updates (MORIMORI3017, Ale2Bit, mindy15963)
And several bug fixes: Several bug fixes:
* Fix various computer commands failing when OP level was 4. * Fix keys being "sticky" when opening the off-hand pocket computer GUI.
* Various documentation fixes. (xXTurnerLP, MCJack123) * Correctly handle broken coroutine managers resuming Java code with a `nil` event.
* Fix `textutils.serialize` not serialising infinity and nan values. (Wojbie) * Prevent computer buttons stealing focus from the terminal.
* Wired modems now correctly clean up mounts when a peripheral is detached. * Fix a class cast exception when a monitor is malformed in ways I do not quite understand.
* Fix incorrect turtle and pocket computer upgrade recipes in the recipe book.
* Fix speakers not playing sounds added via resource packs which are not registered in-game.
* Fix speaker upgrades sending packets after the server has stopped.
* Monitor sizing has been rewritten, hopefully making it more stable.
* Peripherals are now invalidated when the computer ticks, rather than when the peripheral changes.
* Fix printouts and pocket computers rendering at fullbright when in item frames.
* All mod blocks now have an effective tool (pickaxe).
Type "help changelog" to see the full version history. Type "help changelog" to see the full version history.

View File

@@ -31,22 +31,37 @@ local function preload(package)
end end
end end
local function from_file(package, env, dir) local function from_file(package, env)
return function(name) return function(name)
local fname = string.gsub(name, "%.", "/") local sPath, sError = package.searchpath(name, package.path)
local sError = "" if not sPath then
for pattern in string.gmatch(package.path, "[^;]+") do return nil, sError
local sPath = string.gsub(pattern, "%?", fname)
if sPath:sub(1, 1) ~= "/" then
sPath = fs.combine(dir, sPath)
end end
if fs.exists(sPath) and not fs.isDir(sPath) then
local fnFile, sError = loadfile(sPath, nil, env) local fnFile, sError = loadfile(sPath, nil, env)
if fnFile then if fnFile then
return fnFile, sPath return fnFile, sPath
else else
return nil, sError return nil, sError
end end
end
end
local function make_searchpath(dir)
return function(name, path, sep, rep)
expect(1, name, "string")
expect(2, path, "string")
sep = expect(3, sep, "string", "nil") or "."
rep = expect(4, rep, "string", "nil") or "/"
local fname = string.gsub(name, sep:gsub("%.", "%%%."), rep)
local sError = ""
for pattern in string.gmatch(path, "[^;]+") do
local sPath = string.gsub(pattern, "%?", fname)
if sPath:sub(1, 1) ~= "/" then
sPath = fs.combine(dir, sPath)
end
if fs.exists(sPath) and not fs.isDir(sPath) then
return sPath
else else
if #sError > 0 then if #sError > 0 then
sError = sError .. "\n " sError = sError .. "\n "
@@ -118,7 +133,8 @@ local function make_package(env, dir)
end end
package.config = "/\n;\n?\n!\n-" package.config = "/\n;\n?\n!\n-"
package.preload = {} package.preload = {}
package.loaders = { preload(package), from_file(package, env, dir) } package.loaders = { preload(package), from_file(package, env) }
package.searchpath = make_searchpath(dir)
return make_require(package), package return make_require(package), package
end end

View File

@@ -97,7 +97,7 @@ public class ComputerTestDelegate
if( REPORT_PATH.delete() ) ComputerCraft.log.info( "Deleted previous coverage report." ); if( REPORT_PATH.delete() ) ComputerCraft.log.info( "Deleted previous coverage report." );
Terminal term = new Terminal( 80, 30 ); Terminal term = new Terminal( 80, 100 );
IWritableMount mount = new FileMount( new File( "test-files/mount" ), 10_000_000 ); IWritableMount mount = new FileMount( new File( "test-files/mount" ), 10_000_000 );
// Remove any existing files // Remove any existing files

View File

@@ -120,6 +120,13 @@ public class GeneratorTest
contramap( notNullValue(), "callback", MethodResult::getCallback ) ); contramap( notNullValue(), "callback", MethodResult::getCallback ) );
} }
@Test
public void testUnsafe()
{
List<NamedMethod<LuaMethod>> methods = LuaMethod.GENERATOR.getMethods( Unsafe.class );
assertThat( methods, contains( named( "withUnsafe" ) ) );
}
public static class Basic public static class Basic
{ {
@LuaFunction @LuaFunction
@@ -222,6 +229,21 @@ public class GeneratorTest
{} {}
} }
public static class Unsafe
{
@LuaFunction( unsafe = true )
public final void withUnsafe( LuaTable<?, ?> table )
{}
@LuaFunction
public final void withoutUnsafe( LuaTable<?, ?> table )
{}
@LuaFunction( unsafe = true, mainThread = true )
public final void invalid( LuaTable<?, ?> table )
{}
}
private static <T> T find( Collection<NamedMethod<T>> methods, String name ) private static <T> T find( Collection<NamedMethod<T>> methods, String name )
{ {
return methods.stream() return methods.stream()

View File

@@ -27,7 +27,7 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.flat.FlatLayerInfo; import net.minecraft.world.level.levelgen.flat.FlatLayerInfo;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.client.event.ScreenEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@@ -50,9 +50,9 @@ public final class ClientHooks
} }
@SubscribeEvent @SubscribeEvent
public static void onGuiInit( GuiScreenEvent.InitGuiEvent event ) public static void onGuiInit( ScreenEvent.InitScreenEvent event )
{ {
if( triggered || !(event.getGui() instanceof TitleScreen) ) return; if( triggered || !(event.getScreen() instanceof TitleScreen) ) return;
triggered = true; triggered = true;
ClientHooks.openWorld(); ClientHooks.openWorld();
@@ -93,7 +93,7 @@ public final class ClientHooks
WorldGenSettings generator = new WorldGenSettings( 0, false, false, withOverworld( WorldGenSettings generator = new WorldGenSettings( 0, false, false, withOverworld(
dimensions, dimensions,
DimensionType.defaultDimensions( dimensions, biomes, registries.registryOrThrow( Registry.NOISE_GENERATOR_SETTINGS_REGISTRY ), 0 ), DimensionType.defaultDimensions( registries, 0 ),
new FlatLevelSource( flatSettings ) new FlatLevelSource( flatSettings )
) ); ) );

View File

@@ -5,9 +5,9 @@
*/ */
package dan200.computercraft.ingame.mod; package dan200.computercraft.ingame.mod;
import dan200.computercraft.ingame.api.Times;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.SharedConstants; import net.minecraft.SharedConstants;
import dan200.computercraft.ingame.api.Times;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@@ -21,11 +21,11 @@ import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.server.ServerStartedEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; import net.minecraftforge.server.ServerLifecycleHooks;
import net.minecraftforge.fmlserverevents.FMLServerStartedEvent;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -49,7 +49,7 @@ public class TestHooks
} }
@SubscribeEvent @SubscribeEvent
public static void onServerStarted( FMLServerStartedEvent event ) public static void onServerStarted( ServerStartedEvent event )
{ {
MinecraftServer server = event.getServer(); MinecraftServer server = event.getServer();
GameRules rules = server.getGameRules(); GameRules rules = server.getGameRules();