1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 20:20:30 +00:00

Merge branch 'mc-1.15.x' into mc-1.16.x

This commit is contained in:
Jonathan Coates 2021-04-24 11:50:23 +01:00
commit f387730b88
19 changed files with 482 additions and 247 deletions

View File

@ -4,7 +4,7 @@ buildscript {
mavenCentral() mavenCentral()
maven { maven {
name = "forge" name = "forge"
url = "https://files.minecraftforge.net/maven" url = "https://maven.minecraftforge.net"
} }
maven { maven {
name = "Sponge (Mixin)" name = "Sponge (Mixin)"
@ -14,7 +14,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.google.code.gson:gson:2.8.1' classpath 'com.google.code.gson:gson:2.8.1'
classpath 'net.minecraftforge.gradle:ForgeGradle:4.1.3' classpath 'net.minecraftforge.gradle:ForgeGradle:4.1.9'
classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2' classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT'
} }
@ -23,6 +23,7 @@ buildscript {
plugins { plugins {
id "checkstyle" id "checkstyle"
id "jacoco" id "jacoco"
id "maven-publish"
id "com.github.hierynomus.license" version "0.15.0" id "com.github.hierynomus.license" version "0.15.0"
id "com.matthewprenger.cursegradle" version "1.4.0" id "com.matthewprenger.cursegradle" version "1.4.0"
id "com.github.breadmoirai.github-release" version "2.2.12" id "com.github.breadmoirai.github-release" version "2.2.12"
@ -31,8 +32,6 @@ plugins {
apply plugin: 'net.minecraftforge.gradle' apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'org.spongepowered.mixin' apply plugin: 'org.spongepowered.mixin'
apply plugin: 'maven-publish'
apply plugin: 'maven'
version = mod_version version = mod_version
@ -43,6 +42,9 @@ java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(8) languageVersion = JavaLanguageVersion.of(8)
} }
withSourcesJar()
withJavadocJar()
} }
minecraft { minecraft {
@ -127,7 +129,6 @@ repositories {
configurations { configurations {
shade shade
compile.extendsFrom shade compile.extendsFrom shade
deployerJars
cctJavadoc cctJavadoc
} }
@ -153,8 +154,7 @@ dependencies {
testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72' testImplementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72'
testImplementation 'org.jetbrains.kotlin:kotlin-reflect:1.3.72' testImplementation 'org.jetbrains.kotlin:kotlin-reflect:1.3.72'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8' testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
testAnnotationProcessor 'org.spongepowered:mixin:0.8.2:processor'
deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
cctJavadoc 'cc.tweaked:cct-javadoc:1.3.0' cctJavadoc 'cc.tweaked:cct-javadoc:1.3.0'
} }
@ -183,8 +183,6 @@ task luaJavadoc(type: Javadoc) {
} }
jar { jar {
dependsOn javadoc
manifest { manifest {
attributes(["Specification-Title": "computercraft", attributes(["Specification-Title": "computercraft",
"Specification-Vendor": "SquidDev", "Specification-Vendor": "SquidDev",
@ -195,10 +193,6 @@ jar {
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")]) "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")])
} }
from (sourceSets.main.allSource) {
include "dan200/computercraft/api/**/*.java"
}
from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) } from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
} }
@ -568,51 +562,41 @@ curseforge {
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { maven(MavenPublication) {
from components.java from components.java
// artifact sourceJar
}
}
}
uploadArchives { pom {
repositories { name = 'CC: Tweaked'
if(project.hasProperty('mavenUploadUrl')) { description = 'CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.'
mavenDeployer { url = 'https://github.com/SquidDev-CC/CC-Tweaked'
configuration = configurations.deployerJars
repository(url: project.property('mavenUploadUrl')) {
authentication(
userName: project.property('mavenUploadUser'),
privateKey: project.property('mavenUploadKey'))
}
pom.project {
name 'CC: Tweaked'
packaging 'jar'
description 'CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.'
url 'https://github.com/SquidDev-CC/CC-Tweaked'
scm { scm {
url 'https://github.com/SquidDev-CC/CC-Tweaked.git' url = 'https://github.com/SquidDev-CC/CC-Tweaked.git'
} }
issueManagement { issueManagement {
system 'github' system = 'github'
url 'https://github.com/SquidDev-CC/CC-Tweaked/issues' url = 'https://github.com/SquidDev-CC/CC-Tweaked/issues'
} }
licenses { licenses {
license { license {
name 'ComputerCraft Public License, Version 1.0' name = 'ComputerCraft Public License, Version 1.0'
url 'https://github.com/SquidDev-CC/CC-Tweaked/blob/master/LICENSE' url = 'https://github.com/SquidDev-CC/CC-Tweaked/blob/mc-1.15.x/LICENSE'
distribution 'repo' }
}
} }
} }
} }
pom.whenConfigured { pom -> repositories {
pom.dependencies.clear() if (project.hasProperty("mavenUser")) {
maven {
name = "SquidDev"
url = "https://squiddev.cc/maven"
credentials {
username = project.property("mavenUser") as String
password = project.property("mavenPass") as String
} }
} }
} }
@ -643,7 +627,7 @@ githubRelease {
prerelease false prerelease false
} }
def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"] def uploadTasks = ["publish", "curseforge", "githubRelease"]
uploadTasks.forEach { tasks.getByName(it).dependsOn checkRelease } uploadTasks.forEach { tasks.getByName(it).dependsOn checkRelease }
task uploadAll(dependsOn: uploadTasks) { task uploadAll(dependsOn: uploadTasks) {

View File

@ -1 +1,13 @@
--[[- Craft a recipe based on the turtle's inventory.
The turtle's inventory should set up like a crafting grid. For instance, to
craft sticks, slots 1 and 5 should contain sticks. _All_ other slots should be
empty, including those outside the crafting "grid".
@tparam[opt=64] number limit The maximum number of crafting steps to run.
@throws When limit is less than 1 or greater than 64.
@treturn[1] true If crafting succeeds.
@treturn[2] false If crafting fails.
@treturn string A string describing why crafting failed.
]]
function craft(limit) end function craft(limit) end

View File

@ -88,27 +88,16 @@
;; Suppress warnings for currently undocumented modules. ;; Suppress warnings for currently undocumented modules.
(at (at
(; Java APIs (; Lua APIs
/doc/stub/http.lua
/doc/stub/os.lua
/doc/stub/turtle.lua
/doc/stub/global.lua
; Java generated APIs
/build/docs/luaJavadoc/turtle.lua
; Peripherals
/build/docs/luaJavadoc/drive.lua
/build/docs/luaJavadoc/speaker.lua
/build/docs/luaJavadoc/printer.lua
; Generic peripherals
/build/docs/luaJavadoc/fluid_storage.lua
; Lua APIs
/src/main/resources/*/computercraft/lua/rom/apis/io.lua /src/main/resources/*/computercraft/lua/rom/apis/io.lua
/src/main/resources/*/computercraft/lua/rom/apis/window.lua) /src/main/resources/*/computercraft/lua/rom/apis/window.lua)
(linters -doc:undocumented -doc:undocumented-arg -doc:undocumented-return)) (linters -doc:undocumented -doc:undocumented-arg -doc:undocumented-return))
;; Suppress warnings for the BIOS using its own deprecated members for now. ;; Suppress warnings for various APIs using its own deprecated members.
(at /src/main/resources/*/computercraft/lua/bios.lua (at
(/src/main/resources/*/computercraft/lua/bios.lua
/src/main/resources/*/computercraft/lua/rom/apis/turtle/turtle.lua)
(linters -var:deprecated)) (linters -var:deprecated))
(at /src/test/resources/test-rom (at /src/test/resources/test-rom

View File

@ -98,7 +98,9 @@ public final class ComputerCraftAPI
* resource folder onto a computer's file system. * resource folder onto a computer's file system.
* *
* The files in this mount will be a combination of files in all mod jar, and data packs that contain * The files in this mount will be a combination of files in all mod jar, and data packs that contain
* resources with the same domain and path. * resources with the same domain and path. For instance, ComputerCraft's resources are stored in
* "/data/computercraft/lua/rom". We construct a mount for that with
* {@code createResourceMount("computercraft", "lua/rom")}.
* *
* @param domain The domain under which to look for resources. eg: "mymod". * @param domain The domain under which to look for resources. eg: "mymod".
* @param subPath The subPath under which to look for resources. eg: "lua/myfiles". * @param subPath The subPath under which to look for resources. eg: "lua/myfiles".

View File

@ -103,9 +103,13 @@ public final class ResourceMount implements IMount
private void load() private void load()
{ {
boolean hasAny = false; boolean hasAny = false;
String existingNamespace = null;
FileEntry newRoot = new FileEntry( new ResourceLocation( namespace, subPath ) ); FileEntry newRoot = new FileEntry( new ResourceLocation( namespace, subPath ) );
for( ResourceLocation file : manager.listResources( subPath, s -> true ) ) for( ResourceLocation file : manager.listResources( subPath, s -> true ) )
{ {
existingNamespace = file.getNamespace();
if( !file.getNamespace().equals( namespace ) ) continue; if( !file.getNamespace().equals( namespace ) ) continue;
String localPath = FileSystem.toLocal( file.getPath(), subPath ); String localPath = FileSystem.toLocal( file.getPath(), subPath );
@ -114,6 +118,15 @@ public final class ResourceMount implements IMount
} }
root = hasAny ? newRoot : null; root = hasAny ? newRoot : null;
if( !hasAny )
{
ComputerCraft.log.warn( "Cannot find any files under /data/{}/{} for resource mount.", namespace, subPath );
if( newRoot != null )
{
ComputerCraft.log.warn( "There are files under /data/{}/{} though. Did you get the wrong namespace?", existingNamespace, subPath );
}
}
} }
private FileEntry get( String path ) private FileEntry get( String path )

View File

@ -12,46 +12,12 @@ public class TextBuffer
public TextBuffer( char c, int length ) public TextBuffer( char c, int length )
{ {
text = new char[length]; text = new char[length];
for( int i = 0; i < length; i++ ) this.fill( c );
{
text[i] = c;
}
} }
public TextBuffer( String text ) public TextBuffer( String text )
{ {
this( text, 1 ); this.text = text.toCharArray();
}
public TextBuffer( String text, int repetitions )
{
int textLength = text.length();
this.text = new char[textLength * repetitions];
for( int i = 0; i < repetitions; i++ )
{
for( int j = 0; j < textLength; j++ )
{
this.text[j + i * textLength] = text.charAt( j );
}
}
}
public TextBuffer( TextBuffer text )
{
this( text, 1 );
}
public TextBuffer( TextBuffer text, int repetitions )
{
int textLength = text.length();
this.text = new char[textLength * repetitions];
for( int i = 0; i < repetitions; i++ )
{
for( int j = 0; j < textLength; j++ )
{
this.text[j + i * textLength] = text.charAt( j );
}
}
} }
public int length() public int length()
@ -59,39 +25,16 @@ public class TextBuffer
return text.length; return text.length;
} }
public String read()
{
return read( 0, text.length );
}
public String read( int start )
{
return read( start, text.length );
}
public String read( int start, int end )
{
start = Math.max( start, 0 );
end = Math.min( end, text.length );
int textLength = Math.max( end - start, 0 );
return new String( text, start, textLength );
}
public void write( String text ) public void write( String text )
{ {
write( text, 0, text.length() ); write( text, 0 );
} }
public void write( String text, int start ) public void write( String text, int start )
{
write( text, start, start + text.length() );
}
public void write( String text, int start, int end )
{ {
int pos = start; int pos = start;
start = Math.max( start, 0 ); start = Math.max( start, 0 );
end = Math.min( end, pos + text.length() ); int end = Math.min( start + text.length(), pos + text.length() );
end = Math.min( end, this.text.length ); end = Math.min( end, this.text.length );
for( int i = start; i < end; i++ ) for( int i = start; i < end; i++ )
{ {
@ -101,23 +44,10 @@ public class TextBuffer
public void write( TextBuffer text ) public void write( TextBuffer text )
{ {
write( text, 0, text.length() ); int end = Math.min( text.length(), this.text.length );
} for( int i = 0; i < end; i++ )
public void write( TextBuffer text, int start )
{ {
write( text, start, start + text.length() ); this.text[i] = text.charAt( i );
}
public void write( TextBuffer text, int start, int end )
{
int pos = start;
start = Math.max( start, 0 );
end = Math.min( end, pos + text.length() );
end = Math.min( end, this.text.length );
for( int i = start; i < end; i++ )
{
this.text[i] = text.charAt( i - pos );
} }
} }
@ -126,11 +56,6 @@ public class TextBuffer
fill( c, 0, text.length ); fill( c, 0, text.length );
} }
public void fill( char c, int start )
{
fill( c, start, text.length );
}
public void fill( char c, int start, int end ) public void fill( char c, int start, int end )
{ {
start = Math.max( start, 0 ); start = Math.max( start, 0 );
@ -141,52 +66,6 @@ public class TextBuffer
} }
} }
public void fill( String text )
{
fill( text, 0, this.text.length );
}
public void fill( String text, int start )
{
fill( text, start, this.text.length );
}
public void fill( String text, int start, int end )
{
int pos = start;
start = Math.max( start, 0 );
end = Math.min( end, this.text.length );
int textLength = text.length();
for( int i = start; i < end; i++ )
{
this.text[i] = text.charAt( (i - pos) % textLength );
}
}
public void fill( TextBuffer text )
{
fill( text, 0, this.text.length );
}
public void fill( TextBuffer text, int start )
{
fill( text, start, this.text.length );
}
public void fill( TextBuffer text, int start, int end )
{
int pos = start;
start = Math.max( start, 0 );
end = Math.min( end, this.text.length );
int textLength = text.length();
for( int i = start; i < end; i++ )
{
this.text[i] = text.charAt( (i - pos) % textLength );
}
}
public char charAt( int i ) public char charAt( int i )
{ {
return text[i]; return text[i];

View File

@ -114,10 +114,10 @@ public class JEIComputerCraft implements IModPlugin
*/ */
private static final ISubtypeInterpreter turtleSubtype = stack -> { private static final ISubtypeInterpreter turtleSubtype = stack -> {
Item item = stack.getItem(); Item item = stack.getItem();
if( !(item instanceof ITurtleItem) ) return ""; if( !(item instanceof ITurtleItem) ) return ISubtypeInterpreter.NONE;
ITurtleItem turtle = (ITurtleItem) item; ITurtleItem turtle = (ITurtleItem) item;
StringBuilder name = new StringBuilder(); StringBuilder name = new StringBuilder( "turtle:" );
// Add left and right upgrades to the identifier // Add left and right upgrades to the identifier
ITurtleUpgrade left = turtle.getUpgrade( stack, TurtleSide.LEFT ); ITurtleUpgrade left = turtle.getUpgrade( stack, TurtleSide.LEFT );
@ -134,9 +134,9 @@ public class JEIComputerCraft implements IModPlugin
*/ */
private static final ISubtypeInterpreter pocketSubtype = stack -> { private static final ISubtypeInterpreter pocketSubtype = stack -> {
Item item = stack.getItem(); Item item = stack.getItem();
if( !(item instanceof ItemPocketComputer) ) return ""; if( !(item instanceof ItemPocketComputer) ) return ISubtypeInterpreter.NONE;
StringBuilder name = new StringBuilder(); StringBuilder name = new StringBuilder( "pocket:" );
// Add the upgrade to the identifier // Add the upgrade to the identifier
IPocketUpgrade upgrade = ItemPocketComputer.getUpgrade( stack ); IPocketUpgrade upgrade = ItemPocketComputer.getUpgrade( stack );
@ -150,11 +150,11 @@ public class JEIComputerCraft implements IModPlugin
*/ */
private static final ISubtypeInterpreter diskSubtype = stack -> { private static final ISubtypeInterpreter diskSubtype = stack -> {
Item item = stack.getItem(); Item item = stack.getItem();
if( !(item instanceof ItemDisk) ) return ""; if( !(item instanceof ItemDisk) ) return ISubtypeInterpreter.NONE;
ItemDisk disk = (ItemDisk) item; ItemDisk disk = (ItemDisk) item;
int colour = disk.getColour( stack ); int colour = disk.getColour( stack );
return colour == -1 ? "" : String.format( "%06x", colour ); return colour == -1 ? ISubtypeInterpreter.NONE : String.format( "%06x", colour );
}; };
} }

View File

@ -200,7 +200,7 @@ class RecipeResolver implements IRecipeManagerPlugin
for( UpgradeInfo upgrade : upgrades ) for( UpgradeInfo upgrade : upgrades )
{ {
ItemStack craftingStack = upgrade.stack; ItemStack craftingStack = upgrade.stack;
if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && upgrade.upgrade.isItemSuitable( stack ) ) if( craftingStack.isEmpty() || craftingStack.getItem() != stack.getItem() || !upgrade.upgrade.isItemSuitable( stack ) )
{ {
continue; continue;
} }
@ -319,13 +319,6 @@ class RecipeResolver implements IRecipeManagerPlugin
super( ID, null, width, height, input, output ); super( ID, null, width, height, input, output );
} }
@Nonnull
@Override
public ResourceLocation getId()
{
return null;
}
@Nonnull @Nonnull
@Override @Override
public IRecipeSerializer<?> getSerializer() public IRecipeSerializer<?> getSerializer()

View File

@ -45,6 +45,19 @@ public class FluidMethods implements GenericSource
return new ResourceLocation( ForgeVersion.MOD_ID, "fluid" ); return new ResourceLocation( ForgeVersion.MOD_ID, "fluid" );
} }
/**
* Get all "tanks" in this fluid storage.
*
* Each tank either contains some amount of fluid or is empty. Tanks with fluids inside will return some basic
* information about the fluid, including its name and amount.
*
* The returned table is sparse, and so empty tanks will be `nil` - it is recommended to loop over using `pairs`
* rather than `ipairs`.
*
* @param fluids The current fluid handler.
* @return All tanks.
* @cc.treturn { (table|nil)... } All tanks in this fluid storage.
*/
@LuaFunction( mainThread = true ) @LuaFunction( mainThread = true )
public static Map<Integer, Map<String, ?>> tanks( IFluidHandler fluids ) public static Map<Integer, Map<String, ?>> tanks( IFluidHandler fluids )
{ {
@ -59,6 +72,22 @@ public class FluidMethods implements GenericSource
return result; return result;
} }
/**
* Move a fluid from one fluid container to another connected one.
*
* This allows you to pull fluid in the current fluid container to another container <em>on the same wired
* network</em>. Both containers must attached to wired modems which are connected via a cable.
*
* @param from Container to move fluid from.
* @param computer The current computer.
* @param toName The name of the peripheral/container to push to. This is the string given to @{peripheral.wrap},
* and displayed by the wired modem.
* @param limit The maximum amount of fluid to move.
* @param fluidName The fluid to move. If not given, an arbitrary fluid will be chosen.
* @return The amount of moved fluid.
* @throws LuaException If the peripheral to transfer to doesn't exist or isn't an fluid container.
* @cc.see peripheral.getName Allows you to get the name of a @{peripheral.wrap|wrapped} peripheral.
*/
@LuaFunction( mainThread = true ) @LuaFunction( mainThread = true )
public static int pushFluid( public static int pushFluid(
IFluidHandler from, IComputerAccess computer, IFluidHandler from, IComputerAccess computer,
@ -84,6 +113,22 @@ public class FluidMethods implements GenericSource
: moveFluid( from, new FluidStack( fluid, actualLimit ), to ); : moveFluid( from, new FluidStack( fluid, actualLimit ), to );
} }
/**
* Move a fluid from a connected fluid container into this oneone.
*
* This allows you to pull fluid in the current fluid container from another container <em>on the same wired
* network</em>. Both containers must attached to wired modems which are connected via a cable.
*
* @param to Container to move fluid to.
* @param computer The current computer.
* @param fromName The name of the peripheral/container to push to. This is the string given to @{peripheral.wrap},
* and displayed by the wired modem.
* @param limit The maximum amount of fluid to move.
* @param fluidName The fluid to move. If not given, an arbitrary fluid will be chosen.
* @return The amount of moved fluid.
* @throws LuaException If the peripheral to transfer to doesn't exist or isn't an fluid container.
* @cc.see peripheral.getName Allows you to get the name of a @{peripheral.wrap|wrapped} peripheral.
*/
@LuaFunction( mainThread = true ) @LuaFunction( mainThread = true )
public static int pullFluid( public static int pullFluid(
IFluidHandler to, IComputerAccess computer, IFluidHandler to, IComputerAccess computer,

View File

@ -65,8 +65,8 @@ public class InventoryMethods implements GenericSource
* {@link dan200.computercraft.shared.turtle.apis.TurtleAPI#getItemDetail} includes. More information can be fetched * {@link dan200.computercraft.shared.turtle.apis.TurtleAPI#getItemDetail} includes. More information can be fetched
* with {@link #getItemDetail}. * with {@link #getItemDetail}.
* *
* The table is sparse, and so empty slots will be `nil` - it is recommended to loop over using `pairs` rather than * The returned table is sparse, and so empty slots will be `nil` - it is recommended to loop over using `pairs`
* `ipairs`. * rather than `ipairs`.
* *
* @param inventory The current inventory. * @param inventory The current inventory.
* @return All items in this inventory. * @return All items in this inventory.

View File

@ -371,18 +371,36 @@ public class TurtleAPI implements ILuaAPI
return trackCommand( new TurtleDetectCommand( InteractDirection.DOWN ) ); return trackCommand( new TurtleDetectCommand( InteractDirection.DOWN ) );
} }
/**
* Check if the block in front of the turtle is equal to the item in the currently selected slot.
*
* @return If the block and item are equal.
* @cc.treturn boolean If the block and item are equal.
*/
@LuaFunction @LuaFunction
public final MethodResult compare() public final MethodResult compare()
{ {
return trackCommand( new TurtleCompareCommand( InteractDirection.FORWARD ) ); return trackCommand( new TurtleCompareCommand( InteractDirection.FORWARD ) );
} }
/**
* Check if the block above the turtle is equal to the item in the currently selected slot.
*
* @return If the block and item are equal.
* @cc.treturn boolean If the block and item are equal.
*/
@LuaFunction @LuaFunction
public final MethodResult compareUp() public final MethodResult compareUp()
{ {
return trackCommand( new TurtleCompareCommand( InteractDirection.UP ) ); return trackCommand( new TurtleCompareCommand( InteractDirection.UP ) );
} }
/**
* Check if the block below the turtle is equal to the item in the currently selected slot.
*
* @return If the block and item are equal.
* @cc.treturn boolean If the block and item are equal.
*/
@LuaFunction @LuaFunction
public final MethodResult compareDown() public final MethodResult compareDown()
{ {
@ -478,12 +496,57 @@ public class TurtleAPI implements ILuaAPI
return trackCommand( new TurtleSuckCommand( InteractDirection.DOWN, checkCount( count ) ) ); return trackCommand( new TurtleSuckCommand( InteractDirection.DOWN, checkCount( count ) ) );
} }
/**
* Get the maximum amount of fuel this turtle currently holds.
*
* @return The fuel level, or "unlimited".
* @cc.treturn [1] number The current amount of fuel a turtle this turtle has.
* @cc.treturn [2] "unlimited" If turtles do not consume fuel when moving.
* @see #getFuelLimit()
* @see #refuel(Optional)
*/
@LuaFunction @LuaFunction
public final Object getFuelLevel() public final Object getFuelLevel()
{ {
return turtle.isFuelNeeded() ? turtle.getFuelLevel() : "unlimited"; return turtle.isFuelNeeded() ? turtle.getFuelLevel() : "unlimited";
} }
/**
* Refuel this turtle.
*
* While most actions a turtle can perform (such as digging or placing blocks), moving consumes fuel from the
* turtle's internal buffer. If a turtle has no fuel, it will not move.
*
* {@link #refuel} refuels the turtle, consuming fuel items (such as coal or lava buckets) from the currently
* selected slot and converting them into energy. This finishes once the turtle is fully refuelled or all items have
* been consumed.
*
* @param countA The maximum number of items to consume. One can pass `0` to check if an item is combustable or not.
* @return If this turtle could be refuelled.
* @throws LuaException If the refuel count is out of range.
* @cc.treturn [1] true If the turtle was refuelled.
* @cc.treturn [2] false If the turtle was not refuelled.
* @cc.treturn [2] string The reason the turtle was not refuelled (
* @cc.usage Refuel a turtle from the currently selected slot.
* <pre>{@code
* local level = turtle.getFuelLevel()
* if new_level == "unlimited" then error("Turtle does not need fuel", 0) end
*
* local ok, err = turtle.refuel()
* if ok then
* local new_level = turtle.getFuelLevel()
* print(("Refuelled %d, current level is %d"):format(new_level - level, new_level))
* else
* printError(err)
* end}</pre>
* @cc.usage Check if the current item is a valid fuel source.
* <pre>{@code
* local is_fuel, reason = turtle.refuel(0)
* if not is_fuel then printError(reason) end
* }</pre>
* @see #getFuelLevel()
* @see #getFuelLimit()
*/
@LuaFunction @LuaFunction
public final MethodResult refuel( Optional<Integer> countA ) throws LuaException public final MethodResult refuel( Optional<Integer> countA ) throws LuaException
{ {
@ -492,12 +555,30 @@ public class TurtleAPI implements ILuaAPI
return trackCommand( new TurtleRefuelCommand( count ) ); return trackCommand( new TurtleRefuelCommand( count ) );
} }
/**
* Compare the item in the currently selected slot to the item in another slot.
*
* @param slot The slot to compare to.
* @return If the items are the same.
* @throws LuaException If the slot is out of range.
* @cc.treturn boolean If the two items are equal.
*/
@LuaFunction @LuaFunction
public final MethodResult compareTo( int slot ) throws LuaException public final MethodResult compareTo( int slot ) throws LuaException
{ {
return trackCommand( new TurtleCompareToCommand( checkSlot( slot ) ) ); return trackCommand( new TurtleCompareToCommand( checkSlot( slot ) ) );
} }
/**
* Move an item from the selected slot to another one.
*
* @param slotArg The slot to move this item to.
* @param countArg The maximum number of items to move.
* @return If the item was moved or not.
* @throws LuaException If the slot is out of range.
* @throws LuaException If the number of items is out of range.
* @cc.treturn boolean If some items were successfully moved.
*/
@LuaFunction @LuaFunction
public final MethodResult transferTo( int slotArg, Optional<Integer> countArg ) throws LuaException public final MethodResult transferTo( int slotArg, Optional<Integer> countArg ) throws LuaException
{ {
@ -518,18 +599,55 @@ public class TurtleAPI implements ILuaAPI
return turtle.getSelectedSlot() + 1; return turtle.getSelectedSlot() + 1;
} }
/**
* Get the maximum amount of fuel this turtle can hold.
*
* By default, normal turtles have a limit of 20,000 and advanced turtles of 100,000.
*
* @return The limit, or "unlimited".
* @cc.treturn [1] number The maximum amount of fuel a turtle can hold.
* @cc.treturn [2] "unlimited" If turtles do not consume fuel when moving.
* @see #getFuelLevel()
* @see #refuel(Optional)
*/
@LuaFunction @LuaFunction
public final Object getFuelLimit() public final Object getFuelLimit()
{ {
return turtle.isFuelNeeded() ? turtle.getFuelLimit() : "unlimited"; return turtle.isFuelNeeded() ? turtle.getFuelLimit() : "unlimited";
} }
/**
* Equip (or unequip) an item on the left side of this turtle.
*
* This finds the item in the currently selected slot and attempts to equip it to the left side of the turtle. The
* previous upgrade is removed and placed into the turtle's inventory. If there is no item in the slot, the previous
* upgrade is removed, but no new one is equipped.
*
* @return Whether an item was equiped or not.
* @cc.treturn [1] true If the item was equipped.
* @cc.treturn [2] false If we could not equip the item.
* @cc.treturn [2] string The reason equipping this item failed.
* @see #equipRight()
*/
@LuaFunction @LuaFunction
public final MethodResult equipLeft() public final MethodResult equipLeft()
{ {
return trackCommand( new TurtleEquipCommand( TurtleSide.LEFT ) ); return trackCommand( new TurtleEquipCommand( TurtleSide.LEFT ) );
} }
/**
* Equip (or unequip) an item on the right side of this turtle.
*
* This finds the item in the currently selected slot and attempts to equip it to the right side of the turtle. The
* previous upgrade is removed and placed into the turtle's inventory. If there is no item in the slot, the previous
* upgrade is removed, but no new one is equipped.
*
* @return Whether an item was equiped or not.
* @cc.treturn [1] true If the item was equipped.
* @cc.treturn [2] false If we could not equip the item.
* @cc.treturn [2] string The reason equipping this item failed.
* @see #equipRight()
*/
@LuaFunction @LuaFunction
public final MethodResult equipRight() public final MethodResult equipRight()
{ {

View File

@ -137,6 +137,15 @@ handleMetatable = {
return handle.seek(whence, offset) return handle.seek(whence, offset)
end, end,
--[[- Sets the buffering mode for an output file.
This has no effect under ComputerCraft, and exists with compatility
with base Lua.
@tparam string mode The buffering mode.
@tparam[opt] number size The size of the buffer.
@see file:setvbuf Lua's documentation for `setvbuf`.
@deprecated This has no effect in CC.
]]
setvbuf = function(self, mode, size) end, setvbuf = function(self, mode, size) end,
--- Write one or more values to the file --- Write one or more values to the file

View File

@ -132,7 +132,17 @@ function drawLine(startX, startY, endX, endY, colour)
return return
end end
local minX, maxX, minY, maxY = sortCoords(startX, startY, endX, endY) local minX = math.min(startX, endX)
local maxX, minY, maxY
if minX == startX then
minY = startY
maxX = endX
maxY = endY
else
minY = endY
maxX = startX
maxY = startY
end
-- TODO: clip to screen rectangle? -- TODO: clip to screen rectangle?

View File

@ -161,7 +161,9 @@ end
-- @tparam string name The name of the peripheral to wrap. -- @tparam string name The name of the peripheral to wrap.
-- @treturn table|nil The table containing the peripheral's methods, or `nil` if -- @treturn table|nil The table containing the peripheral's methods, or `nil` if
-- there is no peripheral present with the given name. -- there is no peripheral present with the given name.
-- @usage peripheral.wrap("top").open(1) -- @usage Open the modem on the top of this computer.
--
-- peripheral.wrap("top").open(1)
function wrap(name) function wrap(name)
expect(1, name, "string") expect(1, name, "string")
@ -183,16 +185,25 @@ function wrap(name)
return result return result
end end
--- Find all peripherals of a specific type, and return the --[[- Find all peripherals of a specific type, and return the
-- @{peripheral.wrap|wrapped} peripherals. @{peripheral.wrap|wrapped} peripherals.
--
-- @tparam string ty The type of peripheral to look for. @tparam string ty The type of peripheral to look for.
-- @tparam[opt] function(name:string, wrapped:table):boolean filter A @tparam[opt] function(name:string, wrapped:table):boolean filter A
-- filter function, which takes the peripheral's name and wrapped table filter function, which takes the peripheral's name and wrapped table
-- and returns if it should be included in the result. and returns if it should be included in the result.
-- @treturn table... 0 or more wrapped peripherals matching the given filters. @treturn table... 0 or more wrapped peripherals matching the given filters.
-- @usage { peripheral.find("monitor") } @usage Find all monitors and store them in a table, writing "Hello" on each one.
-- @usage peripheral.find("modem", rednet.open)
local monitors = { peripheral.find("monitor") }
for _, monitor in pairs(monitors) do
monitor.write("Hello")
end
@usage This abuses the `filter` argument to call @{rednet.open} on every modem.
peripheral.find("modem", rednet.open)
]]
function find(ty, filter) function find(ty, filter)
expect(1, ty, "string") expect(1, ty, "string")
expect(2, filter, "function", "nil") expect(2, filter, "function", "nil")

View File

@ -10,6 +10,7 @@ end
-- --
-- Generally you should not need to use this table - it only exists for -- Generally you should not need to use this table - it only exists for
-- backwards compatibility reasons. -- backwards compatibility reasons.
-- @deprecated
native = turtle.native or turtle native = turtle.native or turtle
local function addCraftMethod(object) local function addCraftMethod(object)

View File

@ -1,23 +1,28 @@
--- Provides a "pretty printer", for rendering data structures in an --[[- Provides a "pretty printer", for rendering data structures in an
-- aesthetically pleasing manner. aesthetically pleasing manner.
--
-- In order to display something using @{cc.pretty}, you build up a series of In order to display something using @{cc.pretty}, you build up a series of
-- @{Doc|documents}. These behave a little bit like strings; you can concatenate @{Doc|documents}. These behave a little bit like strings; you can concatenate
-- them together and then print them to the screen. them together and then print them to the screen.
--
-- However, documents also allow you to control how they should be printed. There However, documents also allow you to control how they should be printed. There
-- are several functions (such as @{nest} and @{group}) which allow you to control are several functions (such as @{nest} and @{group}) which allow you to control
-- the "layout" of the document. When you come to display the document, the 'best' the "layout" of the document. When you come to display the document, the 'best'
-- (most compact) layout is used. (most compact) layout is used.
--
-- @module cc.pretty The structure of this module is based on [A Prettier Printer][prettier].
-- @usage Print a table to the terminal
-- local pretty = require "cc.pretty" [prettier]: https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf "A Prettier Printer"
-- pretty.print(pretty.pretty({ 1, 2, 3 }))
-- @module cc.pretty
-- @usage Build a custom document and display it @usage Print a table to the terminal
-- local pretty = require "cc.pretty" local pretty = require "cc.pretty"
-- pretty.print(pretty.group(pretty.text("hello") .. pretty.space_line .. pretty.text("world"))) pretty.print(pretty.pretty({ 1, 2, 3 }))
@usage Build a custom document and display it
local pretty = require "cc.pretty"
pretty.print(pretty.group(pretty.text("hello") .. pretty.space_line .. pretty.text("world")))
]]
local expect = require "cc.expect" local expect = require "cc.expect"
local expect, field = expect.expect, expect.field local expect, field = expect.expect, expect.field

View File

@ -801,6 +801,7 @@ while bRunning do
end end
else else
bMenu = false bMenu = false
term.setCursorBlink(true)
redrawMenu() redrawMenu()
end end
end end

View File

@ -0,0 +1,150 @@
/*
* 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.terminal;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class TextBufferTest
{
@Test
void testStringConstructor()
{
TextBuffer textBuffer = new TextBuffer( "test" );
assertEquals( "test", textBuffer.toString() );
}
@Test
void testCharRepetitionConstructor()
{
TextBuffer textBuffer = new TextBuffer( 'a', 5 );
assertEquals( "aaaaa", textBuffer.toString() );
}
@Test
void testLength()
{
TextBuffer textBuffer = new TextBuffer( "test" );
assertEquals( 4, textBuffer.length() );
}
@Test
void testWrite()
{
TextBuffer textBuffer = new TextBuffer( ' ', 4 );
textBuffer.write( "test" );
assertEquals( "test", textBuffer.toString() );
}
@Test
void testWriteTextBuffer()
{
TextBuffer source = new TextBuffer( "test" );
TextBuffer target = new TextBuffer( " " );
target.write( source );
assertEquals( "test", target.toString() );
}
@Test
void testWriteFromPos()
{
TextBuffer textBuffer = new TextBuffer( "test" );
textBuffer.write( "il", 1 );
assertEquals( "tilt", textBuffer.toString() );
}
@Test
void testWriteOutOfBounds()
{
TextBuffer textBuffer = new TextBuffer( "test" );
textBuffer.write( "abcdefghijklmnop", -5 );
assertEquals( "fghi", textBuffer.toString() );
}
@Test
void testWriteOutOfBounds2()
{
TextBuffer textBuffer = new TextBuffer( " " );
textBuffer.write( "Hello, world!", -3 );
assertEquals( "lo, world! ", textBuffer.toString() );
}
@Test
void testFill()
{
TextBuffer textBuffer = new TextBuffer( "test" );
textBuffer.fill( 'c' );
assertEquals( "cccc", textBuffer.toString() );
}
@Test
void testFillSubstring()
{
TextBuffer textBuffer = new TextBuffer( "test" );
textBuffer.fill( 'c', 1, 3 );
assertEquals( "tcct", textBuffer.toString() );
}
@Test
void testFillOutOfBounds()
{
TextBuffer textBuffer = new TextBuffer( "test" );
textBuffer.fill( 'c', -5, 5 );
assertEquals( "cccc", textBuffer.toString() );
}
@Test
void testCharAt()
{
TextBuffer textBuffer = new TextBuffer( "test" );
assertEquals( 'e', textBuffer.charAt( 1 ) );
}
@Test
void testSetChar()
{
TextBuffer textBuffer = new TextBuffer( "test" );
textBuffer.setChar( 2, 'n' );
assertEquals( "tent", textBuffer.toString() );
}
@Test
void testSetCharWithNegativeIndex()
{
TextBuffer textBuffer = new TextBuffer( "test" );
textBuffer.setChar( -5, 'n' );
assertEquals( "test", textBuffer.toString(), "Buffer should not change after setting char with negative index." );
}
@Test
void testSetCharWithIndexBeyondBufferEnd()
{
TextBuffer textBuffer = new TextBuffer( "test" );
textBuffer.setChar( 10, 'n' );
assertEquals( "test", textBuffer.toString(), "Buffer should not change after setting char beyond buffer end." );
}
@Test
void testMultipleOperations()
{
TextBuffer textBuffer = new TextBuffer( ' ', 5 );
textBuffer.setChar( 0, 'H' );
textBuffer.setChar( 1, 'e' );
textBuffer.setChar( 2, 'l' );
textBuffer.write( "lo", 3 );
assertEquals( "Hello", textBuffer.toString(), "TextBuffer failed to persist over multiple operations." );
}
@Test
void testEmptyBuffer()
{
TextBuffer textBuffer = new TextBuffer( "" );
// exception on writing to empty buffer would fail the test
textBuffer.write( "test" );
assertEquals( "", textBuffer.toString() );
}
}

View File

@ -67,6 +67,19 @@ describe("The paintutils library", function()
{ " ", "000", "ffe" }, { " ", "000", "ffe" },
}) })
end) end)
it("draws a line going diagonally from bottom left", function()
local w = with_window(3, 3, function()
term.setBackgroundColour(colours.red)
paintutils.drawLine(1, 3, 3, 1)
end)
window_eq(w, {
{ " ", "000", "ffe" },
{ " ", "000", "fef" },
{ " ", "000", "eff" },
})
end)
end) end)
describe("paintutils.drawBox", function() describe("paintutils.drawBox", function()