1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-16 22:47:38 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
SquidDev
6ac1c0e944 Basic network visualiser 2019-02-11 09:05:27 +00:00
SquidDev
12e82afad2 Bump Cobalt version to enable single-threading
The latest version of Cobalt has several major changes, which I'm
looking forward to taking advantage of in the coming months:

 - The Lua interpreter has been split up from the actual LuaClosure
   instance. It now runs multiple functions within one loop, handling
   pushing/popping and resuming method calls correctly.

   This means we have a theoretically infinite call depth, as we're no
   longer bounded by Java's stack size. In reality, this is limited to
   32767 (Short.MAX_VALUE), as that's a mostly equivalent to the limits
   PUC Lua exposes.

 - The stack is no longer unwound in the event of errors. This both
   simplifies error handling (not that CC:T needs to care about that)
   but also means one can call debug.traceback on a now-dead coroutine
   (which is more useful for debugging than using xpcall).

 - Most significantly, coroutines are no longer each run on a dedicated
   thread. Instead, yielding or resuming throws an exception to unwind
   the Java stack and switches to a different coroutine.

   In order to preserve compatability with CC's assumption about LuaJ's
   threading model (namely that yielding blocks the thread), we also
   provide a yieldBlock method (which CC:T consumes). This suspends the
   current thread and switches execution to a new thread (see
   SquidDev/Cobalt@b5ddf164f1 for more
   details). While this does mean we need to use more than 1 thread,
   it's still /substantially/ less than would otherwise be needed.

We've been running these changes on SwitchCraft for a few days now and
haven't seen any issues. One nice thing to observe is that the number of
CC thread has gone down from ~1.9k to ~100 (of those, ~70 are dedicated
to running coroutines). Similarly, the server has gone from generating
~15k threads over its lifetime, to ~3k. While this is still a lot, it's
a substantial improvement.
2019-02-10 22:02:30 +00:00
SquidDev
6c2db93cbd Register item colour handlers on the event instead
Another step on my misguided quest to get rid of proxies
2019-02-10 09:55:06 +00:00
SquidDev
d5edbe700b Load turtle item models using a model loader
This is far more elegant than our weird method of baking things and
manually inserting them into the model map. Also means we no longer need
the whole turtle_dynamic thing.
2019-02-10 09:45:15 +00:00
SquidDev
86ad43c3ab Fix peripheral direction not being set
We moved the direction call within the if block, but never actally
updated the condition! I'm on a roll of stupid bug fixes today, which
really isn't a good sign.
2019-02-07 23:07:49 +00:00
SquidDev
f450c0156b Recomment out a global
It's actually rather worrying this was exposed, you could cause some
serious issues with it.
2019-02-07 20:22:00 +00:00
SquidDev
8abcfcb4ac Track turtle commands as server tasks
They're basically an alternative version of issueMainThreadTask anyway.
2019-01-30 20:43:08 +00:00
SquidDev
f3cace1d03 Allow building without a git repository
Closes #102
2019-01-28 14:05:53 +00:00
SquidDev
e1e5e898ab Make monitors use a concurrent map instead of a synchronized
We didn't lock when iterating on the main-thread, so it wasn't actually
thread-safe anyway!
2019-01-25 22:59:01 +00:00
SquidDev
3aa3852ff6 Some further improvements to BlockGeneric
- Only have computers implement custom block drop logic: everything
   else only drops in creative mode.
 - Fix redstone inputs not being received correctly. Introduced in
   8b86a954ee, yes I'm a silly billy.
 - Only update the neighbour which changed.
2019-01-25 22:03:44 +00:00
SquidDev
709a6329c7 Fix all wireless modem blocks being advanced 2019-01-25 00:12:49 +00:00
SquidDev
c9f05a2939 Make require a little more consistent with Lua 5.1
- Error messages are indented correctly
 - The module's name is passed as the first argument to modules
 - Make error messages match Lua's
2019-01-23 18:50:17 +00:00
Devilholk
e41377f862 Handle connection errors on websockets 2019-01-22 11:11:25 +00:00
34 changed files with 695 additions and 658 deletions

View File

