From 3a147c78a82eeffccac9413a9f2497f6fa438283 Mon Sep 17 00:00:00 2001 From: Ronan Hanley Date: Tue, 16 Mar 2021 21:19:54 +0000 Subject: [PATCH 01/14] Refactor and add tests for TextBuffer (#738) --- .../core/terminal/TextBuffer.java | 135 +--------------- .../core/terminal/TextBufferTest.java | 150 ++++++++++++++++++ 2 files changed, 157 insertions(+), 128 deletions(-) create mode 100644 src/test/java/dan200/computercraft/core/terminal/TextBufferTest.java diff --git a/src/main/java/dan200/computercraft/core/terminal/TextBuffer.java b/src/main/java/dan200/computercraft/core/terminal/TextBuffer.java index e855ff5d1..d042a2b34 100644 --- a/src/main/java/dan200/computercraft/core/terminal/TextBuffer.java +++ b/src/main/java/dan200/computercraft/core/terminal/TextBuffer.java @@ -12,46 +12,12 @@ public class TextBuffer public TextBuffer( char c, int length ) { text = new char[length]; - for( int i = 0; i < length; i++ ) - { - text[i] = c; - } + this.fill( c ); } public TextBuffer( String text ) { - this( text, 1 ); - } - - 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 ); - } - } + this.text = text.toCharArray(); } public int length() @@ -59,39 +25,16 @@ public class TextBuffer 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 ) { - write( text, 0, text.length() ); + write( text, 0 ); } 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; 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 ); for( int i = start; i < end; i++ ) { @@ -101,23 +44,10 @@ public class TextBuffer public void write( TextBuffer text ) { - write( text, 0, text.length() ); - } - - public void write( TextBuffer text, int start ) - { - write( text, start, start + text.length() ); - } - - 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++ ) + int end = Math.min( text.length(), this.text.length ); + for( int i = 0; i < end; i++ ) { - this.text[i] = text.charAt( i - pos ); + this.text[i] = text.charAt( i ); } } @@ -126,11 +56,6 @@ public class TextBuffer 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 ) { 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 ) { return text[i]; diff --git a/src/test/java/dan200/computercraft/core/terminal/TextBufferTest.java b/src/test/java/dan200/computercraft/core/terminal/TextBufferTest.java new file mode 100644 index 000000000..286e62ad6 --- /dev/null +++ b/src/test/java/dan200/computercraft/core/terminal/TextBufferTest.java @@ -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() ); + } +} From 32d956bbe7d2bb32f06cc25ceaf69f59ddace631 Mon Sep 17 00:00:00 2001 From: Wojbie Date: Fri, 19 Mar 2021 16:07:20 +0100 Subject: [PATCH 02/14] Fix missing `term.setCursorBlink(true)` in edit.lua --- src/main/resources/data/computercraft/lua/rom/programs/edit.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/data/computercraft/lua/rom/programs/edit.lua b/src/main/resources/data/computercraft/lua/rom/programs/edit.lua index f67bd0ede..c913aa234 100644 --- a/src/main/resources/data/computercraft/lua/rom/programs/edit.lua +++ b/src/main/resources/data/computercraft/lua/rom/programs/edit.lua @@ -801,6 +801,7 @@ while bRunning do end else bMenu = false + term.setCursorBlink(true) redrawMenu() end end From e48427dbbcb9c0c2211564733e69dd66135b2b25 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sun, 28 Mar 2021 19:38:25 +0100 Subject: [PATCH 03/14] Add documentation for io.setvbuf Fixes #746. Love how "good first issue" guarantees that nobody will do it. Not actually true, and thank you for those people who have contributed! --- .../resources/data/computercraft/lua/rom/apis/io.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/resources/data/computercraft/lua/rom/apis/io.lua b/src/main/resources/data/computercraft/lua/rom/apis/io.lua index 5ecbdf652..4898df308 100644 --- a/src/main/resources/data/computercraft/lua/rom/apis/io.lua +++ b/src/main/resources/data/computercraft/lua/rom/apis/io.lua @@ -137,6 +137,15 @@ handleMetatable = { return handle.seek(whence, offset) 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, --- Write one or more values to the file From 9708dd67864143d1588697d81cdeae97c66fbb26 Mon Sep 17 00:00:00 2001 From: lily <56274881+lilyzeiset@users.noreply.github.com> Date: Fri, 2 Apr 2021 10:30:28 -0400 Subject: [PATCH 04/14] Fixed sortCoords for draw functions (#749) --- .../data/computercraft/lua/rom/apis/paintutils.lua | 12 +++++++++++- .../test-rom/spec/apis/paintutils_spec.lua | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/resources/data/computercraft/lua/rom/apis/paintutils.lua b/src/main/resources/data/computercraft/lua/rom/apis/paintutils.lua index b920341c3..f6f1efaac 100644 --- a/src/main/resources/data/computercraft/lua/rom/apis/paintutils.lua +++ b/src/main/resources/data/computercraft/lua/rom/apis/paintutils.lua @@ -132,7 +132,17 @@ function drawLine(startX, startY, endX, endY, colour) return 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? diff --git a/src/test/resources/test-rom/spec/apis/paintutils_spec.lua b/src/test/resources/test-rom/spec/apis/paintutils_spec.lua index fc2b6008c..f13bbcfd2 100644 --- a/src/test/resources/test-rom/spec/apis/paintutils_spec.lua +++ b/src/test/resources/test-rom/spec/apis/paintutils_spec.lua @@ -67,6 +67,19 @@ describe("The paintutils library", function() { " ", "000", "ffe" }, }) 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) describe("paintutils.drawBox", function() From 51d3b091da4e4083f3616e5ed65fdfceaaf90cd0 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sat, 3 Apr 2021 12:44:22 +0100 Subject: [PATCH 05/14] "Finish" documentation for several modules - Add remaining docs for the turtle API - Add documentation for the fluid storage peripheral. - Enforce undocumented warning for most modules (only io and window remaining). "Finish" in quotes, because these are clearly a long way from perfect. I'm bad at writing docs, OK! --- doc/stub/turtle.lua | 12 ++ illuaminate.sexp | 21 +--- .../generic/methods/FluidMethods.java | 45 +++++++ .../generic/methods/InventoryMethods.java | 4 +- .../shared/turtle/apis/TurtleAPI.java | 118 ++++++++++++++++++ .../lua/rom/apis/turtle/turtle.lua | 1 + 6 files changed, 183 insertions(+), 18 deletions(-) diff --git a/doc/stub/turtle.lua b/doc/stub/turtle.lua index f5668f1ae..a2c0eef55 100644 --- a/doc/stub/turtle.lua +++ b/doc/stub/turtle.lua @@ -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 diff --git a/illuaminate.sexp b/illuaminate.sexp index 61f671582..22d222f7e 100644 --- a/illuaminate.sexp +++ b/illuaminate.sexp @@ -88,27 +88,16 @@ ;; Suppress warnings for currently undocumented modules. (at - (; Java 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 + (; Lua APIs /src/main/resources/*/computercraft/lua/rom/apis/io.lua /src/main/resources/*/computercraft/lua/rom/apis/window.lua) (linters -doc:undocumented -doc:undocumented-arg -doc:undocumented-return)) -;; Suppress warnings for the BIOS using its own deprecated members for now. -(at /src/main/resources/*/computercraft/lua/bios.lua +;; Suppress warnings for various APIs using its own deprecated members. +(at + (/src/main/resources/*/computercraft/lua/bios.lua + /src/main/resources/*/computercraft/lua/rom/apis/turtle/turtle.lua) (linters -var:deprecated)) (at /src/test/resources/test-rom diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java index a9d206f5a..9c994aa6e 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/FluidMethods.java @@ -45,6 +45,19 @@ public class FluidMethods implements GenericSource 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 ) public static Map> tanks( IFluidHandler fluids ) { @@ -59,6 +72,22 @@ public class FluidMethods implements GenericSource 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 on the same wired + * network. 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 ) public static int pushFluid( IFluidHandler from, IComputerAccess computer, @@ -84,6 +113,22 @@ public class FluidMethods implements GenericSource : 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 on the same wired + * network. 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 ) public static int pullFluid( IFluidHandler to, IComputerAccess computer, diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java index 0663d66ad..64e342b30 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java @@ -65,8 +65,8 @@ public class InventoryMethods implements GenericSource * {@link dan200.computercraft.shared.turtle.apis.TurtleAPI#getItemDetail} includes. More information can be fetched * with {@link #getItemDetail}. * - * The table is sparse, and so empty slots will be `nil` - it is recommended to loop over using `pairs` rather than - * `ipairs`. + * The returned table is sparse, and so empty slots will be `nil` - it is recommended to loop over using `pairs` + * rather than `ipairs`. * * @param inventory The current inventory. * @return All items in this inventory. diff --git a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java index 671c9a3b7..cd3862b07 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java +++ b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java @@ -371,18 +371,36 @@ public class TurtleAPI implements ILuaAPI 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 public final MethodResult compare() { 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 public final MethodResult compareUp() { 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 public final MethodResult compareDown() { @@ -478,12 +496,57 @@ public class TurtleAPI implements ILuaAPI 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 public final Object getFuelLevel() { 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. + *
{@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}
+ * @cc.usage Check if the current item is a valid fuel source. + *
{@code
+     * local is_fuel, reason = turtle.refuel(0)
+     * if not is_fuel then printError(reason) end
+     * }
+ * @see #getFuelLevel() + * @see #getFuelLimit() + */ @LuaFunction public final MethodResult refuel( Optional countA ) throws LuaException { @@ -492,12 +555,30 @@ public class TurtleAPI implements ILuaAPI 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 public final MethodResult compareTo( int slot ) throws LuaException { 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 public final MethodResult transferTo( int slotArg, Optional countArg ) throws LuaException { @@ -518,18 +599,55 @@ public class TurtleAPI implements ILuaAPI 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 public final Object getFuelLimit() { 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 public final MethodResult equipLeft() { 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 public final MethodResult equipRight() { diff --git a/src/main/resources/data/computercraft/lua/rom/apis/turtle/turtle.lua b/src/main/resources/data/computercraft/lua/rom/apis/turtle/turtle.lua index c9d57bf12..0a66add16 100644 --- a/src/main/resources/data/computercraft/lua/rom/apis/turtle/turtle.lua +++ b/src/main/resources/data/computercraft/lua/rom/apis/turtle/turtle.lua @@ -10,6 +10,7 @@ end -- -- Generally you should not need to use this table - it only exists for -- backwards compatibility reasons. +-- @deprecated native = turtle.native or turtle local function addCraftMethod(object) From e8f5531a8c45718baf7d56d828278727782f7de6 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sat, 3 Apr 2021 12:55:20 +0100 Subject: [PATCH 06/14] Fix checkstyle --- .../shared/turtle/apis/TurtleAPI.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java index cd3862b07..6c87be3d2 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java +++ b/src/main/java/dan200/computercraft/shared/turtle/apis/TurtleAPI.java @@ -500,8 +500,8 @@ public class TurtleAPI implements ILuaAPI * 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. + * @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) */ @@ -524,9 +524,9 @@ public class TurtleAPI implements ILuaAPI * @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.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. *
{@code
      * local level = turtle.getFuelLevel()
@@ -605,8 +605,8 @@ public class TurtleAPI implements ILuaAPI
      * 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.
+     * @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)
      */
@@ -624,9 +624,9 @@ public class TurtleAPI implements ILuaAPI
      * 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.
+     * @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
@@ -643,9 +643,9 @@ public class TurtleAPI implements ILuaAPI
      * 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.
+     * @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

From b17ff6daf03e0be2b919a2cab3846ac6b0b6cd45 Mon Sep 17 00:00:00 2001
From: Jonathan Coates 
Date: Sat, 3 Apr 2021 14:08:58 +0100
Subject: [PATCH 07/14] Fix a couple of JEI issues

 - Don't treat turtles/pocket computers with no upgrades as an "any"
   turtle. Otherwise getting the recipe of a crafty turtle shows the
   recipe of a normal turtle too.
 - Fix "get usage" of upgrade items not returning their recipes.
 - Fix NPEs inside JEI (closes #719)
---
 .../shared/integration/jei/JEIComputerCraft.java     | 12 ++++++------
 .../shared/integration/jei/RecipeResolver.java       |  9 +--------
 2 files changed, 7 insertions(+), 14 deletions(-)

diff --git a/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java b/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java
index a6ea2fc91..cb4ca8e81 100644
--- a/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java
+++ b/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java
@@ -114,10 +114,10 @@ public class JEIComputerCraft implements IModPlugin
      */
     private static final ISubtypeInterpreter turtleSubtype = stack -> {
         Item item = stack.getItem();
-        if( !(item instanceof ITurtleItem) ) return "";
+        if( !(item instanceof ITurtleItem) ) return ISubtypeInterpreter.NONE;
 
         ITurtleItem turtle = (ITurtleItem) item;
-        StringBuilder name = new StringBuilder();
+        StringBuilder name = new StringBuilder("turtle:");
 
         // Add left and right upgrades to the identifier
         ITurtleUpgrade left = turtle.getUpgrade( stack, TurtleSide.LEFT );
@@ -134,9 +134,9 @@ public class JEIComputerCraft implements IModPlugin
      */
     private static final ISubtypeInterpreter pocketSubtype = stack -> {
         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
         IPocketUpgrade upgrade = ItemPocketComputer.getUpgrade( stack );
@@ -150,11 +150,11 @@ public class JEIComputerCraft implements IModPlugin
      */
     private static final ISubtypeInterpreter diskSubtype = stack -> {
         Item item = stack.getItem();
-        if( !(item instanceof ItemDisk) ) return "";
+        if( !(item instanceof ItemDisk) ) return ISubtypeInterpreter.NONE;
 
         ItemDisk disk = (ItemDisk) item;
 
         int colour = disk.getColour( stack );
-        return colour == -1 ? "" : String.format( "%06x", colour );
+        return colour == -1 ? ISubtypeInterpreter.NONE : String.format( "%06x", colour );
     };
 }
diff --git a/src/main/java/dan200/computercraft/shared/integration/jei/RecipeResolver.java b/src/main/java/dan200/computercraft/shared/integration/jei/RecipeResolver.java
index a3a4810d6..2050a83e7 100644
--- a/src/main/java/dan200/computercraft/shared/integration/jei/RecipeResolver.java
+++ b/src/main/java/dan200/computercraft/shared/integration/jei/RecipeResolver.java
@@ -200,7 +200,7 @@ class RecipeResolver implements IRecipeManagerPlugin
             for( UpgradeInfo upgrade : upgrades )
             {
                 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;
                 }
@@ -319,13 +319,6 @@ class RecipeResolver implements IRecipeManagerPlugin
             super( ID, null, width, height, input, output );
         }
 
-        @Nonnull
-        @Override
-        public ResourceLocation getId()
-        {
-            return null;
-        }
-
         @Nonnull
         @Override
         public IRecipeSerializer getSerializer()

From c3f57004943aa515a5ff83329c20a5bc72ba50b2 Mon Sep 17 00:00:00 2001
From: Jonathan Coates 
Date: Sat, 3 Apr 2021 14:13:55 +0100
Subject: [PATCH 08/14] Fix checkstyle

Today is not a good day apparently :D:.
---
 .../shared/integration/jei/JEIComputerCraft.java              | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java b/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java
index cb4ca8e81..ae8f9589f 100644
--- a/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java
+++ b/src/main/java/dan200/computercraft/shared/integration/jei/JEIComputerCraft.java
@@ -117,7 +117,7 @@ public class JEIComputerCraft implements IModPlugin
         if( !(item instanceof ITurtleItem) ) return ISubtypeInterpreter.NONE;
 
         ITurtleItem turtle = (ITurtleItem) item;
-        StringBuilder name = new StringBuilder("turtle:");
+        StringBuilder name = new StringBuilder( "turtle:" );
 
         // Add left and right upgrades to the identifier
         ITurtleUpgrade left = turtle.getUpgrade( stack, TurtleSide.LEFT );
@@ -136,7 +136,7 @@ public class JEIComputerCraft implements IModPlugin
         Item item = stack.getItem();
         if( !(item instanceof ItemPocketComputer) ) return ISubtypeInterpreter.NONE;
 
-        StringBuilder name = new StringBuilder("pocket:");
+        StringBuilder name = new StringBuilder( "pocket:" );
 
         // Add the upgrade to the identifier
         IPocketUpgrade upgrade = ItemPocketComputer.getUpgrade( stack );

From 17b5bca4434fc84dd7321f9d50300f17497c6dde Mon Sep 17 00:00:00 2001
From: Jonathan Coates 
Date: Wed, 7 Apr 2021 18:34:55 +0100
Subject: [PATCH 09/14] Make the peripheral API examples a little clearer

---
 .../computercraft/lua/rom/apis/peripheral.lua | 33 ++++++++++++-------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/src/main/resources/data/computercraft/lua/rom/apis/peripheral.lua b/src/main/resources/data/computercraft/lua/rom/apis/peripheral.lua
index c284d0691..0f3478046 100644
--- a/src/main/resources/data/computercraft/lua/rom/apis/peripheral.lua
+++ b/src/main/resources/data/computercraft/lua/rom/apis/peripheral.lua
@@ -161,7 +161,9 @@ end
 -- @tparam string name The name of the peripheral to wrap.
 -- @treturn table|nil The table containing the peripheral's methods, or `nil` if
 -- 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)
     expect(1, name, "string")
 
@@ -183,16 +185,25 @@ function wrap(name)
     return result
 end
 
---- Find all peripherals of a specific type, and return the
--- @{peripheral.wrap|wrapped} peripherals.
---
--- @tparam string ty The type of peripheral to look for.
--- @tparam[opt] function(name:string, wrapped:table):boolean filter A
--- filter function, which takes the peripheral's name and wrapped table
--- and returns if it should be included in the result.
--- @treturn table... 0 or more wrapped peripherals matching the given filters.
--- @usage { peripheral.find("monitor") }
--- @usage peripheral.find("modem", rednet.open)
+--[[- Find all peripherals of a specific type, and return the
+@{peripheral.wrap|wrapped} peripherals.
+
+@tparam string ty The type of peripheral to look for.
+@tparam[opt] function(name:string, wrapped:table):boolean filter A
+filter function, which takes the peripheral's name and wrapped table
+and returns if it should be included in the result.
+@treturn table... 0 or more wrapped peripherals matching the given filters.
+@usage Find all monitors and store them in a table, writing "Hello" on each one.
+
+    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)
     expect(1, ty, "string")
     expect(2, filter, "function", "nil")

From 058d63e77ffe45fea917dde8a641277c68b53be2 Mon Sep 17 00:00:00 2001
From: Jonathan Coates 
Date: Sun, 11 Apr 2021 18:43:24 +0100
Subject: [PATCH 10/14] Add citation to cc.pretty

ust to look extra pretentious.
---
 .../lua/rom/modules/main/cc/pretty.lua        | 45 ++++++++++---------
 1 file changed, 25 insertions(+), 20 deletions(-)

diff --git a/src/main/resources/data/computercraft/lua/rom/modules/main/cc/pretty.lua b/src/main/resources/data/computercraft/lua/rom/modules/main/cc/pretty.lua
index 9a3aa7b0a..f202c204e 100644
--- a/src/main/resources/data/computercraft/lua/rom/modules/main/cc/pretty.lua
+++ b/src/main/resources/data/computercraft/lua/rom/modules/main/cc/pretty.lua
@@ -1,23 +1,28 @@
---- Provides a "pretty printer", for rendering data structures in an
--- aesthetically pleasing manner.
---
--- 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
--- them together and then print them to the screen.
---
--- 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
--- the "layout" of the document. When you come to display the document, the 'best'
--- (most compact) layout is used.
---
--- @module cc.pretty
--- @usage Print a table to the terminal
---     local pretty = require "cc.pretty"
---     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")))
+--[[- Provides a "pretty printer", for rendering data structures in an
+aesthetically pleasing manner.
+
+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
+them together and then print them to the screen.
+
+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
+the "layout" of the document. When you come to display the document, the 'best'
+(most compact) layout is used.
+
+The structure of this module is based on [A Prettier Printer][prettier].
+
+[prettier]: https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf "A Prettier Printer"
+
+@module cc.pretty
+@usage Print a table to the terminal
+    local pretty = require "cc.pretty"
+    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, field = expect.expect, expect.field

From 8494ba8ce29cd8d7b9105eef497fe3fe3f89d350 Mon Sep 17 00:00:00 2001
From: Jonathan Coates 
Date: Tue, 13 Apr 2021 13:01:28 +0100
Subject: [PATCH 11/14] Improve UX when a resource mount cannot be found

 - Add a full example of the docs. Hopefully is a little more explicit.
 - Print a warning when the mount is empty.

Closes #762
---
 .../dan200/computercraft/api/ComputerCraftAPI.java  |  4 +++-
 .../core/filesystem/ResourceMount.java              | 13 +++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java b/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java
index f429ca946..2c4223725 100644
--- a/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java
+++ b/src/main/java/dan200/computercraft/api/ComputerCraftAPI.java
@@ -98,7 +98,9 @@ public final class ComputerCraftAPI
      * 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
-     * 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 subPath The subPath under which to look for resources. eg: "lua/myfiles".
diff --git a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java
index ed21df789..afaa3dbb9 100644
--- a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java
+++ b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java
@@ -103,9 +103,13 @@ public final class ResourceMount implements IMount
     private void load()
     {
         boolean hasAny = false;
+        String existingNamespace = null;
+
         FileEntry newRoot = new FileEntry( new ResourceLocation( namespace, subPath ) );
         for( ResourceLocation file : manager.listResources( subPath, s -> true ) )
         {
+            existingNamespace = file.getNamespace();
+
             if( !file.getNamespace().equals( namespace ) ) continue;
 
             String localPath = FileSystem.toLocal( file.getPath(), subPath );
@@ -114,6 +118,15 @@ public final class ResourceMount implements IMount
         }
 
         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 )

From c45221a2d0e91eaebabc495a817c009e6dc6b321 Mon Sep 17 00:00:00 2001
From: Jonathan Coates 
Date: Tue, 13 Apr 2021 13:03:26 +0100
Subject: [PATCH 12/14] Fix checkstyle

This is gonna be 50% of my commits at this rate.
---
 .../dan200/computercraft/core/filesystem/ResourceMount.java   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java
index afaa3dbb9..279871e50 100644
--- a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java
+++ b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java
@@ -121,10 +121,10 @@ public final class ResourceMount implements IMount
 
         if( !hasAny )
         {
-            ComputerCraft.log.warn("Cannot find any files under /data/{}/{} for resource mount.", namespace, subPath);
+            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);
+                ComputerCraft.log.warn( "There are files under /data/{}/{} though. Did you get the wrong namespace?", existingNamespace, subPath );
             }
         }
     }

From 003c7ec2e87235d093b7e82de0383c21293d767e Mon Sep 17 00:00:00 2001
From: Jonathan Coates 
Date: Fri, 23 Apr 2021 22:26:00 +0100
Subject: [PATCH 13/14] Fix Forge maven location

1.16 is going to be sad for a while, as I need to work out FG 4 woes.
---
 build.gradle | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/build.gradle b/build.gradle
index 7230d002b..416675f2e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,12 +4,12 @@ buildscript {
         mavenCentral()
         maven {
             name = "forge"
-            url = "https://files.minecraftforge.net/maven"
+            url = "https://maven.minecraftforge.net"
         }
     }
     dependencies {
         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'
     }
 }