@@ -10,7 +10,7 @@ buildscript {
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
classpath 'org.ajoberstar:gradle-git:1.6.0'
classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
}
}
@@ -48,7 +48,7 @@ repositories {
}
maven {
name = "squiddev"
url = "https://dl.bintray.com/squiddev/maven"
url = "https://squiddev.cc/maven"
}
ivy { artifactPattern "https://asie.pl/files/mods/Charset/LibOnly/[module]-[revision](-[classifier]).[ext]" }
@@ -66,7 +66,7 @@ dependencies {
runtime "mezz.jei:jei_1.12.2:4.8.5.159"
shade 'org.squiddev:Cobalt:0.4.0'
shade 'org.squiddev:Cobalt:0.5.0-SNAPSHOT'
testCompile 'junit:junit:4.11'
@@ -99,16 +99,20 @@ processResources {
inputs.property "version", project.version
inputs.property "mcversion", project.minecraft.version
def grgit = Grgit.open(dir: '.')
inputs.property "commithash", grgit.head().id
def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
def hash = 'none'
Set<String> contributors = []
try {
def grgit = Grgit.open(dir: '.')
hash = grgit.head().id
grgit.log().each {
if (!blacklist.contains(it.author.name)) contributors.add(it.author.name)
if (!blacklist.contains(it.committer.name)) contributors.add(it.committer.name)
}
def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
grgit.log().each {
if (!blacklist.contains(it.author.name)) contributors.add(it.author.name)
if (!blacklist.contains(it.committer.name)) contributors.add(it.committer.name)
}
} catch(Exception ignored) { }
inputs.property "commithash", hash
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'

View File

@@ -235,7 +235,8 @@ public class ComputerCraft
}
@Deprecated
public static class Upgrades {
public static class Upgrades
{
public static TurtleModem advancedModem;
}

View File

@@ -7,6 +7,10 @@
package dan200.computercraft.client;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.shared.media.items.ItemDiskLegacy;
import dan200.computercraft.shared.turtle.items.ItemTurtleBase;
import dan200.computercraft.shared.util.Colour;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemMeshDefinition;
import net.minecraft.client.renderer.block.model.IBakedModel;
@@ -17,6 +21,7 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
@@ -35,7 +40,7 @@ import javax.annotation.Nonnull;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT )
public class ClientRegistry
{
private static final String[] TURTLE_UPGRADES = {
private static final String[] EXTRA_MODELS = {
"turtle_modem_off_left",
"turtle_modem_on_left",
"turtle_modem_off_right",
@@ -48,11 +53,16 @@ public class ClientRegistry
"advanced_turtle_modem_on_right",
"turtle_speaker_upgrade_left",
"turtle_speaker_upgrade_right",
"turtle_white",
"turtle_elf_overlay",
};
@SubscribeEvent
public static void registerModels( ModelRegistryEvent event )
{
ModelLoaderRegistry.registerLoader( TurtleModelLoader.INSTANCE );
// Register item models
registerUniversalItemModel( ComputerCraft.Items.computer, "computer" );
registerItemModel( ComputerCraft.Items.commandComputer, 0, "command_computer" );
@@ -79,35 +89,70 @@ public class ClientRegistry
registerItemModel( ComputerCraft.Items.printout, 1, "pages" );
registerItemModel( ComputerCraft.Items.printout, 2, "book" );
String[] extraTurtleModels = new String[] { "turtle", "turtle_advanced", "turtle_white", "turtle_elf_overlay" };
registerUniversalItemModel( ComputerCraft.Items.turtle, "turtle_dynamic", extraTurtleModels );
registerUniversalItemModel( ComputerCraft.Items.turtleExpanded, "turtle_dynamic", extraTurtleModels );
registerUniversalItemModel( ComputerCraft.Items.turtleAdvanced, "turtle_dynamic", extraTurtleModels );
registerUniversalItemModel( ComputerCraft.Items.turtle, "turtle" );
registerUniversalItemModel( ComputerCraft.Items.turtleExpanded, "turtle" );
registerUniversalItemModel( ComputerCraft.Items.turtleAdvanced, "turtle_advanced" );
}
@SubscribeEvent
public static void onTextureStitchEvent( TextureStitchEvent.Pre event )
{
// Load all textures for upgrades
// Load all textures for the extra models
TextureMap map = event.getMap();
for( String upgrade : TURTLE_UPGRADES )
for( String upgrade : EXTRA_MODELS )
{
IModel model = ModelLoaderRegistry.getModelOrMissing( new ResourceLocation( "computercraft", "block/" + upgrade ) );
for( ResourceLocation texture : model.getTextures() )
{
map.registerSprite( texture );
}
for( ResourceLocation texture : model.getTextures() ) map.registerSprite( texture );
}
}
@SubscribeEvent
public static void onModelBakeEvent( ModelBakeEvent event )
{
// Load all upgrade models
for( String upgrade : TURTLE_UPGRADES )
{
loadBlockModel( event, upgrade );
}
// Load all extra models
for( String model : EXTRA_MODELS ) loadBlockModel( event, model );
}
@SubscribeEvent
public static void onItemColours( ColorHandlerEvent.Item event )
{
event.getItemColors().registerItemColorHandler(
( stack, layer ) -> layer == 0 ? 0xFFFFFF : ((ItemDiskLegacy) stack.getItem()).getColour( stack ),
ComputerCraft.Items.disk, ComputerCraft.Items.diskExpanded
);
event.getItemColors().registerItemColorHandler( ( stack, layer ) -> {
switch( layer )
{
case 0:
default:
return 0xFFFFFF;
case 1:
{
// Frame colour
int colour = ComputerCraft.Items.pocketComputer.getColour( stack );
return colour == -1 ? 0xFFFFFF : colour;
}
case 2:
{
// Light colour
int colour = ComputerCraft.Items.pocketComputer.getLightState( stack );
return colour == -1 ? Colour.Black.getHex() : colour;
}
}
}, ComputerCraft.Items.pocketComputer );
// Setup turtle colours
event.getItemColors().registerItemColorHandler( ( stack, tintIndex ) -> {
if( tintIndex == 0 )
{
ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem();
int colour = turtle.getColour( stack );
if( colour != -1 ) return colour;
}
return 0xFFFFFF;
}, ComputerCraft.Blocks.turtle, ComputerCraft.Blocks.turtleExpanded, ComputerCraft.Blocks.turtleAdvanced );
}
private static void registerItemModel( Item item, int damage, String name )
@@ -118,18 +163,10 @@ public class ClientRegistry
ModelLoader.setCustomModelResourceLocation( item, damage, res );
}
private static void registerUniversalItemModel( Item item, String mainModel, String... extraModels )
private static void registerUniversalItemModel( Item item, String mainModel )
{
ResourceLocation mainLocation = new ResourceLocation( ComputerCraft.MOD_ID, mainModel );
ResourceLocation[] modelLocations = new ResourceLocation[extraModels.length + 1];
modelLocations[0] = mainLocation;
for( int i = 0; i < extraModels.length; i++ )
{
modelLocations[i + 1] = new ResourceLocation( ComputerCraft.MOD_ID, extraModels[i] );
}
ModelBakery.registerItemVariants( item, modelLocations );
ModelBakery.registerItemVariants( item, mainLocation );
final ModelResourceLocation mainModelLocation = new ModelResourceLocation( mainLocation, "inventory" );
ModelLoader.setCustomMeshDefinition( item, new ItemMeshDefinition()

View File

@@ -6,69 +6,19 @@
package dan200.computercraft.client.proxy;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
import dan200.computercraft.client.render.TurtleSmartItemModel;
import dan200.computercraft.shared.proxy.CCTurtleProxyCommon;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.items.ItemTurtleBase;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.resources.IResourceManager;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class CCTurtleProxyClient extends CCTurtleProxyCommon
{
@Override
public void preInit()
{
super.preInit();
MinecraftForge.EVENT_BUS.register( new ForgeHandlers() );
}
@Override
public void init()
{
super.init();
// Setup turtle colours
Minecraft.getMinecraft().getItemColors().registerItemColorHandler( ( stack, tintIndex ) -> {
if( tintIndex == 0 )
{
ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem();
int colour = turtle.getColour( stack );
if( colour != -1 ) return colour;
}
return 0xFFFFFF;
}, ComputerCraft.Blocks.turtle, ComputerCraft.Blocks.turtleExpanded, ComputerCraft.Blocks.turtleAdvanced );
// Setup renderers
ClientRegistry.bindTileEntitySpecialRenderer( TileTurtle.class, new TileEntityTurtleRenderer() );
}
public static class ForgeHandlers
{
private final TurtleSmartItemModel m_turtleSmartItemModel = new TurtleSmartItemModel();
ForgeHandlers()
{
IResourceManager resourceManager = Minecraft.getMinecraft().getResourceManager();
if( resourceManager instanceof IReloadableResourceManager )
{
((IReloadableResourceManager) resourceManager).registerReloadListener( m_turtleSmartItemModel );
}
}
@SubscribeEvent
public void onModelBakeEvent( ModelBakeEvent event )
{
event.getModelRegistry().putObject( new ModelResourceLocation( "computercraft:turtle_dynamic", "inventory" ), m_turtleSmartItemModel );
}
}
}

View File

@@ -10,24 +10,16 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.render.TileEntityCableRenderer;
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
import dan200.computercraft.shared.command.CommandCopy;
import dan200.computercraft.shared.media.items.ItemDiskLegacy;
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
import dan200.computercraft.shared.util.Colour;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.color.IItemColor;
import net.minecraft.item.ItemStack;
import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nonnull;
public class ComputerCraftProxyClient extends ComputerCraftProxyCommon
{
@@ -45,33 +37,6 @@ public class ComputerCraftProxyClient extends ComputerCraftProxyCommon
{
super.init();
Minecraft mc = Minecraft.getMinecraft();
// Setup
mc.getItemColors().registerItemColorHandler( new DiskColorHandler( ComputerCraft.Items.disk ), ComputerCraft.Items.disk );
mc.getItemColors().registerItemColorHandler( new DiskColorHandler( ComputerCraft.Items.diskExpanded ), ComputerCraft.Items.diskExpanded );
mc.getItemColors().registerItemColorHandler( ( stack, layer ) -> {
switch( layer )
{
case 0:
default:
return 0xFFFFFF;
case 1:
{
// Frame colour
int colour = ComputerCraft.Items.pocketComputer.getColour( stack );
return colour == -1 ? 0xFFFFFF : colour;
}
case 2:
{
// Light colour
int colour = ComputerCraft.Items.pocketComputer.getLightState( stack );
return colour == -1 ? Colour.Black.getHex() : colour;
}
}
}, ComputerCraft.Items.pocketComputer );
// Setup renderers
ClientRegistry.bindTileEntitySpecialRenderer( TileMonitor.class, new TileEntityMonitorRenderer() );
ClientRegistry.bindTileEntitySpecialRenderer( TileCable.class, new TileEntityCableRenderer() );
@@ -90,20 +55,5 @@ public class ComputerCraftProxyClient extends ComputerCraftProxyCommon
}
}
@SideOnly( Side.CLIENT )
private static class DiskColorHandler implements IItemColor
{
private final ItemDiskLegacy disk;
private DiskColorHandler( ItemDiskLegacy disk )
{
this.disk = disk;
}
@Override
public int colorMultiplier( @Nonnull ItemStack stack, int layer )
{
return layer == 0 ? 0xFFFFFF : disk.getColour( stack );
}
}
}

View File

@@ -0,0 +1,188 @@
package dan200.computercraft.client.render;
import com.google.common.collect.Sets;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.shared.wired.WiredNetwork;
import dan200.computercraft.shared.wired.WiredNode;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.util.Collection;
import java.util.Set;
/**
* This is a helper to render a network when testing.
*/
public final class RenderOverlayNetwork
{
private int ticksInGame;
private IWiredElement element;
@SubscribeEvent
public void onWorldRenderLast( RenderWorldLastEvent event )
{
++ticksInGame;
RayTraceResult result = Minecraft.getMinecraft().objectMouseOver;
if( result != null && result.typeOfHit == RayTraceResult.Type.BLOCK )
{
World clientWorld = Minecraft.getMinecraft().world;
World world = FMLCommonHandler.instance().getMinecraftServerInstance().getWorld( clientWorld.provider.getDimension() );
IWiredElement newElement = ComputerCraft.getWiredElementAt( world, result.getBlockPos(), result.sideHit );
if( newElement != null ) element = newElement;
}
if( element == null ) return;
Minecraft minecraft = Minecraft.getMinecraft();
ItemStack stack = minecraft.player.getHeldItemMainhand();
ItemStack otherStack = minecraft.player.getHeldItemOffhand();
if( stack.getItem() != Items.STICK && otherStack.getItem() != Items.STICK ) return;
GlStateManager.pushMatrix();
RenderManager renderManager = minecraft.getRenderManager();
GlStateManager.translate( -renderManager.viewerPosX, -renderManager.viewerPosY, -renderManager.viewerPosZ );
GlStateManager.disableDepth();
GlStateManager.disableTexture2D();
GlStateManager.enableBlend();
GlStateManager.blendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA );
Set<Pair<IWiredElement>> connections = Sets.newHashSet();
WiredNetwork network = (WiredNetwork) element.getNode().getNetwork();
for( WiredNode node : network.getNodes() )
{
for( WiredNode other : node.getNeighbours() )
{
connections.add( new Pair<>( node.getElement(), other.getElement() ) );
}
}
renderNetworkConnections( connections, new Color( Color.HSBtoRGB( ticksInGame % 200 / 200F, 0.6F, 1F ) ), 1f );
GlStateManager.enableDepth();
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
GlStateManager.popMatrix();
}
private void renderNetworkConnections( Collection<Pair<IWiredElement>> data, Color color, float thickness )
{
renderConnections( data, color, 1.0f, thickness );
renderConnections( data, color, 64.0f / 255.0f, thickness * 3 );
}
private void renderConnections( Collection<Pair<IWiredElement>> connections, Color color, float alpha, float thickness )
{
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBuffer();
GlStateManager.pushMatrix();
GlStateManager.scale( 1, 1, 1 );
GlStateManager.color( color.getRed() / 255.0f, color.getGreen() / 255.0f, color.getBlue() / 255.0f, alpha );
GL11.glLineWidth( thickness );
renderer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION );
for( Pair<IWiredElement> connection : connections )
{
Vec3d a = connection.x.getPosition(), b = connection.y.getPosition();
renderer.pos( a.x, a.y, a.z ).endVertex();
renderer.pos( b.x, b.y, b.z ).endVertex();
}
tessellator.draw();
GlStateManager.popMatrix();
}
private void renderLabel( double x, double y, double z, String label )
{
RenderManager renderManager = Minecraft.getMinecraft().getRenderManager();
FontRenderer fontrenderer = renderManager.getFontRenderer();
if( fontrenderer == null ) return;
GlStateManager.pushMatrix();
GlStateManager.disableLighting();
float scale = 0.02666667f;
GlStateManager.translate( x, y, z );
GlStateManager.rotate( -renderManager.playerViewY, 0, 1, 0 );
GlStateManager.rotate( renderManager.playerViewX, 1, 0, 0 );
GlStateManager.scale( -scale, -scale, scale );
// Render label background
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBuffer();
int width = fontrenderer.getStringWidth( label );
int xOffset = width / 2;
GlStateManager.disableTexture2D();
GlStateManager.color( 0, 0, 0, 65 / 225.0f );
renderer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION );
renderer.pos( -xOffset - 1, -1, 0 ).endVertex();
renderer.pos( -xOffset - 1, 8, 0 ).endVertex();
renderer.pos( xOffset + 1, 8, 0 ).endVertex();
renderer.pos( xOffset + 1, -1, 0 ).endVertex();
tessellator.draw();
GlStateManager.enableTexture2D();
// Render label
fontrenderer.drawString( label, -width / 2, 0, 0xFFFFFFFF );
GlStateManager.enableLighting();
GlStateManager.popMatrix();
}
private static class Pair<T>
{
public final T x;
public final T y;
public Pair( T right, T y )
{
this.x = right;
this.y = y;
}
@Override
public boolean equals( Object o )
{
if( this == o ) return true;
if( o == null || getClass() != o.getClass() ) return false;
Pair<?> p = (Pair<?>) o;
return (x.equals( p.x ) && y.equals( p.y ))
|| (x.equals( p.y ) && y.equals( p.x ));
}
@Override
public int hashCode()
{
return x.hashCode() ^ y.hashCode();
}
}
}

View File

@@ -14,23 +14,20 @@ import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.block.model.ModelManager;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.pipeline.LightUtil;
@@ -43,7 +40,7 @@ import java.util.List;
public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurtle>
{
private static final ModelResourceLocation NORMAL_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle", "inventory" );
private static final ModelResourceLocation ADVANCED_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_advanced", "inventory" );
private static final ModelResourceLocation ADVANCED_TURTLE_MODEL = new ModelResourceLocation( "computercraft:advanced_turtle", "inventory" );
private static final ModelResourceLocation COLOUR_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_white", "inventory" );
private static final ModelResourceLocation ELF_OVERLAY_MODEL = new ModelResourceLocation( "computercraft:turtle_elf_overlay", "inventory" );
@@ -65,7 +62,7 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
}
}
public static ModelResourceLocation getTurtleOverlayModel( ComputerFamily family, ResourceLocation overlay, boolean christmas )
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
{
if( overlay != null )
{
@@ -83,6 +80,19 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
private void renderTurtleAt( TileTurtle turtle, double posX, double posY, double posZ, float f, int i )
{
// Render the label
String label = turtle.createProxy().getLabel();
if( label != null && rendererDispatcher.cameraHitResult != null && turtle.getPos().equals( rendererDispatcher.cameraHitResult.getBlockPos() ) )
{
setLightmapDisabled( true );
EntityRenderer.drawNameplate(
getFontRenderer(), label,
(float) posX + 0.5F, (float) posY + 1.2F, (float) posZ + 0.5F, 0,
rendererDispatcher.entityYaw, rendererDispatcher.entityPitch, false, false
);
setLightmapDisabled( false );
}
IBlockState state = turtle.getWorld().getBlockState( turtle.getPos() );
GlStateManager.pushMatrix();
try
@@ -94,13 +104,6 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
yaw = turtle.getRenderYaw( f );
GlStateManager.translate( posX + offset.x, posY + offset.y, posZ + offset.z );
// Render the label
String label = turtle.createProxy().getLabel();
if( label != null )
{
renderLabel( turtle.getAccess().getPosition(), label );
}
// Render the turtle
GlStateManager.translate( 0.5f, 0.5f, 0.5f );
GlStateManager.rotate( 180.0f - yaw, 0.0f, 1.0f, 0.0f );
@@ -123,7 +126,6 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
// Render the overlay
ModelResourceLocation overlayModel = getTurtleOverlayModel(
family,
overlay,
HolidayUtil.getCurrentHoliday() == Holiday.Christmas
);
@@ -232,72 +234,4 @@ public class TileEntityTurtleRenderer extends TileEntitySpecialRenderer<TileTurt
}
tessellator.draw();
}
private void renderLabel( BlockPos position, String label )
{
Minecraft mc = Minecraft.getMinecraft();
RayTraceResult mop = mc.objectMouseOver;
if( mop != null && mop.typeOfHit == RayTraceResult.Type.BLOCK && mop.getBlockPos().equals( position ) )
{
RenderManager renderManager = mc.getRenderManager();
FontRenderer fontrenderer = renderManager.getFontRenderer();
float scale = 0.016666668F * 1.6f;
GlStateManager.pushMatrix();
GlStateManager.disableLighting();
GlStateManager.enableBlend();
GlStateManager.blendFunc( GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA );
try
{
GlStateManager.translate( 0.5f, 1.25f, 0.5f );
GlStateManager.rotate( -renderManager.playerViewY, 0.0F, 1.0F, 0.0F );
GlStateManager.rotate( renderManager.playerViewX, 1.0F, 0.0F, 0.0F );
GlStateManager.scale( -scale, -scale, scale );
int yOffset = 0;
int xOffset = fontrenderer.getStringWidth( label ) / 2;
// Draw background
GlStateManager.depthMask( false );
GlStateManager.disableDepth();
try
{
// Quad
GlStateManager.disableTexture2D();
try
{
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBuffer();
renderer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR );
renderer.pos( -xOffset - 1, -1 + yOffset, 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex();
renderer.pos( -xOffset - 1, 8 + yOffset, 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex();
renderer.pos( xOffset + 1, 8 + yOffset, 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex();
renderer.pos( xOffset + 1, -1 + yOffset, 0.0D ).color( 0.0F, 0.0F, 0.0F, 0.25F ).endVertex();
tessellator.draw();
}
finally
{
GlStateManager.enableTexture2D();
}
// Text
fontrenderer.drawString( label, -fontrenderer.getStringWidth( label ) / 2, yOffset, 0x20ffffff );
}
finally
{
GlStateManager.enableDepth();
GlStateManager.depthMask( true );
}
// Draw foreground text
fontrenderer.drawString( label, -fontrenderer.getStringWidth( label ) / 2, yOffset, -1 );
}
finally
{
GlStateManager.disableBlend();
GlStateManager.enableLighting();
GlStateManager.popMatrix();
}
}
}
}

View File

@@ -0,0 +1,121 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.render;
import com.google.common.collect.ImmutableMap;
import dan200.computercraft.ComputerCraft;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ICustomModelLoader;
import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.IModelState;
import javax.annotation.Nonnull;
import java.util.function.Function;
public class TurtleModelLoader implements ICustomModelLoader
{
private static final ResourceLocation NORMAL_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle" );
private static final ResourceLocation ADVANCED_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/advanced_turtle" );
private static final ResourceLocation COLOUR_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_white" );
public static final TurtleModelLoader INSTANCE = new TurtleModelLoader();
private TurtleModelLoader()
{
}
@Override
public void onResourceManagerReload( @Nonnull IResourceManager manager )
{
}
@Override
public boolean accepts( @Nonnull ResourceLocation name )
{
return name.getNamespace().equals( ComputerCraft.MOD_ID )
&& (name.getPath().equals( "turtle" ) || name.getPath().equals( "turtle_advanced" ));
}
@Nonnull
@Override
public IModel loadModel( @Nonnull ResourceLocation name ) throws Exception
{
if( name.getNamespace().equals( ComputerCraft.MOD_ID ) )
{
IModel colourModel = ModelLoaderRegistry.getModel( COLOUR_TURTLE_MODEL );
switch( name.getPath() )
{
case "turtle":
return new TurtleModel( ModelLoaderRegistry.getModel( NORMAL_TURTLE_MODEL ), colourModel );
case "turtle_advanced":
return new TurtleModel( ModelLoaderRegistry.getModel( ADVANCED_TURTLE_MODEL ), colourModel );
}
}
throw new IllegalStateException( "Loader does not accept " + name );
}
private static class TurtleModel implements IModel
{
private final IModel family;
private final IModel colour;
private TurtleModel( IModel family, IModel colour )
{
this.family = family;
this.colour = colour;
}
@Nonnull
@Override
public IBakedModel bake( @Nonnull IModelState state, @Nonnull VertexFormat format, @Nonnull Function<ResourceLocation, TextureAtlasSprite> function )
{
return new TurtleSmartItemModel(
family.bake( state, format, function ),
colour.bake( state, format, function )
);
}
private TurtleModel copy( IModel family, IModel colour )
{
return this.family == family && this.colour == colour ? this : new TurtleModel( family, colour );
}
@Nonnull
@Override
public IModel smoothLighting( boolean value )
{
return copy( family.smoothLighting( value ), colour.smoothLighting( value ) );
}
@Nonnull
@Override
public IModel gui3d( boolean value )
{
return copy( family.gui3d( value ), colour.gui3d( value ) );
}
@Nonnull
@Override
public IModel uvlock( boolean value )
{
return copy( family.uvlock( value ), colour.uvlock( value ) );
}
@Nonnull
@Override
public IModel retexture( ImmutableMap<String, String> textures )
{
return copy( family.retexture( textures ), colour.retexture( textures ) );
}
}
}

View File

@@ -9,7 +9,6 @@ package dan200.computercraft.client.render;
import com.google.common.base.Objects;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.turtle.items.ItemTurtleBase;
import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
@@ -17,15 +16,11 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.client.resource.IResourceType;
import net.minecraftforge.client.resource.ISelectiveResourceReloadListener;
import net.minecraftforge.client.resource.VanillaResourceType;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
@@ -34,9 +29,8 @@ import javax.vecmath.Matrix4f;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Predicate;
public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceReloadListener
public class TurtleSmartItemModel implements IBakedModel
{
private static final Matrix4f s_identity, s_flip;
@@ -53,17 +47,15 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
private static class TurtleModelCombination
{
public final ComputerFamily m_family;
public final boolean m_colour;
public final ITurtleUpgrade m_leftUpgrade;
public final ITurtleUpgrade m_rightUpgrade;
public final ResourceLocation m_overlay;
public final boolean m_christmas;
public final boolean m_flip;
final boolean m_colour;
final ITurtleUpgrade m_leftUpgrade;
final ITurtleUpgrade m_rightUpgrade;
final ResourceLocation m_overlay;
final boolean m_christmas;
final boolean m_flip;
public TurtleModelCombination( ComputerFamily family, boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas, boolean flip )
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas, boolean flip )
{
m_family = family;
m_colour = colour;
m_leftUpgrade = leftUpgrade;
m_rightUpgrade = rightUpgrade;
@@ -79,8 +71,7 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
if( !(other instanceof TurtleModelCombination) ) return false;
TurtleModelCombination otherCombo = (TurtleModelCombination) other;
return otherCombo.m_family == m_family &&
otherCombo.m_colour == m_colour &&
return otherCombo.m_colour == m_colour &&
otherCombo.m_leftUpgrade == m_leftUpgrade &&
otherCombo.m_rightUpgrade == m_rightUpgrade &&
Objects.equal( otherCombo.m_overlay, m_overlay ) &&
@@ -92,8 +83,7 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + m_family.hashCode();
int result = 0;
result = prime * result + (m_colour ? 1 : 0);
result = prime * result + (m_leftUpgrade != null ? m_leftUpgrade.hashCode() : 0);
result = prime * result + (m_rightUpgrade != null ? m_rightUpgrade.hashCode() : 0);
@@ -104,14 +94,18 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
}
}
private final IBakedModel familyModel;
private final IBakedModel colourModel;
private HashMap<TurtleModelCombination, IBakedModel> m_cachedModels;
private ItemOverrideList m_overrides;
private final TurtleModelCombination m_defaultCombination;
public TurtleSmartItemModel()
public TurtleSmartItemModel( IBakedModel familyModel, IBakedModel colourModel )
{
this.familyModel = familyModel;
this.colourModel = colourModel;
m_cachedModels = new HashMap<>();
m_defaultCombination = new TurtleModelCombination( ComputerFamily.Normal, false, null, null, null, false, false );
m_overrides = new ItemOverrideList( new ArrayList<>() )
{
@Nonnull
@@ -119,7 +113,6 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
public IBakedModel handleItemState( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable EntityLivingBase entity )
{
ItemTurtleBase turtle = (ItemTurtleBase) stack.getItem();
ComputerFamily family = turtle.getFamily( stack );
int colour = turtle.getColour( stack );
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.Left );
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.Right );
@@ -127,17 +120,11 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.Christmas;
String label = turtle.getLabel( stack );
boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
TurtleModelCombination combo = new TurtleModelCombination( family, colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
if( m_cachedModels.containsKey( combo ) )
{
return m_cachedModels.get( combo );
}
else
{
IBakedModel model = buildModel( combo );
m_cachedModels.put( combo, model );
return model;
}
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
IBakedModel model = m_cachedModels.get( combo );
if( model == null ) m_cachedModels.put( combo, model = buildModel( combo ) );
return model;
}
};
}
@@ -149,19 +136,13 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
return m_overrides;
}
@Override
public void onResourceManagerReload( @Nonnull IResourceManager resourceManager, @Nonnull Predicate<IResourceType> resourcePredicate )
{
if( resourcePredicate.test( VanillaResourceType.MODELS ) ) m_cachedModels.clear();
}
private IBakedModel buildModel( TurtleModelCombination combo )
{
Minecraft mc = Minecraft.getMinecraft();
ModelManager modelManager = mc.getRenderItem().getItemModelMesher().getModelManager();
ModelResourceLocation baseModelLocation = TileEntityTurtleRenderer.getTurtleModel( combo.m_family, combo.m_colour );
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_family, combo.m_overlay, combo.m_christmas );
IBakedModel baseModel = modelManager.getModel( baseModelLocation );
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_overlay, combo.m_christmas );
IBakedModel baseModel = combo.m_colour ? colourModel : familyModel;
IBakedModel overlayModel = (overlayModelLocation != null) ? modelManager.getModel( overlayModelLocation ) : null;
Matrix4f transform = combo.m_flip ? s_flip : s_identity;
Pair<IBakedModel, Matrix4f> leftModel = (combo.m_leftUpgrade != null) ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
@@ -184,38 +165,36 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
}
}
// These should not be called:
@Nonnull
@Override
public List<BakedQuad> getQuads( IBlockState state, EnumFacing facing, long rand )
{
return getDefaultModel().getQuads( state, facing, rand );
return familyModel.getQuads( state, facing, rand );
}
@Override
public boolean isAmbientOcclusion()
{
return getDefaultModel().isAmbientOcclusion();
return familyModel.isAmbientOcclusion();
}
@Override
public boolean isGui3d()
{
return getDefaultModel().isGui3d();
return familyModel.isGui3d();
}
@Override
public boolean isBuiltInRenderer()
{
return getDefaultModel().isBuiltInRenderer();
return familyModel.isBuiltInRenderer();
}
@Nonnull
@Override
public TextureAtlasSprite getParticleTexture()
{
return getDefaultModel().getParticleTexture();
return familyModel.getParticleTexture();
}
@Nonnull
@@ -223,18 +202,7 @@ public class TurtleSmartItemModel implements IBakedModel, ISelectiveResourceRelo
@Deprecated
public ItemCameraTransforms getItemCameraTransforms()
{
return getDefaultModel().getItemCameraTransforms();
return familyModel.getItemCameraTransforms();
}
private IBakedModel getDefaultModel()
{
IBakedModel model = m_cachedModels.get( m_defaultCombination );
if( model == null )
{
model = buildModel( m_defaultCombination );
m_cachedModels.put( m_defaultCombination, model );
}
return model;
}
}