From 92b45b18682e3e9f588bce5472cd1490ca764808 Mon Sep 17 00:00:00 2001
From: Jonathan Coates 
Date: Sat, 24 Apr 2021 11:26:04 +0100
Subject: [PATCH 14/14] Switch to using maven-publish

The old maven package is removed in Gradle 7.0. Instead, we publish to
squiddev.cc using WebDAV (ewww).
---
 build.gradle | 87 +++++++++++++++++++++-------------------------------
 1 file changed, 35 insertions(+), 52 deletions(-)

diff --git a/build.gradle b/build.gradle
index 416675f2e..2ede63c40 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,6 +17,7 @@ buildscript {
 plugins {
     id "checkstyle"
     id "jacoco"
+    id "maven-publish"
     id "com.github.hierynomus.license" version "0.15.0"
     id "com.matthewprenger.cursegradle" version "1.4.0"
     id "com.github.breadmoirai.github-release" version "2.2.12"
@@ -24,8 +25,6 @@ plugins {
 }
 
 apply plugin: 'net.minecraftforge.gradle'
-apply plugin: 'maven-publish'
-apply plugin: 'maven'
 
 version = mod_version
 
@@ -36,6 +35,9 @@ java {
     toolchain {
         languageVersion = JavaLanguageVersion.of(8)
     }
+
+    withSourcesJar()
+    withJavadocJar()
 }
 
 minecraft {
@@ -112,7 +114,6 @@ repositories {
 configurations {
     shade
     compile.extendsFrom shade
-    deployerJars
     cctJavadoc
 }
 
@@ -139,8 +140,6 @@ dependencies {
     testImplementation 'org.jetbrains.kotlin:kotlin-reflect:1.3.72'
     testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
 
-    deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
-
     cctJavadoc 'cc.tweaked:cct-javadoc:1.3.0'
 }
 
@@ -168,8 +167,6 @@ task luaJavadoc(type: Javadoc) {
 }
 
 jar {
-    dependsOn javadoc
-
     manifest {
         attributes(["Specification-Title": "computercraft",
                     "Specification-Vendor": "SquidDev",
@@ -180,10 +177,6 @@ jar {
                     "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) }
 }
 
@@ -550,51 +543,41 @@ curseforge {
 
 publishing {
     publications {
-        mavenJava(MavenPublication) {
+        maven(MavenPublication) {
             from components.java
-            // artifact sourceJar
+
+            pom {
+                name = 'CC: Tweaked'
+                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 {
+                    url = 'https://github.com/SquidDev-CC/CC-Tweaked.git'
+                }
+
+                issueManagement {
+                    system = 'github'
+                    url = 'https://github.com/SquidDev-CC/CC-Tweaked/issues'
+                }
+
+                licenses {
+                    license {
+                        name = 'ComputerCraft Public License, Version 1.0'
+                        url = 'https://github.com/SquidDev-CC/CC-Tweaked/blob/mc-1.15.x/LICENSE'
+                    }
+                }
+            }
         }
     }
-}
 
-uploadArchives {
     repositories {
-        if(project.hasProperty('mavenUploadUrl')) {
-            mavenDeployer {
-                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 {
-                        url 'https://github.com/SquidDev-CC/CC-Tweaked.git'
-                    }
-
-                    issueManagement {
-                        system 'github'
-                        url 'https://github.com/SquidDev-CC/CC-Tweaked/issues'
-                    }
-
-                    licenses {
-                        license {
-                            name 'ComputerCraft Public License, Version 1.0'
-                            url 'https://github.com/SquidDev-CC/CC-Tweaked/blob/master/LICENSE'
-                            distribution 'repo'
-                        }
-                    }
-                }
-
-                pom.whenConfigured { pom ->
-                    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
                 }
             }
         }
@@ -625,7 +608,7 @@ githubRelease {
     prerelease false
 }
 
-def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"]
+def uploadTasks = ["publish", "curseforge", "githubRelease"]
 uploadTasks.forEach { tasks.getByName(it).dependsOn checkRelease }
 
 task uploadAll(dependsOn: uploadTasks) {