View File

@@ -161,7 +161,10 @@ public class Websocket extends Resource<Websocket>
}
} )
.remoteAddress( socketAddress )
.connect();
.connect()
.addListener( c -> {
if( !c.isSuccess() ) failure( c.cause().getMessage() );
} );
// Do an additional check for cancellation
checkClosed();

View File

@@ -16,6 +16,7 @@ import java.util.WeakHashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.locks.LockSupport;
public class ComputerThread
{
@@ -216,22 +217,37 @@ public class ComputerThread
// Interrupt the thread
if( !done )
{
StringBuilder builder = new StringBuilder( "Terminating " );
if( computer != null )
if( ComputerCraft.logPeripheralErrors )
{
builder.append( "computer " ).append( computer.getID() );
}
else
{
builder.append( "unknown computer" );
}
long time = System.nanoTime() - start;
StringBuilder builder = new StringBuilder( "Terminating " );
if( computer != null )
{
builder.append( "computer #" ).append( computer.getID() );
}
else
{
builder.append( "unknown computer" );
}
builder.append( ". Thread is currently running" );
for( StackTraceElement element : thread.getStackTrace() )
{
builder.append( "\n at " ).append( element );
{
builder.append( " due to timeout (running for " )
.append( time / 1e9 )
.append( " seconds). This is NOT a bug, but may mean a computer is misbehaving. " )
.append( thread.getName() )
.append( " is currently " )
.append( thread.getState() );
Object blocking = LockSupport.getBlocker( thread );
if( blocking != null ) builder.append( "\n on " ).append( blocking );
for( StackTraceElement element : thread.getStackTrace() )
{
builder.append( "\n at " ).append( element );
}
}
ComputerCraft.log.warn( builder.toString() );
}
ComputerCraft.log.error( builder.toString() );
thread.interrupt();
thread = null;

View File

@@ -46,7 +46,7 @@ public class CobaltLuaMachine implements ILuaMachine
{
private static final ThreadPoolExecutor coroutines = new ThreadPoolExecutor(
0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
5L, TimeUnit.MINUTES,
new SynchronousQueue<>(),
ThreadUtils.factory( "Coroutine" )
);
@@ -74,12 +74,12 @@ public class CobaltLuaMachine implements ILuaMachine
private boolean hasSoftAbort;
@Override
public void onInstruction( DebugState ds, DebugFrame di, int pc, Varargs extras, int top ) throws LuaError
public void onInstruction( DebugState ds, DebugFrame di, int pc ) throws LuaError, UnwindThrowable
{
int count = ++this.count;
if( count > 100000 )
{
if( m_hardAbortMessage != null ) LuaThread.yield( m_state, NONE );
if( m_hardAbortMessage != null ) throw HardAbortError.INSTANCE;
this.count = 0;
}
else
@@ -87,13 +87,13 @@ public class CobaltLuaMachine implements ILuaMachine
handleSoftAbort();
}
super.onInstruction( ds, di, pc, extras, top );
super.onInstruction( ds, di, pc );
}
@Override
public void poll() throws LuaError
{
if( m_hardAbortMessage != null ) LuaThread.yield( m_state, NONE );
if( m_hardAbortMessage != null ) throw HardAbortError.INSTANCE;
handleSoftAbort();
}
@@ -117,7 +117,7 @@ public class CobaltLuaMachine implements ILuaMachine
throw new LuaError( message );
}
} )
.coroutineFactory( command -> {
.yieldThreader( command -> {
Tracking.addValue( m_computer, TrackingField.COROUTINES_CREATED, 1 );
coroutines.execute( () -> {
try
@@ -145,10 +145,10 @@ public class CobaltLuaMachine implements ILuaMachine
if( ComputerCraft.debug_enable ) m_globals.load( state, new DebugLib() );
// Register custom load/loadstring provider which automatically adds prefixes.
LibFunction.bind( state, m_globals, PrefixLoader.class, new String[] { "load", "loadstring" } );
LibFunction.bind( m_globals, PrefixLoader.class, new String[] { "load", "loadstring" } );
// Remove globals we don't want to expose
// m_globals.rawset( "collectgarbage", Constants.NIL );
m_globals.rawset( "collectgarbage", Constants.NIL );
m_globals.rawset( "dofile", Constants.NIL );
m_globals.rawset( "loadfile", Constants.NIL );
m_globals.rawset( "print", Constants.NIL );
@@ -222,26 +222,18 @@ public class CobaltLuaMachine implements ILuaMachine
resumeArgs = varargsOf( valueOf( eventName ), toValues( arguments ) );
}
Varargs results = m_mainRoutine.resume( resumeArgs );
if( m_hardAbortMessage != null )
{
throw new LuaError( m_hardAbortMessage );
}
else if( !results.first().checkBoolean() )
{
throw new LuaError( results.arg( 2 ).checkString() );
}
else
{
LuaValue filter = results.arg( 2 );
m_eventFilter = filter.isString() ? filter.toString() : null;
}
Varargs results = LuaThread.run( m_mainRoutine, resumeArgs );
if( m_hardAbortMessage != null ) throw new LuaError( m_hardAbortMessage );
LuaValue filter = results.first();
m_eventFilter = filter.isString() ? filter.toString() : null;
if( m_mainRoutine.getStatus().equals( "dead" ) ) unload();
}
catch( LuaError e )
catch( LuaError | HardAbortError e )
{
unload();
ComputerCraft.log.warn( "Top level coroutine errored", e );
}
finally
{
@@ -339,16 +331,12 @@ public class CobaltLuaMachine implements ILuaMachine
{
try
{
Varargs results = LuaThread.yield( state, toValues( yieldArgs ) );
Varargs results = LuaThread.yieldBlocking( state, toValues( yieldArgs ) );
return toObjects( results, 1 );
}
catch( OrphanedThread e )
catch( LuaError e )
{
throw new InterruptedException();
}
catch( Throwable e )
{
throw new RuntimeException( e );
throw new IllegalStateException( e );
}
}
@@ -699,7 +687,7 @@ public class CobaltLuaMachine implements ILuaMachine
LuaValue s;
try
{
s = OperationHelper.call( state, func );
s = OperationHelper.noYield( state, () -> OperationHelper.call( state, func ) );
}
catch( LuaError e )
{
@@ -731,4 +719,16 @@ public class CobaltLuaMachine implements ILuaMachine
return bytes[offset++];
}
}
private static class HardAbortError extends Error
{
private static final long serialVersionUID = 7954092008586367501L;
public static final HardAbortError INSTANCE = new HardAbortError();
private HardAbortError()
{
super( "Hard Abort", null, true, false );
}
}
}

View File

@@ -11,11 +11,9 @@ import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
@@ -35,96 +33,32 @@ public abstract class BlockGeneric extends Block implements ITileEntityProvider
protected abstract TileGeneric createTile( int damage );
@Override
public final void dropBlockAsItemWithChance( World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, float chance, int fortune )
{
}
@Override
public final void getDrops( @Nonnull NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos, @Nonnull IBlockState state, int fortune )
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric )
{
TileGeneric generic = (TileGeneric) tile;
generic.getDroppedItems( drops, false );
}
}
@Override
public boolean removedByPlayer( @Nonnull IBlockState state, World world, @Nonnull BlockPos pos, @Nonnull EntityPlayer player, boolean willHarvest )
{
if( !world.isRemote )
{
// Drop items
boolean creative = player.capabilities.isCreativeMode;
dropAllItems( world, pos, creative );
}
// Remove block
return super.removedByPlayer( state, world, pos, player, willHarvest );
}
public final void dropAllItems( World world, BlockPos pos, boolean creative )
{
// Get items to drop
NonNullList<ItemStack> drops = NonNullList.create();
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric )
{
TileGeneric generic = (TileGeneric) tile;
generic.getDroppedItems( drops, creative );
}
// Drop items
if( drops.size() > 0 )
{
for( ItemStack item : drops )
{
dropItem( world, pos, item );
}
}
}
public final void dropItem( World world, BlockPos pos, @Nonnull ItemStack stack )
{
Block.spawnAsEntity( world, pos, stack );
}
@Override
public final void breakBlock( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState newState )
{
TileEntity tile = world.getTileEntity( pos );
super.breakBlock( world, pos, newState );
world.removeTileEntity( pos );
if( tile instanceof TileGeneric )
{
TileGeneric generic = (TileGeneric) tile;
generic.destroy();
}
if( tile instanceof TileGeneric ) ((TileGeneric) tile).destroy();
}
@Override
public final boolean onBlockActivated( World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ )
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric )
{
TileGeneric generic = (TileGeneric) tile;
return generic.onActivate( player, hand, side, hitX, hitY, hitZ );
}
return false;
return tile instanceof TileGeneric && ((TileGeneric) tile).onActivate( player, hand, side, hitX, hitY, hitZ );
}
@Override
@Deprecated
public final void neighborChanged( IBlockState state, World world, BlockPos pos, Block block, BlockPos neighorPos )
public final void neighborChanged( IBlockState state, World world, BlockPos pos, Block block, BlockPos neighbour )
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric )
{
TileGeneric generic = (TileGeneric) tile;
generic.onNeighbourChange();
generic.onNeighbourChange( neighbour );
}
}
@@ -132,11 +66,7 @@ public abstract class BlockGeneric extends Block implements ITileEntityProvider
public final void onNeighborChange( IBlockAccess world, BlockPos pos, BlockPos neighbour )
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric )
{
TileGeneric generic = (TileGeneric) tile;
generic.onNeighbourTileEntityChange( neighbour );
}
if( tile instanceof TileGeneric ) ((TileGeneric) tile).onNeighbourTileEntityChange( neighbour );
}
@Override
@@ -157,12 +87,7 @@ public abstract class BlockGeneric extends Block implements ITileEntityProvider
public final boolean canConnectRedstone( IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side )
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric )
{
TileGeneric generic = (TileGeneric) tile;
return generic.getRedstoneConnectivity( side );
}
return false;
return tile instanceof TileGeneric && ((TileGeneric) tile).getRedstoneConnectivity( side );
}
@Override
@@ -172,8 +97,7 @@ public abstract class BlockGeneric extends Block implements ITileEntityProvider
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric && tile.hasWorld() )
{
TileGeneric generic = (TileGeneric) tile;
return generic.getRedstoneOutput( oppositeSide.getOpposite() );
return ((TileGeneric) tile).getRedstoneOutput( oppositeSide.getOpposite() );
}
return 0;
}
@@ -190,8 +114,7 @@ public abstract class BlockGeneric extends Block implements ITileEntityProvider
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric )
{
TileGeneric generic = (TileGeneric) tile;
return generic.getBundledRedstoneConnectivity( side );
return ((TileGeneric) tile).getBundledRedstoneConnectivity( side );
}
return false;
}
@@ -201,8 +124,7 @@ public abstract class BlockGeneric extends Block implements ITileEntityProvider
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileGeneric && tile.hasWorld() )
{
TileGeneric generic = (TileGeneric) tile;
return generic.getBundledRedstoneOutput( side );
return ((TileGeneric) tile).getBundledRedstoneOutput( side );
}
return 0;
}

View File

@@ -9,14 +9,12 @@ package dan200.computercraft.shared.common;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@@ -55,19 +53,20 @@ public abstract class TileGeneric extends TileEntity
getWorld().setBlockState( getPos(), newState, 3 );
}
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
{
}
public boolean onActivate( EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ )
{
return false;
}
@Deprecated
public void onNeighbourChange()
{
}
public void onNeighbourChange( @Nonnull BlockPos neighbour )
{
}
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour )
{
}

View File

@@ -8,11 +8,13 @@ package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.items.ComputerItemFactory;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
@@ -103,4 +105,11 @@ public class BlockCommandComputer extends BlockComputerBase
{
return new TileCommandComputer();
}
@Nonnull
@Override
protected ItemStack getItem( TileComputerBase tile )
{
return tile instanceof TileCommandComputer ? ComputerItemFactory.create( (TileComputer) tile ) : ItemStack.EMPTY;
}
}

View File

@@ -15,14 +15,11 @@ import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -136,9 +133,8 @@ public class BlockComputer extends BlockComputerBase
@Nonnull
@Override
public ItemStack getPickBlock( @Nonnull IBlockState state, RayTraceResult target, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player )
protected ItemStack getItem( TileComputerBase tile )
{
TileEntity tile = world.getTileEntity( pos );
return tile instanceof TileComputer ? ComputerItemFactory.create( (TileComputer) tile ) : super.getPickBlock( state, target, world, pos, player );
return tile instanceof TileComputer ? ComputerItemFactory.create( (TileComputer) tile ) : ItemStack.EMPTY;
}
}

View File

@@ -12,9 +12,13 @@ import dan200.computercraft.shared.util.DirectionUtil;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
@@ -49,6 +53,9 @@ public abstract class BlockComputerBase extends BlockDirectional
protected abstract TileComputerBase createTile( ComputerFamily family );
@Nonnull
protected abstract ItemStack getItem( TileComputerBase tile );
@Nonnull
@Override
@Deprecated
@@ -83,4 +90,55 @@ public abstract class BlockComputerBase extends BlockDirectional
computer.updateInput();
}
}
@Override
@Nonnull
public ItemStack getPickBlock( @Nonnull IBlockState state, RayTraceResult target, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player )
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileComputerBase )
{
ItemStack result = getItem( (TileComputerBase) tile );
if( !result.isEmpty() ) return result;
}
return super.getPickBlock( state, target, world, pos, player );
}
@Override
public final void dropBlockAsItemWithChance( World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, float chance, int fortune )
{
}
@Override
public final void getDrops( @Nonnull NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos, @Nonnull IBlockState state, int fortune )
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileComputerBase )
{
ItemStack stack = getItem( (TileComputerBase) tile );
if( !stack.isEmpty() ) drops.add( stack );
}
}
@Override
public boolean removedByPlayer( @Nonnull IBlockState state, World world, @Nonnull BlockPos pos, @Nonnull EntityPlayer player, boolean willHarvest )
{
if( !world.isRemote )
{
// We drop the item here instead of doing it in the harvest method, as we
// need to drop it for creative players too.
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileComputerBase )
{
TileComputerBase computer = (TileComputerBase) tile;
if( !player.capabilities.isCreativeMode || computer.getLabel() != null )
{
spawnAsEntity( world, pos, getItem( computer ) );
}
}
}
return super.removedByPlayer( state, world, pos, player, willHarvest );
}
}

View File

@@ -9,13 +9,10 @@ package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.items.ComputerItemFactory;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import javax.annotation.Nonnull;
@@ -60,12 +57,6 @@ public class TileComputer extends TileComputerBase
return m_proxy;
}
@Override
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
{
if( !creative || getLabel() != null ) drops.add( ComputerItemFactory.create( this ) );
}
@Override
public void openGUI( EntityPlayer player )
{

View File

@@ -173,9 +173,9 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
}
@Override
public void onNeighbourChange()
public void onNeighbourChange( @Nonnull BlockPos neighbour )
{
updateInput();
updateInput( neighbour );
}
@Override
@@ -296,7 +296,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
int localDir = remapLocalSide( DirectionUtil.toLocal( this, dir ) );
if( !isRedstoneBlockedOnSide( localDir ) )
{
computer.setRedstoneInput( localDir, getWorld().getRedstonePower( offset, offsetSide ) );
computer.setRedstoneInput( localDir, getWorld().getRedstonePower( offset, dir ) );
computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( getWorld(), offset, offsetSide ) );
}
if( !isPeripheralBlockedOnSide( localDir ) )

View File

@@ -29,6 +29,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
@@ -375,17 +376,9 @@ public class BlockPeripheral extends BlockGeneric
{
case DiskDrive:
default:
{
IBlockState state = getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.DiskDriveEmpty );
if( placedSide.getAxis() != EnumFacing.Axis.Y )
{
return state.withProperty( Properties.FACING, placedSide );
}
else
{
return state.withProperty( Properties.FACING, EnumFacing.NORTH );
}
}
return getDefaultState()
.withProperty( Properties.VARIANT, BlockPeripheralVariant.DiskDriveEmpty )
.withProperty( Properties.FACING, placedSide.getAxis() == EnumFacing.Axis.Y ? EnumFacing.NORTH : placedSide );
case WirelessModem:
{
EnumFacing dir = placedSide.getOpposite();
@@ -409,21 +402,13 @@ public class BlockPeripheral extends BlockGeneric
}
}
case Monitor:
{
return getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.Monitor );
}
case Printer:
{
return getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.PrinterEmpty );
}
case AdvancedMonitor:
{
return getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.AdvancedMonitor );
}
case Speaker:
{
return getDefaultState().withProperty( Properties.VARIANT, BlockPeripheralVariant.Speaker );
}
}
}
@@ -465,19 +450,15 @@ public class BlockPeripheral extends BlockGeneric
case Speaker:
case DiskDrive:
case Printer:
{
EnumFacing dir = DirectionUtil.fromEntityRot( player );
if( stack.hasDisplayName() && tile instanceof TilePeripheralBase )
if( tile instanceof TilePeripheralBase )
{
TilePeripheralBase peripheral = (TilePeripheralBase) tile;
peripheral.setLabel( stack.getDisplayName() );
peripheral.setDirection( dir );
peripheral.setDirection( DirectionUtil.fromEntityRot( player ) );
if( stack.hasDisplayName() ) peripheral.setLabel( stack.getDisplayName() );
}
break;
}
case Monitor:
case AdvancedMonitor:
{
if( tile instanceof TileMonitor )
{
int direction = DirectionUtil.fromEntityRot( player ).getIndex();
@@ -504,7 +485,6 @@ public class BlockPeripheral extends BlockGeneric
}
}
break;
}
}
}
@@ -600,4 +580,10 @@ public class BlockPeripheral extends BlockGeneric
? PeripheralItemFactory.create( (ITilePeripheral) tile )
: super.getPickBlock( state, target, world, pos, player );
}
@Override
public void getDrops( @Nonnull NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos, @Nonnull IBlockState state, int fortune )
{
drops.add( PeripheralItemFactory.create( getPeripheralType( state ), null, 1 ) );
}
}

View File

@@ -10,11 +10,9 @@ import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.shared.common.IDirectionalTile;
import dan200.computercraft.shared.common.TileGeneric;
import dan200.computercraft.shared.peripheral.PeripheralType;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.NonNullList;
import javax.annotation.Nonnull;
@@ -42,15 +40,6 @@ public abstract class TilePeripheralBase extends TileGeneric implements IPeriphe
return (BlockPeripheral) super.getBlock();
}
@Override
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
{
if( !creative )
{
drops.add( PeripheralItemFactory.create( this ) );
}
}
@Override
public final PeripheralType getPeripheralType()
{

View File

@@ -14,6 +14,7 @@ import dan200.computercraft.shared.common.TileGeneric;
import dan200.computercraft.shared.peripheral.PeripheralType;
import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyEnum;
@@ -26,6 +27,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
@@ -322,7 +324,10 @@ public class BlockCable extends BlockGeneric
cable.modemChanged();
cable.connectionsChanged();
if( !world.isRemote && !player.capabilities.isCreativeMode ) dropItem( world, pos, item );
if( !world.isRemote && !player.capabilities.isCreativeMode )
{
Block.spawnAsEntity( world, pos, item );
}
return false;
}
@@ -332,6 +337,23 @@ public class BlockCable extends BlockGeneric
return super.removedByPlayer( state, world, pos, player, willHarvest );
}
@Override
public void getDrops( @Nonnull NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos, @Nonnull IBlockState state, int fortune )
{
PeripheralType type = getPeripheralType( state );
switch( type )
{
case Cable:
case WiredModem:
drops.add( PeripheralItemFactory.create( type, null, 1 ) );
break;
case WiredModemWithCable:
drops.add( PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ) );
drops.add( PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ) );
break;
}
}
@Nonnull
@Override
public ItemStack getPickBlock( @Nonnull IBlockState state, RayTraceResult hit, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player )

View File

@@ -20,13 +20,12 @@ import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory;
import dan200.computercraft.shared.peripheral.modem.ModemState;
import dan200.computercraft.shared.util.TickScheduler;
import dan200.computercraft.shared.wired.CapabilityWiredElement;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextComponentTranslation;
@@ -177,44 +176,17 @@ public class TileCable extends TileGeneric implements IPeripheralTile
}
@Override
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
{
if( !creative )
{
PeripheralType type = getPeripheralType();
switch( type )
{
case Cable:
case WiredModem:
{
drops.add( PeripheralItemFactory.create( type, null, 1 ) );
break;
}
case WiredModemWithCable:
{
drops.add( PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ) );
drops.add( PeripheralItemFactory.create( PeripheralType.Cable, null, 1 ) );
break;
}
}
}
}
@Override
public void onNeighbourChange()
public void onNeighbourChange( @Nonnull BlockPos neighbour )
{
EnumFacing dir = getDirection();
if( !getWorld().isSideSolid(
getPos().offset( dir ),
dir.getOpposite()
) )
if( neighbour.equals( getPos().offset( dir ) ) && !getWorld().isSideSolid( neighbour, dir.getOpposite() ) )
{
switch( getPeripheralType() )
{
case WiredModem:
{
// Drop everything and remove block
getBlock().dropAllItems( getWorld(), getPos(), false );
getBlock().dropBlockAsItem( getWorld(), getPos(), getBlockState(), 0 );
getWorld().setBlockToAir( getPos() );
// This'll call #destroy(), so we don't need to reset the network here.
@@ -223,7 +195,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile
case WiredModemWithCable:
{
// Drop the modem and convert to cable
getBlock().dropItem( getWorld(), getPos(), PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ) );
Block.spawnAsEntity( getWorld(), getPos(), PeripheralItemFactory.create( PeripheralType.WiredModem, null, 1 ) );
setBlockState( getBlockState().withProperty( BlockCable.Properties.MODEM, BlockCableModemVariant.None ) );
modemChanged();
connectionsChanged();

View File

@@ -7,7 +7,6 @@
package dan200.computercraft.shared.peripheral.modem.wired;
import com.google.common.base.Objects;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.network.wired.IWiredNode;
@@ -19,11 +18,9 @@ import dan200.computercraft.shared.peripheral.modem.ModemState;
import dan200.computercraft.shared.util.TickScheduler;
import dan200.computercraft.shared.wired.CapabilityWiredElement;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextComponentString;
@@ -136,24 +133,9 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
}
@Override
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
public void onNeighbourChange( @Nonnull BlockPos neighbour )
{
drops.add( new ItemStack( ComputerCraft.Items.wiredModemFull ) );
}
@Override
public void onNeighbourChange()
{
if( !world.isRemote && m_peripheralAccessAllowed )
{
boolean hasChanged = false;
for( EnumFacing facing : EnumFacing.VALUES )
{
hasChanged |= m_peripherals[facing.ordinal()].attach( world, getPos(), facing );
}
if( hasChanged ) updateConnectedPeripherals();
}
onNeighbourTileEntityChange( neighbour );
}
@Override

View File

@@ -6,24 +6,18 @@
package dan200.computercraft.shared.peripheral.modem.wireless;
import dan200.computercraft.ComputerCraft;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import javax.annotation.Nonnull;
public class TileAdvancedModem extends TileWirelessModemBase
{
public TileAdvancedModem()
{
super( true );
}
@Override
protected EnumFacing getDirection()
{
return getBlockState().getValue( BlockAdvancedModem.Properties.FACING );
}
@Override
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
{
if( !creative ) drops.add( new ItemStack( ComputerCraft.Items.advancedModem ) );
}
}

View File

@@ -12,11 +12,8 @@ import dan200.computercraft.shared.peripheral.PeripheralType;
import dan200.computercraft.shared.peripheral.common.BlockPeripheral;
import dan200.computercraft.shared.peripheral.common.BlockPeripheralVariant;
import dan200.computercraft.shared.peripheral.common.ITilePeripheral;
import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@@ -24,6 +21,11 @@ import javax.annotation.Nonnull;
public class TileWirelessModem extends TileWirelessModemBase implements IDirectionalTile, ITilePeripheral
{
public TileWirelessModem()
{
super( false );
}
@Override
public EnumFacing getDirection()
{
@@ -75,12 +77,6 @@ public class TileWirelessModem extends TileWirelessModemBase implements IDirecti
return super.shouldRefresh( world, pos, oldState, newState ) || ComputerCraft.Blocks.peripheral.getPeripheralType( newState ) != PeripheralType.WirelessModem;
}
@Override
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
{
if( !creative ) drops.add( PeripheralItemFactory.create( PeripheralType.WirelessModem, null, 1 ) );
}
@Override
public PeripheralType getPeripheralType()
{

View File

@@ -22,13 +22,18 @@ import javax.annotation.Nonnull;
public abstract class TileWirelessModemBase extends TileGeneric implements IPeripheralTile
{
protected TileWirelessModemBase( boolean advanced )
{
this.advanced = advanced;
}
private static class Peripheral extends WirelessModemPeripheral
{
private final TileWirelessModemBase entity;
Peripheral( TileWirelessModemBase entity )
{
super( new ModemState( () -> TickScheduler.schedule( entity ) ), true );
super( new ModemState( () -> TickScheduler.schedule( entity ) ), entity.advanced );
this.entity = entity;
}
@@ -54,6 +59,7 @@ public abstract class TileWirelessModemBase extends TileGeneric implements IPeri
}
}
private final boolean advanced;
private boolean hasModemDirection = false;
private EnumFacing modemDirection = EnumFacing.DOWN;
private final ModemPeripheral modem = new Peripheral( this );
@@ -115,13 +121,13 @@ public abstract class TileWirelessModemBase extends TileGeneric implements IPeri
protected abstract EnumFacing getDirection();
@Override
public void onNeighbourChange()
public void onNeighbourChange( @Nonnull BlockPos neighbour )
{
EnumFacing dir = getDirection();
if( !getWorld().isSideSolid( getPos().offset( dir ), dir.getOpposite() ) )
if( neighbour.equals( getPos().offset( dir ) ) && !getWorld().isSideSolid( neighbour, dir.getOpposite() ) )
{
// Drop everything and remove block
getBlock().dropAllItems( getWorld(), getPos(), false );
getBlock().dropBlockAsItem( getWorld(), getPos(), getBlockState(), 0 );
getWorld().setBlockToAir( getPos() );
}
}

View File

@@ -28,8 +28,6 @@ public class MonitorPeripheral implements IPeripheral
m_monitor = monitor;
}
// IPeripheral implementation
@Nonnull
@Override
public String getType()

View File

@@ -16,27 +16,23 @@ import dan200.computercraft.shared.peripheral.PeripheralType;
import dan200.computercraft.shared.peripheral.common.BlockPeripheral;
import dan200.computercraft.shared.peripheral.common.IPeripheralTile;
import dan200.computercraft.shared.peripheral.common.ITilePeripheral;
import dan200.computercraft.shared.peripheral.common.PeripheralItemFactory;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.HashSet;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class TileMonitor extends TileGeneric implements ITilePeripheral, IPeripheralTile
{
// Statics
public static final double RENDER_BORDER = (2.0 / 16.0);
public static final double RENDER_MARGIN = (0.5 / 16.0);
public static final double RENDER_PIXEL_SCALE = (1.0 / 64.0);
@@ -44,39 +40,23 @@ public class TileMonitor extends TileGeneric implements ITilePeripheral, IPeriph
private static final int MAX_WIDTH = 8;
private static final int MAX_HEIGHT = 6;
// Members
private ServerMonitor m_serverMonitor;
private ClientMonitor m_clientMonitor;
private MonitorPeripheral m_peripheral;
private final Set<IComputerAccess> m_computers;
private final Set<IComputerAccess> m_computers = Collections.newSetFromMap( new ConcurrentHashMap<>() );
private boolean m_destroyed;
private boolean m_ignoreMe;
private boolean m_destroyed = false;
private boolean m_ignoreMe = false;
private int m_width;
private int m_height;
private int m_xIndex;
private int m_yIndex;
private int m_width = 1;
private int m_height = 1;
private int m_xIndex = 0;
private int m_yIndex = 0;
private int m_dir;
private int m_dir = 2;
private boolean m_advanced;
public TileMonitor()
{
m_computers = new HashSet<>();
m_destroyed = false;
m_ignoreMe = false;
m_width = 1;
m_height = 1;
m_xIndex = 0;
m_yIndex = 0;
m_dir = 2;
}
@Override
public void onLoad()
{
@@ -697,20 +677,14 @@ public class TileMonitor extends TileGeneric implements ITilePeripheral, IPeriph
}
}
public void addComputer( IComputerAccess computer )
void addComputer( IComputerAccess computer )
{
synchronized( this )
{
m_computers.add( computer );
}
m_computers.add( computer );
}
public void removeComputer( IComputerAccess computer )
void removeComputer( IComputerAccess computer )
{
synchronized( this )
{
m_computers.remove( computer );
}
m_computers.remove( computer );
}
@Nonnull
@@ -757,10 +731,4 @@ public class TileMonitor extends TileGeneric implements ITilePeripheral, IPeriph
}
}
}
@Override
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
{
if( !creative ) drops.add( PeripheralItemFactory.create( this ) );
}
}

View File

@@ -27,7 +27,6 @@ import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
@@ -200,11 +199,10 @@ public class BlockTurtle extends BlockComputerBase
return super.getExplosionResistance( exploder );
}
@Override
@Nonnull
public ItemStack getPickBlock( @Nonnull IBlockState state, RayTraceResult target, @Nonnull World world, @Nonnull BlockPos pos, EntityPlayer player )
@Override
protected ItemStack getItem( TileComputerBase tile )
{
TileEntity tile = world.getTileEntity( pos );
return tile instanceof TileTurtle ? TurtleItemFactory.create( (TileTurtle) tile ) : super.getPickBlock( state, target, world, pos, player );
return tile instanceof TileTurtle ? TurtleItemFactory.create( (TileTurtle) tile ) : ItemStack.EMPTY;
}
}

View File

@@ -17,7 +17,6 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.turtle.apis.TurtleAPI;
import dan200.computercraft.shared.turtle.core.TurtleBrain;
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
import dan200.computercraft.shared.util.DefaultInventory;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.RedstoneUtil;
@@ -166,12 +165,6 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
}
}
@Override
public void getDroppedItems( @Nonnull NonNullList<ItemStack> drops, boolean creative )
{
if( !creative || getLabel() != null ) drops.add( TurtleItemFactory.create( this ) );
}
@Override
public boolean onActivate( EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ )
{
@@ -262,38 +255,26 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
}
@Override
public void onNeighbourChange()
public void onNeighbourChange( @Nonnull BlockPos neighbour )
{
if( m_moveState == MoveState.NOT_MOVED )
{
super.onNeighbourChange();
}
if( m_moveState == MoveState.NOT_MOVED ) super.onNeighbourChange( neighbour );
}
@Override
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour )
{
if( m_moveState == MoveState.NOT_MOVED )
{
super.onNeighbourTileEntityChange( neighbour );
}
if( m_moveState == MoveState.NOT_MOVED ) super.onNeighbourTileEntityChange( neighbour );
}
public void notifyMoveStart()
{
if( m_moveState == MoveState.NOT_MOVED )
{
m_moveState = MoveState.IN_PROGRESS;
}
if( m_moveState == MoveState.NOT_MOVED ) m_moveState = MoveState.IN_PROGRESS;
}
public void notifyMoveEnd()
{
// MoveState.MOVED is final
if( m_moveState == MoveState.IN_PROGRESS )
{
m_moveState = MoveState.NOT_MOVED;
}
if( m_moveState == MoveState.IN_PROGRESS ) m_moveState = MoveState.NOT_MOVED;
}
@Override

View File

@@ -13,6 +13,7 @@ import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.*;
import dan200.computercraft.core.tracking.Tracking;
import dan200.computercraft.shared.computer.blocks.ComputerProxy;
import dan200.computercraft.shared.computer.blocks.TileComputerBase;
import dan200.computercraft.shared.computer.core.ComputerFamily;
@@ -972,17 +973,21 @@ public class TurtleBrain implements ITurtleAccess
TurtleCommandQueueEntry nextCommand = m_commandQueue.poll();
if( nextCommand != null )
{
ServerComputer computer = m_owner.getServerComputer();
// Execute the command
long start = System.nanoTime();
TurtleCommandResult result = nextCommand.command.execute( this );
long end = System.nanoTime();
// Dispatch the callback
int callbackID = nextCommand.callbackID;
if( callbackID >= 0 )
if( computer != null )
{
if( result != null && result.isSuccess() )
Tracking.addServerTiming( computer.getComputer(), end - start );
int callbackID = nextCommand.callbackID;
if( callbackID >= 0 )
{
ServerComputer computer = m_owner.getServerComputer();
if( computer != null )
if( result != null && result.isSuccess() )
{
Object[] results = result.getResults();
if( results != null )
@@ -1000,11 +1005,7 @@ public class TurtleBrain implements ITurtleAccess
} );
}
}
}
else
{
ServerComputer computer = m_owner.getServerComputer();
if( computer != null )
else
{
computer.queueEvent( "turtle_response", new Object[] {
callbackID, false, result != null ? result.getErrorMessage() : null

View File

@@ -18,7 +18,7 @@ public class RedstoneUtil
@Deprecated
public static int getRedstoneOutput( World world, BlockPos pos, EnumFacing side )
{
return world.getRedstonePower( pos, side );
return world.getRedstonePower( pos, side.getOpposite() );
}
@Deprecated

View File

@@ -63,7 +63,7 @@ local function createShellEnv( sDir )
end
else
if #sError > 0 then
sError = sError .. "\n"
sError = sError .. "\n "
end
sError = sError .. "no file '" .. sPath .. "'"
end
@@ -78,27 +78,24 @@ local function createShellEnv( sDir )
error( "bad argument #1 (expected string, got " .. type( name ) .. ")", 2 )
end
if package.loaded[name] == sentinel then
error("Loop detected requiring '" .. name .. "'", 0)
error("loop or previous error loading module '" .. name .. "'", 0)
end
if package.loaded[name] then
return package.loaded[name]
end
local sError = "Error loading module '" .. name .. "':"
for n,searcher in ipairs(package.loaders) do
local loader, err = searcher(name)
if loader then
local sError = "module '" .. name .. "' not found:"
for _, searcher in ipairs(package.loaders) do
local loader = table.pack(searcher(name))
if loader[1] then
package.loaded[name] = sentinel
local result = loader( err )
if result ~= nil then
package.loaded[name] = result
return result
else
package.loaded[name] = true
return true
end
local result = loader[1](name, table.unpack(loader, 2, loader.n))
if result == nil then result = true end
package.loaded[name] = result
return result
else
sError = sError .. "\n" .. err
sError = sError .. "\n " .. loader[2]
end
end
error(sError, 2)