1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-17 06:57:38 +00:00

Compare commits

..

132 Commits

Author SHA1 Message Date
SquidDev
0f82a4589b Fix complaints 2019-12-24 19:31:14 +00:00
SquidDev
4320a4f851 Update CT integration
Sadly we have to disable -Werror, as the annotation class files are not
available on maven, so this produces a warning.
2019-12-24 19:16:06 +00:00
SquidDev
037cbabb32 Merge branch 'master' into mc-1.14.x
Unfortunately we can't apply the config changes due to backwards
compatibility. This'll be something we may need to PR into Forge.

CraftTweaker support still needs to be added.
2019-12-23 22:34:30 +00:00
SquidDev
0dde859582 Bump version 2019-12-23 22:10:32 +00:00
SquidDev
e59c043fb6 Fix a couple of comments to use the new config names 2019-12-23 21:34:03 +00:00
SquidDev
ae928c4397 Make http domain configuration a little clearer 2019-12-23 18:59:36 +00:00
SquidDev
da41c65128 Update proguard configuration
- Remove redundant preservation of cobalt lib constructors. We use
   lambdas now, so this is no longer needed.
 - Fix Java crypto lib not being included.
2019-12-23 18:54:19 +00:00
SquidDev
4d18234714 Use a fake network handler too
It appears that WB opens containers manually, and thus all of our stubs
network stubs are entirely ignored. Thus the only solution here is to
stub out the whole network handler code.

Thankfully this is simple enough - we do the same for Plethora and 1.14.

Fixes #328
2019-12-23 17:17:32 +00:00
JakobDev
d254c6464b Add more MOTD messages again (#241) 2019-12-23 14:43:48 +00:00
Jonathan Coates
3a5d50e572 Basic Minetweaker support (#327)
This provides the following methods:

 - dan200.computercraft.turtle.removeUpgrade(id: String)
 - dan200.computercraft.turtle.removeUpgrade(stack: IItemStack)
 - dan200.computercraft.turtle.addTool(id: String, craftItem: IItemStack[, toolItem: IItemStack][, kind: string])

While it's pretty minimal, it should allow for a reasonable amount of
functionality.

Closes #327 and #97.
2019-12-18 15:29:24 +00:00
Jonathan Coates
03b6d2f1ab Replace string.len with # 2019-12-10 18:55:11 +00:00
Jared Allard
b0397ed3c5 Add support for HTTP PATCH and TRACE (#324) 2019-12-08 17:10:58 +00:00
Jonathan Coates
fa70ebcac2 Fix spacing on all of the rom (#323) 2019-12-07 10:33:47 +00:00
SquidDev
86e0330100 Lint bios and the rom (#321)
We now use illuaminate[1]'s linting facilities to check the rom and
bios.lua for a couple of common bugs and other problems.

Right now this doesn't detect any especially important bugs, though it
has caught lots of small things (unused variables, some noisy code). In
the future, the linter will grow in scope and features, which should
allow us to be stricter and catch most issues.

As a fun aside, we started off with ~150 bugs, and illuaminate was able
to fix all but 30 of them, which is pretty neat.

[1]: https://github.com/SquidDev/illuaminate
2019-12-03 23:26:13 +00:00
SquidDev
92567b4d7e Merge branch 'master' into mc-1.14.x 2019-11-29 20:23:56 +00:00
SquidDev
0ae70fed13 Correctly implement mouse movement within read
Note to self: if you're going to modify the rom, make sure you test on a
computer which doesn't overwrite the rom with something else.
2019-11-29 20:15:58 +00:00
SquidDev
3b7300543a Correctly invalidate the ROM mount cache
Before it would remain the same across world reloads, and thus would be
out-of-date after leaving the first world. This architecture technically
allows for running multiple servers at once, though that's not going to
matter that soon.
2019-11-26 18:16:49 +00:00
SquidDev
642351af1a Merge branch 'master' into mc-1.14.x 2019-11-25 09:15:20 +00:00
SquidDev
121802a683 Bump version 2019-11-25 08:58:36 +00:00
SquidDev
08cf55e55f Correct implementation of clamp
That's what I get for inlining definitions.
2019-11-23 14:36:43 +00:00
SquidDev
3c8c0d78ef Use correct render type for turtles
This fixes them not rendering particles when broken. Particle rendering
is a little janky right now, as it uses the whole texture - we should
probably split up the texture into smaller images. Fixes #315
2019-11-23 13:24:36 +00:00
SquidDev
c4d18aa9ca Allow navigating read's input using the mouse 2019-11-23 13:21:07 +00:00
SquidDev
2d4a87adc9 Fix the eye height for turtle fake players
This was causing the eye height of the turtle to be above it when
placing down, causing all sorts of funkiness. Fixes #297
2019-11-23 13:05:26 +00:00
SquidDev
bedac71e3d Add a fake network handler to the TurtleFakePlayer
This should fix several issues (see #304, etc...). I'll try to get round
to PRing this into Forge at some point, though on the other hand this is
/super/ ugly.
2019-11-23 12:12:02 +00:00
SquidDev
ee4e42e730 Dont' remove treasure disks from JEI
This shouldn't matter either way - we don't expose it in the creative
menu, and there's no recipes for it. This should shut up a log message
though. Fixes #305.
2019-11-23 11:23:25 +00:00
SquidDev
0de75f05dd Make parameter name a bit nicer
Woops
2019-11-23 11:17:03 +00:00
SquidDev
be6dd21e54 Make monitors "properly" solid blocks
This fixes monitor rendering underwater (closes #314). By default,
isSolid returns true if the render layer is SOLID. As we use CUTOUT due
to our funky TE rendering, we need to override this to return true
anyway.

This will cause some side effects, as monitors now blocking light
propagation, but I don't think that's the end of the world.
2019-11-23 10:31:55 +00:00
SquidDev
927ddb0bde Remove Charset and MCMP integration for now
It's not clear if either of these are coming back soon, and it should be
fairly simple to add them back when needed.
2019-11-23 10:14:32 +00:00
SquidDev
a8fadabaf1 Correct spelling in error message 2019-11-23 09:59:37 +00:00
SquidDev
44d0f78c1b Bump versions 2019-11-23 09:58:54 +00:00
SquidDev
38f9a015ca Wrap all remaining uses of Grgit
This allows you to build from a zip folder of CC:T. Fixes #307. Also fix
the build, woops.
2019-10-30 17:07:29 +00:00
SquidDev
c311cdc6f5 Make our Javadoc validation a little stricter
I'm not sure there's much utility in this, but still feels worth doing.
2019-10-27 15:16:47 +00:00
SquidDev
a93e0f3284 Expose ArgumentHelper in the public API
This is sufficiently useful a class, that it's worthwhile exposing it.
Hopefully we can slowly encourage other mods to migrate to it (well, at
least in 1.14), and so make error messages more consistent.

Also:
 - Add Javadoc for all public methods
 - Clarify the method names a little (getNumber -> getDouble,
   getReal -> getFiniteDouble).
 - Make the *Table methods return a Map<?,?> instead of
   Map<Object, Object>.
2019-10-27 14:29:07 +00:00
SquidDev
14b3065ba4 Check for trailing whitespace
I'd rather assumed one of the existing checkers did this already, but
apparently not.
2019-10-16 09:22:38 +01:00
SquidDev
3ea2d6a0a8 Merge branch 'master' into mc-1.14.x 2019-10-04 19:56:49 +01:00
SquidDev
c802290437 Bump version 2019-10-04 19:52:02 +01:00
SquidDev
f7781defe5 Merge branch 'master' into mc-1.14.x 2019-10-04 19:44:34 +01:00
SquidDev
418420523a Proxy the current turtle's inventory
Previously we were just returning the current tile. However, if someone
was holding a reference to this inventory (such as a GUI), then it'd be
outdated and invalid once the turtle had moved.

This caused a couple of issues:
 - turtle_inventory events would not be fired when moving items in the
   turtle GUI.
 - As of 75e2845c01, turtles would no
   longer share their inventory state after moving. Thus, removing items
   from a GUI using an invalid inventory would move them from an old
   tile, duplicating the items.

Fixes #298, fixes #300
2019-10-04 16:53:48 +01:00
SquidDev
d342a1f368 Prevent wired modems dropping on block change
Fixes #303
2019-10-01 20:06:38 +01:00
SquidDev
81f85361d5 Move Lua files to the correct location
I really need to fix this.
2019-10-01 19:43:03 +01:00
SquidDev
f1621b30ec Remove redundant imports 2019-10-01 19:15:13 +01:00
SquidDev
d4f6a594b6 Merge branch 'master' into mc-1.14.x 2019-10-01 18:58:40 +01:00
SquidDev
ff5ba5c131 Update GUI code to be compatible with 1.14.4
Not quite sure when this changed, but I'm fairly sure isMouseOver wasn't
a thing when I wrote this. Or I'm a plonker. Both are possible.

Also fixes mouse dragging not being handled in turtles.

Fixes #299
2019-10-01 18:53:46 +01:00
SquidDev
4243f30308 Bump Forge version 2019-10-01 18:53:38 +01:00
Jonathan Coates
813e91073d Merge pull request #302 from Wendelstein7/master
Fixed turtle property category
2019-09-30 15:59:55 +01:00
Jonathan Coates
7250f22ff6 Update CI to also run on PRs 2019-09-30 15:37:52 +01:00
Wendelstein7
db31a53bba Fixed turtle property category
Likely was a leftover from copy pasting and a tired programmer.
2019-09-30 15:15:22 +02:00
SquidDev
3023f235a4 Goodbye Travis, I'm with GH Actions now 2019-09-27 08:56:53 +01:00
SquidDev
79cd8b4da5 Also return the number of affected entities
Closes #293. Doesn't really solve anything there aside from exposing the
number, but sadly there's not really anything obvious I can do on my end
- the command API just doesn't expose anything else.
2019-09-15 18:48:51 +01:00
Jonathan Coates
8e4d311cd9 Refactor shell completion into a separate module (#281)
- Adds cc.completions module, with a couple of helper functions for
   working with the more general completion functionality (i.e. that
   provided by read).
 - Adds cc.shell.completions module, which provides shell-specific
   completion functions.
 - Add a "program completion builder", which allows you to write stuff
   like this:

       shell.setCompletionFunction( "rom/programs/redstone.lua", 
         completion.build(
           { completion.choice, { "probe", "set ", "pulse " } },
           completion.side) )

Closes #232
2019-09-15 18:48:40 +01:00
SquidDev
9bd8c86a94 Change event priority to HIGHEST
See the comments in a802f25dd6 -
effectively we want to make sure we arrive before any other thing which
may capture items (some magnet mods, etc...).
2019-09-15 16:42:21 +01:00
Jonathan Coates
cbc0c1d0b6 A little experiment with GitHub actions
Let's give this a go.
2019-09-14 09:16:13 +01:00
SquidDev
49c37857d4 Window.reposition now allow changing the redirect buffer
See #270
2019-09-13 20:55:20 +01:00
SquidDev
b1139a4bf6 Bump to Forge RB 2019-09-12 21:09:57 +01:00
Jonathan Coates
7e8559278e Merge pull request #291 from parly/patch-1.14.x-1
Fix os.time() and os.day() behavior on 1.14
2019-08-19 15:34:20 +01:00
parly
1e7f1c98fc Fix os.time() and os.day() behavior 2019-08-19 23:04:57 +09:00
SquidDev
a802f25dd6 Do not listen to block/entity drop events
It appears several mods inject their own drops on the LOWEST priority,
meaning that we capture the existing drops, and the other mod will clear
the (now empty) drop list and add its own, resulting in dupe bugs.

While I'd argue it's somewhat dubious doing this on the LOWEST priority,
it's not a battle I'm prepared to fight. For now, we just remove the
block/entity drop handlers, and handle all drop logic when entities are
spawned.

Fixes #288
2019-08-19 10:33:53 +01:00
SquidDev
f1d6d21d6d Add back texture registration hook
I totally forgot to do this when Forge re-added this functionality.

Fixes #285
2019-08-18 16:12:16 +01:00
Jonathan Coates
a80302c513 Merge pull request #287 from Lignum/patch-1
The pettiest of spelling fixes
2019-08-15 06:59:59 +01:00
Lignum
1c46949da7 Available 2019-08-15 07:37:02 +02:00
SquidDev
07a56454a0 Bumpity bumpity bump 2019-08-09 09:38:30 +01:00
SquidDev
a0e72d02c8 Bump Forge version 2019-08-06 08:33:39 +01:00
SquidDev
455a59ca85 Sure, you can be an actual release now 2019-08-04 17:01:52 +01:00
SquidDev
46d78af068 Fix changelog being out-of-sync 2019-08-04 11:05:44 +01:00
SquidDev
08d22fd3df Fix changelog being out-of-sync 2019-08-04 11:05:14 +01:00
SquidDev
e6c691a8f8 Fix rom's location
This isn't going to get annoying or anything
2019-08-04 11:02:07 +01:00
SquidDev
4b0e5c445c Merge branch 'master' into mc-1.14.x 2019-08-04 10:57:20 +01:00
SquidDev
eb5cff1045 Alright, let's do this one last time 2019-08-04 09:27:48 +01:00
SquidDev
35c7792aa2 Limit the titles of printed pages
Just enforce the same restrictions as we do for computer/disk labels.
2019-08-04 08:59:44 +01:00
Jonathan Coates
521688d630 Merge pull request #183 from SquidDev-CC/feature/thread-safe-inventories 2019-08-01 14:30:32 +01:00
SquidDev
75e2845c01 Remove synchronized from turtle inventory code
These should never be called off the server thread, so this doesn't make
much difference.
2019-08-01 14:09:57 +01:00
SquidDev
2f96283286 Make disk drives thread-safe 2019-08-01 13:48:03 +01:00
SquidDev
cbe6e9b5f5 Make printers thread-safe 2019-08-01 13:48:03 +01:00
SquidDev
2ab79cf474 Version bumps 'n stuff 2019-07-30 15:48:05 +01:00
SquidDev
6ce34aba79 A quick attempt at fixing Travis
Oracle JDK 8 is EOL (I think at least).
2019-07-30 15:25:14 +01:00
SquidDev
5eeb320b60 Include all mods within a resource mount
This is the behaviour on 1.14 already, so it makes sense to backport to
1.12.

Any mod may now insert files into assets/computercraft/lua/rom, and
they'll be automatically added to the default ROM mount. This allows
other mods to easily register new programs or autorun files.

See #242
2019-07-30 15:20:08 +01:00
SquidDev
93310850d2 Use the "cc" module namespace instead of "craftos"
This is what we actually discussed in the issue, and I failed to
remember.
2019-07-27 11:34:59 +01:00
powerboat9
a2880b12ca Do not refuel beyond the turtle limit (#274) 2019-07-24 08:15:02 +01:00
SquidDev
cef2657048 Fix turtles being replaced by leaves
And logs. Well, hopefully at least.

Fixes #278
2019-07-21 10:28:22 +01:00
SquidDev
ccd85eb055 Bump Forge version 2019-07-21 09:41:58 +01:00
powerboat9
303b57779a Fix turtles harvesting blocks when they shouldn't (#276)
harvestBlock should only be called when removedByPlayer and canHarvestBlock
return true, otherwise we run the risk of causing dupe bugs.

See #273.
2019-07-17 09:23:14 +01:00
SquidDev
6279816ecc Try using the HTTP one instead 2019-07-15 08:45:22 +01:00
SquidDev
4ae77261fa Petty changes because I'm petty 2019-07-13 08:29:28 +01:00
liquid
4b7d843b78 Removed term.getLine 2019-07-13 01:45:16 -05:00
liquid
1c28df65c3 Fixed style errors 2019-07-12 23:56:49 -05:00
liquid
85b740f484 Added term.getLine and window.getLine 2019-07-12 22:54:37 -05:00
SquidDev
f9929cb27d Fix the signature of loadfile
Lua 5.2+ uses loadfile(filename, mode, env), not loadfile(filename,
env). While this is a minor incompatibility, it'd be nice to be
consistent as much as possible.

We try to handle the incorrect case too, as obviously we don't want to
break existing programs.
2019-07-12 22:04:28 +01:00
SquidDev
bafab1ac07 Expose expect as a module (#267)
This moves expect from the bios into a new craftos.expect module,
removing the internal _G["~expect"] definition. Apparently people were
using this irrespective of the "don't use this" comment, so we need to
find another solution.

While this does introduce some ugliness (having to load the module in
weird ways for programs, duplicating the expect function in memory), it
does allow people to use the function in a supported way, and removes
the global ugliness.
2019-07-09 08:04:49 +01:00
JakobDev
e05c262468 Add more tests (#253)
I'm not entirely sure how useful all of these will be yet - still
trying to work out what/when to test things, but hopefully this'll
be a useful datapoint.
2019-07-08 09:24:05 +01:00
SquidDev
acfb72246c Bump JEI version 2019-07-07 15:52:52 +01:00
SquidDev
9d51c4c340 Use world-specific collider entity
This is equally an ugly hack, but means we're at least not constructing
entities with null worlds any more.

Ideally we could always use the turtle entity, but this will require a
bit more of a refactor.

Fixes #265
2019-07-05 22:09:42 +01:00
SquidDev
18068effec Use reflection to get the record's sound
getSound is client side only - I could have sworn it became shared at
some point, but that may have been reverted again (or I imagined it).

Fixes #263
2019-07-05 21:51:54 +01:00
SquidDev
7a3f7d3bba I'm a muppet
Even worse, I enabled branch protection for some reason, and so can't
force push and pretend this never happened.
2019-06-29 15:49:14 +01:00
SquidDev
95aa48c456 Allow running expectations against stubbed functions
Co-authored-by: hydraz <urn@semi.works>
2019-06-29 15:37:41 +01:00
SquidDev
6ea8ca991b Bump Forge to 1.14.3
Guess it's time for another release?
2019-06-26 08:25:32 +01:00
SquidDev
f1e551b960 Bump Forge version
Turtle models now work (though texture registration is still broken).
2019-06-23 15:30:29 +01:00
SquidDev
772c54ec74 Copy the item stack before merging
Otherwise we would mutate the stack, and so the current mount was
considered empty. Closes #240 (though would be nice to improve this).
2019-06-21 22:00:21 +01:00
SquidDev
13cb789c18 Fix "can deploy" check being entirely incorrect
Closes #258
2019-06-21 21:51:22 +01:00
SquidDev
42220c4268 Fix several other client-only methods 2019-06-21 21:32:15 +01:00
SquidDev
3052506e2e Reload configs from the file 2019-06-21 21:32:02 +01:00
SquidDev
0741daa7eb Fix usage of a client-only method
Should probably run forge-lint on this at some point, but it's a good
start.

Fixes #255
2019-06-21 21:02:09 +01:00
SquidDev
b4aa554279 Do not fetch the current block within onLoad
The chunk has not been fully loaded when onLoad is called, which means
we try to load it again, and so the server deadlocks.
2019-06-21 20:57:38 +01:00
SquidDev
8fe2abe0ae Forward tab key directly to the terminal
Fixes #256
2019-06-21 20:31:28 +01:00
SquidDev
5af789ae11 Bump Forge version 2019-06-21 20:31:17 +01:00
SquidDev
904a168d5c Fix incorrect explosion check
We should block explosions if the turtle is advanced /or/ if it's from
a fireball or entity, not if both.

Fixes #257
2019-06-21 18:53:28 +01:00
JakobDev
724441eddc Change URLs in build.gradle to https (#259) 2019-06-21 16:51:55 +01:00
SquidDev
f68ab3edd1 Minor tweaks to build script
Mostly just rearranging. Bump JUnit version in an attempt to fix test
outputs, but it appears this is a mix of gradle/gradle#5975 and
gradle/gradle#4438.
2019-06-15 11:05:45 +01:00
SquidDev
68542aca3a Fix cable breaking rendering
Texture locations have changed a little
2019-06-15 09:19:41 +01:00
SquidDev
594bc4203c Fix block drops for computers and turtles 2019-06-15 09:07:31 +01:00
SquidDev
57318b022d Merge branch 'master' into mc-1.14.x 2019-06-15 08:00:20 +01:00
SquidDev
761159aa93 Bump Forge version 2019-06-15 07:40:27 +01:00
SquidDev
29dce26bf6 Clean up checkstyle warning
Fixes #251, closes #252
2019-06-14 20:55:32 +01:00
JakobDev
717ab69093 Add a few Checks (#248)
- Add some basic tests for several built-in programs.
 - Preserve the state of the shell between tests
2019-06-14 08:15:12 +01:00
SquidDev
138a2cf08f Merge branches 'copycheck' and 'renamefix' 2019-06-13 08:03:35 +01:00
JakobDev
81daf82647 Add Checks to copy.lua 2019-06-13 08:03:01 +01:00
JakobDev
f3798bfb63 Improve rename.lua's argument validation 2019-06-13 08:00:06 +01:00
SquidDev
bc07dfad2e Make sure all writeDescription methods are pure
We don't want to be firing block updates or anything from here! That
runs the ricks of causing CMEs and the like.

Fixes #245
2019-06-12 21:03:11 +01:00
SquidDev
8dd1c2a6cc Finish off containers, somewhat fix block drops
- Add Forge's "name" field to the loot tables. This doesn't resolve all
   our missing loot providers, but it's a start.
 - Add back GUIs for pocket computers, printouts, view computer, etc...
2019-06-12 08:40:20 +01:00
SquidDev
d10b657a54 Initial work on GUIs
Needs a bit of a cleanup, but it's a start!
2019-06-11 21:03:40 +01:00
SquidDev
f90da739eb And bump Forge again 2019-06-09 10:15:53 +01:00
SquidDev
d9cadf64e8 Get the build working I guess? 2019-06-09 09:07:31 +01:00
SquidDev
15d4a55cd8 Bump mappings and Forge versions
Things are shaping up nicely!
2019-06-09 08:58:49 +01:00
JakobDev
309cbdb8be Add wget run (#218)
Equivalent to `pastebin run`, but allows running arbitrary URLs
instead.

Is this a little questionable? Yes - people shouldn't be downloading
and running code from the internet. But hey, people do that already,
so we might as well make it convenient.
2019-06-08 14:49:42 +01:00
SquidDev
39a9ad0ce7 Initial update to 1.14
So very little works, but it compiles and runs.

Things to resolve over the next few days:
 - Horrible mappings (should largely be resolved by tomorrow).
 - Cannot send extra data over containers - we'll have to see what Forge
   does here.
 - Turtle models are broken
 - No block drops yet - this will largely be cherry-picking whatever I
   did on Fabric.
 - Weird inventory desyncs (items don't show up initially when
   interacting with a CC inventory).
 - Probably lots of other things.
2019-06-08 13:36:31 +01:00
SquidDev
0f3c44c926 Merge branch 'master' into mc-1.13.x 2019-06-08 08:21:08 +01:00
SquidDev
a0e7c4a74c Add a little bit of source code checking to Gradle
- Adds a CheckStyle configuration which is pretty similar to CC's
   existing one.
 - Add the Gradle license plugin.
 - Ensure the existing source code is compatible with these additional
   checks.

See #239
2019-06-08 00:28:03 +01:00
Lignum
7d428030df Fix some warnings (#235)
Remove some unused code and fix a bunch of warnings
2019-06-07 14:35:17 +01:00
JakobDev
00c395f689 Add Check to delete.lua (#236) 2019-06-06 16:43:48 +01:00
SquidDev
d8e1c73d26 Ensure files cannot be closed multiple times
Also fix an NPE if we try to close them twice.

Fixes #230
2019-06-04 21:34:19 +01:00
SquidDev
ffa4cc241b Add a test utility for capturing program output
- Make mcfly's stubbing system a little more fault-tolerant.
 - Add a small utility function which redirects print, printError and
   write to capture their output, rather than printing to the terminal.
   This can then be matched against in order to determine a program's
   output.
   It's a little flakey - you can't use it multiple times in an it
   block, etc... but it's a nice feature.
 - Add a small couple of tests to delete as a proof-of-concept.
2019-06-03 20:33:09 +01:00
SquidDev
6f1b740c8f Un-localise paths in mount error messages
This is probably a little more complex than it needs to be, as we try to
handle the mounts as well (which generally don't error).

Fixes #229
2019-06-03 19:58:16 +01:00
SquidDev
3406ba3ebf Fix a build from a clean state failing 2019-06-02 18:48:36 +01:00
525 changed files with 11521 additions and 8504 deletions

View File

@@ -11,5 +11,8 @@ insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.sexp]
indent_size = 2
[*.properties]
insert_final_newline = false

33
.github/workflows/main-ci.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Build
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Gradle
run: ./gradlew build --no-daemon
lint-lua:
name: Lint Lua
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Lint Lua code
run: |
test -d bin || mkdir bin
test -f bin/illuaminate || wget -q -Obin/illuaminate https://squiddev.cc/illuaminate/bin/illuaminate
chmod +x bin/illuaminate
bin/illuaminate lint

6
.gitignore vendored
View File

@@ -15,3 +15,9 @@
.idea
.gradle
*.DS_Store
.classpath
.project
.settings/
bin/
*.launch

View File

@@ -1,34 +0,0 @@
std = "max"
ignore = {
-- Allow access to undefined globals or their fields. In the future we'll
-- define all of CC's globals within this file
'113', '143',
-- FIXME: Ignore unused arguments and loop variables
'212', '213',
-- Disable line is too long for now. It would be possible to clean
-- this up in the future.
'631',
}
-- Only run the linter on ROM and bios for now, as the treasure disks
-- are largely unsupported.
include_files = {
'src/main/resources/assets/computercraft/lua/rom',
'src/main/resources/assets/computercraft/lua/bios.lua'
}
files['src/main/resources/assets/computercraft/lua/bios.lua'] = {
-- Allow declaring and mutating globals
allow_defined_top = true,
ignore = { '112', '121', '122', '131', '142' },
}
files['src/main/resources/assets/computercraft/lua/rom/apis'] = {
-- APIs may define globals on the top level. We'll ignore unused globals,
-- as obviously they may be used outside that API.
allow_defined_top = true,
ignore = { '131' },
}

View File

@@ -1,14 +0,0 @@
language: java
script: ./gradlew build --no-daemon
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/s
jdk:
- oraclejdk8

View File

@@ -1,5 +1,5 @@
# ![CC: Tweaked](logo.png)
[![Current build status](https://travis-ci.org/SquidDev-CC/CC-Tweaked.svg?branch=master)](https://travis-ci.org/SquidDev-CC/CC-Tweaked "Current build status") [![Download CC: Tweaked on CurseForge](https://cf.way2muchnoise.eu/title/cc-tweaked.svg)](https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked on CurseForge")
[![Current build status](https://github.com/SquidDev-CC/CC-Tweaked/workflows/Build/badge.svg)](https://github.com/SquidDev-CC/CC-Tweaked/actions "Current build status") [![Download CC: Tweaked on CurseForge](http://cf.way2muchnoise.eu/title/cc-tweaked.svg)](https://minecraft.curseforge.com/projects/cc-tweaked "Download CC: Tweaked on CurseForge")
CC: Tweaked is a fork of [ComputerCraft](https://github.com/dan200/ComputerCraft), adding programmable computers,
turtles and more to Minecraft.
@@ -41,7 +41,7 @@ Any contribution is welcome, be that using the mod, reporting bugs or contributi
develop CC:T, you'll need to follow these steps:
- **Clone the repository:** `git clone https://github.com/SquidDev-CC/CC-Tweaked.git && cd CC-Tweaked`
- **Setup Forge:** `./gradlew setupDecompWorkspace`
- **Setup Forge:** `./gradlew build`
- **Test your changes:** `./gradlew runClient` (or run the `GradleStart` class from your IDE).
If you want to run CC:T in a normal Minecraft instance, run `./gradlew build` and copy the `.jar` from `build/libs`.

View File

@@ -1,17 +1,28 @@
buildscript {
repositories {
jcenter()
mavenCentral()
maven {
name = "forge"
url = "https://files.minecraftforge.net/maven"
}
}
dependencies {
classpath 'com.google.code.gson:gson:2.8.1'
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.154'
classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
}
}
plugins {
id 'fabric-loom' version '0.2.3-SNAPSHOT'
id 'com.matthewprenger.cursegradle' version '1.2.0'
id "checkstyle"
id "com.github.hierynomus.license" version "0.15.0"
id "com.matthewprenger.cursegradle" version "1.3.0"
id "com.github.breadmoirai.github-release" version "2.2.4"
}
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'org.ajoberstar.grgit'
apply plugin: 'maven-publish'
apply plugin: 'maven'
@@ -22,13 +33,41 @@ group = "org.squiddev"
archivesBaseName = "cc-tweaked-${mc_version}"
minecraft {
runs {
client {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
mods {
computercraft {
source sourceSets.main
}
}
}
server {
workingDirectory project.file('run')
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
property 'forge.logging.console.level', 'debug'
mods {
computercraft {
source sourceSets.main
}
}
}
}
mappings channel: 'snapshot', version: "${mappings_version}".toString()
accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
}
repositories {
mavenCentral()
maven {
name "JEI"
url "http://dvs1.progwml6.com/files/maven"
url "https://dvs1.progwml6.com/files/maven"
}
maven {
name "SquidDev"
@@ -40,7 +79,11 @@ repositories {
}
maven {
name "Amadornes"
url "http://maven.amadornes.com/"
url "https://maven.amadornes.com/"
}
maven {
name "CraftTweaker"
url "https://maven.blamejared.com/"
}
}
@@ -51,29 +94,24 @@ configurations {
}
dependencies {
minecraft "com.mojang:minecraft:${mc_version}"
mappings "net.fabricmc:yarn:${mc_version}+build.${mappings_version}"
modCompile "net.fabricmc:fabric-loader:0.4.8+build.153"
modCompile "net.fabricmc.fabric-api:fabric-api:0.3.0+build.175"
checkstyle "com.puppycrawl.tools:checkstyle:8.25"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.25:api")
compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.14.4:5.0.1.150")
runtimeOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.25")
shade 'org.squiddev:Cobalt:0.5.0-SNAPSHOT'
shade 'javax.vecmath:vecmath:1.5.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.1.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.1.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.2'
deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
}
sourceSets {
main {
java {
exclude 'dan200/computercraft/shared/integration'
}
}
}
// Compile tasks
javadoc {
include "dan200/computercraft/api/**/*.java"
@@ -85,7 +123,7 @@ jar {
manifest {
attributes(["Specification-Title": "computercraft",
"Specification-Vendor": "SquidDev",
"Specification-Version": "25.0",
"Specification-Version": "1",
"Implementation-Title": "CC: Tweaked",
"Implementation-Version": "${mod_version}",
"Implementation-Vendor" :"SquidDev",
@@ -99,12 +137,22 @@ jar {
from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
}
[compileJava, compileTestJava].forEach {
it.configure {
options.compilerArgs << "-Xlint" << "-Xlint:-processing"
}
}
import java.nio.charset.StandardCharsets
import java.nio.file.*
import java.util.zip.*
import com.google.gson.GsonBuilder
import com.google.gson.JsonElement
import com.hierynomus.gradle.license.tasks.LicenseCheck
import com.hierynomus.gradle.license.tasks.LicenseFormat
import org.ajoberstar.grgit.Grgit
import proguard.gradle.ProGuardTask
@@ -112,14 +160,12 @@ task proguard(type: ProGuardTask, dependsOn: jar) {
description "Removes unused shadowed classes from the jar"
group "compact"
afterEvaluate {
// Fabric changes the jar's classifier so we to do this after evaluating!
injars jar.archivePath
outjars "${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar"
}
injars jar.archivePath
outjars "${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar"
// Add the main runtime jar and all non-shadowed dependencies
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
libraryjars "${System.getProperty('java.home')}/lib/jce.jar"
doFirst {
sourceSets.main.compileClasspath
.filter { !it.name.contains("Cobalt") }
@@ -135,12 +181,9 @@ task proguard(type: ProGuardTask, dependsOn: jar) {
// Preserve ComputerCraft classes - we only want to strip shadowed files.
keep 'class dan200.computercraft.** { *; }'
// Preserve the constructors in Cobalt library class, as we init them via reflection
keepclassmembers 'class org.squiddev.cobalt.lib.** { <init>(...); }'
// LWJGL and Apache bundle Java 9 versions, which is great, but rather breaks Proguard
dontwarn 'module-info'
dontwarn 'org.apache.**,org.lwjgl.**,javax.crypto.SecretKey'
dontwarn 'org.apache.**,org.lwjgl.**'
}
task proguardMove(dependsOn: proguard) {
@@ -156,7 +199,7 @@ task proguardMove(dependsOn: proguard) {
}
}
remapJar.dependsOn proguardMove
processResources {
inputs.property "version", mod_version
@@ -178,7 +221,7 @@ processResources {
inputs.property "commithash", hash
from(sourceSets.main.resources.srcDirs) {
include 'fabric.mod.json'
include 'META-INF/mods.toml'
include 'data/computercraft/lua/rom/help/credits.txt'
expand 'version': mod_version,
@@ -187,12 +230,12 @@ processResources {
}
from(sourceSets.main.resources.srcDirs) {
exclude 'fabric.mod.json'
exclude 'META-INF/mods.toml'
exclude 'data/computercraft/lua/rom/help/credits.txt'
}
}
task compressJson(dependsOn: remapJar) {
task compressJson(dependsOn: jar) {
group "compact"
description "Minifies all JSON files, stripping whitespace"
@@ -207,6 +250,7 @@ task compressJson(dependsOn: remapJar) {
// Copy over all files in the current jar to the new one, running json files from GSON. As pretty printing
// is turned off, they should be minified.
new ZipFile(jarPath).withCloseable { inJar ->
tempPath.getParentFile().mkdirs()
new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(tempPath))).withCloseable { outJar ->
inJar.entries().each { entry ->
if(entry.directory) {
@@ -234,6 +278,56 @@ task compressJson(dependsOn: remapJar) {
assemble.dependsOn compressJson
// Check tasks
test {
useJUnitPlatform()
testLogging {
events "skipped", "failed"
}
}
license {
mapping("java", "SLASHSTAR_STYLE")
strictCheck true
ext.year = Calendar.getInstance().get(Calendar.YEAR)
}
[licenseMain, licenseFormatMain].forEach {
it.configure {
include("**/*.java")
exclude("dan200/computercraft/api/**")
header rootProject.file('config/license/main.txt')
}
}
[licenseTest, licenseFormatTest].forEach {
it.configure {
include("**/*.java")
header rootProject.file('config/license/main.txt')
}
}
gradle.projectsEvaluated {
tasks.withType(LicenseFormat) {
outputs.upToDateWhen { false }
}
}
task licenseAPI(type: LicenseCheck);
task licenseFormatAPI(type: LicenseFormat);
[licenseAPI, licenseFormatAPI].forEach {
it.configure {
source = sourceSets.main.java
include("dan200/computercraft/api/**")
header rootProject.file('config/license/api.txt')
}
}
// Upload tasks
task checkRelease {
group "upload"
description "Verifies that everything is ready for a release"
@@ -272,28 +366,18 @@ task checkRelease {
if (!ok) throw new IllegalStateException("Could not check release")
}
}
check.dependsOn checkRelease
curseforge {
apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : ''
project {
id = '282001'
addGameVersion '1.14.2'
releaseType = 'beta'
releaseType = 'release'
changelog = "Release notes can be found on the GitHub repository (https://github.com/SquidDev-CC/CC-Tweaked/releases/tag/v${mc_version}-${mod_version})."
relations {
incompatible "computercraft"
requiredDependency "fabric"
}
afterEvaluate {
mainArtifact(remapJar.output)
uploadTask.dependsOn(remapJar)
}
}
options {
forgeGradleIntegration = false
}
}
@@ -354,7 +438,9 @@ githubRelease {
token project.hasProperty('githubApiKey') ? project.githubApiKey : ''
owner 'SquidDev-CC'
repo 'CC-Tweaked'
targetCommitish { Grgit.open(dir: '.').branch.current().name }
try {
targetCommitish = Grgit.open(dir: '.').branch.current().name
} catch(Exception ignored) { }
tagName "v${mc_version}-${mod_version}"
releaseName "[${mc_version}] ${mod_version}"
@@ -370,21 +456,7 @@ githubRelease {
def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"]
uploadTasks.forEach { tasks.getByName(it).dependsOn checkRelease }
task uploadAll(dependsOn: [remapJar] + uploadTasks) {
task uploadAll(dependsOn: uploadTasks) {
group "upload"
description "Uploads to all repositories (Maven, Curse, GitHub release)"
}
test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint" << "-Xlint:-processing" // Causes Forge build to fail << "-Werror"
}
}

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="tabWidth" value="4"/>
<property name="charset" value="UTF-8" />
<module name="SuppressionFilter">
<property name="file" value="config/checkstyle/suppressions.xml" />
</module>
<module name="TreeWalker">
<!-- Annotations -->
<module name="AnnotationLocation" />
<module name="AnnotationUseStyle" />
<module name="MissingDeprecated" />
<module name="MissingOverride" />
<!-- Blocks -->
<module name="EmptyBlock" />
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="ignored" />
</module>
<module name="LeftCurly">
<property name="option" value="nl" />
<!-- The defaults, minus lambdas. -->
<property name="tokens" value="ANNOTATION_DEF,CLASS_DEF,CTOR_DEF,ENUM_CONSTANT_DEF,ENUM_DEF,INTERFACE_DEF,LITERAL_CASE,LITERAL_CATCH,LITERAL_DEFAULT,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,METHOD_DEF,OBJBLOCK,STATIC_INIT" />
</module>
<module name="NeedBraces">
<property name="allowSingleLineStatement" value="true"/>
</module>
<module name="RightCurly">
<property name="option" value="alone" />
</module>
<!-- Class design. As if we've ever followed good practice here. -->
<module name="FinalClass" />
<module name="InterfaceIsType" />
<module name="MutableException" />
<module name="OneTopLevelClass" />
<!-- Coding -->
<module name="ArrayTrailingComma" />
<module name="EqualsHashCode" />
<!-- FallThrough does not handle unreachable code well -->
<module name="IllegalInstantiation" />
<module name="IllegalThrows" />
<module name="ModifiedControlVariable" />
<module name="NoClone" />
<module name="NoFinalizer" />
<module name="OneStatementPerLine" />
<module name="PackageDeclaration" />
<module name="SimplifyBooleanExpression" />
<module name="SimplifyBooleanReturn" />
<module name="StringLiteralEquality" />
<module name="UnnecessaryParentheses" />
<module name="UnnecessarySemicolonAfterTypeMemberDeclaration" />
<module name="UnnecessarySemicolonInTryWithResources" />
<module name="UnnecessarySemicolonInEnumeration" />
<!-- Imports -->
<module name="CustomImportOrder" />
<module name="IllegalImport" />
<module name="RedundantImport" />
<module name="UnusedImports" />
<!-- Javadoc -->
<!-- TODO: Missing* checks for the dan200.computercraft.api package? -->
<module name="AtclauseOrder" />
<module name="InvalidJavadocPosition" />
<module name="JavadocBlockTagLocation" />
<module name="JavadocMethod"/>
<module name="JavadocType"/>
<module name="JavadocStyle" />
<module name="NonEmptyAtclauseDescription" />
<module name="SingleLineJavadoc" />
<module name="SummaryJavadocCheck"/>
<!-- Misc -->
<module name="ArrayTypeStyle" />
<module name="CommentsIndentation" />
<module name="Indentation" />
<module name="OuterTypeFilename" />
<!-- Modifiers -->
<module name="ModifierOrder" />
<module name="RedundantModifier" />
<!-- Naming -->
<module name="ClassTypeParameterName" />
<module name="InterfaceTypeParameterName" />
<module name="LambdaParameterName" />
<module name="LocalFinalVariableName" />
<module name="LocalVariableName" />
<!-- Allow an optional m_ on private members -->
<module name="MemberName">
<property name="applyToPrivate" value="false" />
<property name="applyToPackage" value="false" />
</module>
<module name="MemberName">
<property name="format" value="^(m_)?[a-z][a-zA-Z0-9]*$" />
<property name="applyToPrivate" value="true" />
<property name="applyToPackage" value="true" />
</module>
<module name="MethodName" />
<module name="MethodTypeParameterName" />
<module name="PackageName">
<property name="format" value="^dan200\.computercraf(\.[a-z][a-z0-9]*)*" />
</module>
<module name="ParameterName" />
<module name="StaticVariableName">
<property name="format" value="^[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z]+)?$" />
<property name="applyToPrivate" value="false" />
</module>
<module name="StaticVariableName">
<property name="format" value="^(s_)?[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z]+)?$" />
<property name="applyToPrivate" value="true" />
</module>
<module name="TypeName" />
<!-- Whitespace -->
<module name="EmptyForInitializerPad"/>
<module name="EmptyForIteratorPad">
<property name="option" value="space"/>
</module>
<module name="GenericWhitespace" />
<module name="MethodParamPad" />
<module name="NoLineWrap" />
<module name="NoWhitespaceAfter">
<property name="tokens" value="AT,INC,DEC,UNARY_MINUS,UNARY_PLUS,BNOT,LNOT,DOT,ARRAY_DECLARATOR,INDEX_OP" />
</module>
<module name="NoWhitespaceBefore" />
<!-- TODO: Decide on an OperatorWrap style. -->
<module name="ParenPad">
<property name="option" value="space" />
<property name="tokens" value="ANNOTATION,ANNOTATION_FIELD_DEF,CTOR_CALL,CTOR_DEF,ENUM_CONSTANT_DEF,LITERAL_CATCH,LITERAL_DO,LITERAL_FOR,LITERAL_IF,LITERAL_NEW,LITERAL_SWITCH,LITERAL_SYNCHRONIZED,LITERAL_WHILE,METHOD_CALL,METHOD_DEF,RESOURCE_SPECIFICATION,SUPER_CTOR_CALL,LAMBDA" />
</module>
<module name="ParenPad">
<property name="option" value="nospace" />
<property name="tokens" value="DOT,EXPR,QUESTION" />
</module>
<module name="SeparatorWrap">
<property name="option" value="eol" />
<property name="tokens" value="COMMA,SEMI,ELLIPSIS,ARRAY_DECLARATOR,RBRACK,METHOD_REF" />
</module>
<module name="SeparatorWrap">
<property name="option" value="nl" />
<property name="tokens" value="DOT,AT" />
</module>
<module name="SingleSpaceSeparator" />
<module name="TypecastParenPad" />
<module name="WhitespaceAfter">
<property name="tokens" value="COMMA" />
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true" />
<property name="ignoreEnhancedForColon" value="false" />
<property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAMBDA,LAND,LCURLY,LE,LITERAL_RETURN,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,RCURLY,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND" />
</module>
</module>
<module name="FileTabCharacter" />
<module name="NewlineAtEndOfFile" />
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="message" value="Trailing whitespace"/>
</module>
</module>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<!-- All the config options and method fields. -->
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraft.java" />
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraftAPI.java" />
<!-- Do not check for missing package Javadoc. -->
<suppress checks="JavadocStyle" files=".*[\\/]package-info.java" />
</suppressions>

3
config/license/api.txt Normal file
View File

@@ -0,0 +1,3 @@
This file is part of the public ComputerCraft API - http://www.computercraft.info
Copyright Daniel Ratcliffe, 2011-${year}. This API may be redistributed unmodified and in full only.
For help using the API, and posting your mods, visit the forums at computercraft.info.

3
config/license/main.txt Normal file
View File

@@ -0,0 +1,3 @@
This file is part of ComputerCraft - http://www.computercraft.info
Copyright Daniel Ratcliffe, 2011-${year}. Do not distribute without permission.
Send enquiries to dratcliffe@gmail.com

View File

@@ -1,6 +1,7 @@
# Mod properties
mod_version=1.83.1
mod_version=1.86.0
# Minecraft properties
mc_version=1.14.2
mappings_version=2
# Minecraft properties (update mods.toml when changing)
mc_version=1.14.4
forge_version=28.1.71
mappings_version=20191123-1.14.3

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

28
illuaminate.sexp Normal file
View File

@@ -0,0 +1,28 @@
; -*- mode: Lisp;-*-
(sources
/src/main/resources/assets/computercraft/lua/bios.lua
/src/main/resources/assets/computercraft/lua/rom/
/src/test/resources/test-rom)
(at /
(linters
;; It'd be nice to avoid this, but right now there's a lot of instances of
;; it.
-var:set-loop
;; It's useful to name arguments for documentation, so we allow this. It'd
;; be good to find a compromise in the future, but this works for now.
-var:unused-arg))
;; We disable the unused global linter in bios.lua and the APIs. In the future
;; hopefully we'll get illuaminate to handle this.
(at
(/src/main/resources/assets/computercraft/lua/bios.lua
/src/main/resources/assets/computercraft/lua/rom/apis/)
(linters -var:unused-global)
(lint
(allow-toplevel-global true)))
;; These warnings are broken right now
(at (bios.lua worm.lua) (linters -control:unreachable))

View File

@@ -1,12 +1 @@
pluginManagement {
repositories {
jcenter()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
gradlePluginPortal()
}
}
rootProject.name = "cc-tweaked-${mc_version}-fabric"
rootProject.name = "cc-tweaked-${mc_version}"

View File

@@ -6,12 +6,10 @@
package dan200.computercraft;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.client.proxy.ComputerCraftProxyClient;
import dan200.computercraft.core.apis.AddressPredicate;
import dan200.computercraft.core.apis.http.websocket.Websocket;
import dan200.computercraft.core.filesystem.ResourceMount;
import dan200.computercraft.shared.Config;
import dan200.computercraft.shared.computer.blocks.BlockComputer;
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
@@ -30,15 +28,13 @@ import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
import dan200.computercraft.shared.turtle.blocks.BlockTurtle;
import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.turtle.upgrades.*;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.resource.ReloadableResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -47,7 +43,8 @@ import java.io.InputStream;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
public final class ComputerCraft implements ModInitializer
@Mod( ComputerCraft.MOD_ID )
public final class ComputerCraft
{
public static final String MOD_ID = "computercraft";
@@ -185,22 +182,9 @@ public final class ComputerCraft implements ModInitializer
// Logging
public static final Logger log = LogManager.getLogger( MOD_ID );
// Implementation
public static ComputerCraft instance;
public ComputerCraft()
{
instance = this;
}
@Override
public void onInitialize()
{
ComputerCraftProxyCommon.setup();
if( FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT )
{
ComputerCraftProxyClient.setup();
}
Config.load();
}
public static String getVersion()
@@ -208,19 +192,12 @@ public final class ComputerCraft implements ModInitializer
return "${version}";
}
static IMount createResourceMount( String domain, String subPath )
{
ReloadableResourceManager manager = ComputerCraftProxyCommon.getServer().getDataManager();
ResourceMount mount = new ResourceMount( domain, subPath, manager );
return mount.exists( "" ) ? mount : null;
}
public static InputStream getResourceFile( String domain, String subPath )
{
ReloadableResourceManager manager = ComputerCraftProxyCommon.getServer().getDataManager();
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
try
{
return manager.getResource( new Identifier( domain, subPath ) ).getInputStream();
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
}
catch( IOException ignored )
{

View File

@@ -6,6 +6,7 @@
package dan200.computercraft;
import com.google.common.collect.MapMaker;
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
@@ -20,21 +21,26 @@ import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.core.apis.ApiFactories;
import dan200.computercraft.core.filesystem.FileMount;
import dan200.computercraft.core.filesystem.ResourceMount;
import dan200.computercraft.shared.*;
import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
import dan200.computercraft.shared.peripheral.modem.wired.TileWiredModemFull;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
import dan200.computercraft.shared.util.IDAssigner;
import dan200.computercraft.shared.wired.CapabilityWiredElement;
import dan200.computercraft.shared.wired.WiredNode;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.resources.IReloadableResourceManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.Map;
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
{
@@ -44,6 +50,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
{
}
private WeakReference<IReloadableResourceManager> currentResources;
private final Map<ResourceLocation, ResourceMount> mountCache = new MapMaker().weakValues().concurrencyLevel( 1 ).makeMap();
@Nonnull
@Override
public String getInstalledVersion()
@@ -54,7 +63,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
@Override
public int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath )
{
return IDAssigner.getNextId( world, parentSubPath );
return IDAssigner.getNextId( parentSubPath );
}
@Override
@@ -62,7 +71,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
{
try
{
return new FileMount( new File( IDAssigner.getDir( world ), subPath ), capacity );
return new FileMount( new File( IDAssigner.getDir(), subPath ), capacity );
}
catch( Exception e )
{
@@ -73,7 +82,9 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
@Override
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
{
return ComputerCraft.createResourceMount( domain, subPath );
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
return mount.exists( "" ) ? mount : null;
}
@Override
@@ -132,19 +143,11 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
return new WiredNode( element );
}
@Nullable
@Nonnull
@Override
public IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side )
public LazyOptional<IWiredElement> getWiredElementAt( @Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
BlockEntity tile = world.getBlockEntity( pos );
if( tile instanceof TileCable )
{
return ((TileCable) tile).getElement( side );
}
else if( tile instanceof TileWiredModemFull )
{
return ((TileWiredModemFull) tile).getElement();
}
return null;
TileEntity tile = world.getTileEntity( pos );
return tile == null ? LazyOptional.empty() : tile.getCapability( CapabilityWiredElement.CAPABILITY, side );
}
}

View File

@@ -1,17 +1,16 @@
/*
* 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
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleUpgradeType;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.SystemUtil;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Util;
import javax.annotation.Nonnull;
@@ -22,12 +21,12 @@ import javax.annotation.Nonnull;
*/
public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
{
private final Identifier id;
private final ResourceLocation id;
private final TurtleUpgradeType type;
private final String adjective;
private final ItemStack stack;
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack )
{
this.id = id;
this.type = type;
@@ -35,24 +34,24 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
this.stack = stack;
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, String adjective, IItemProvider item )
{
this( id, type, adjective, new ItemStack( item ) );
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, ItemStack stack )
{
this( id, type, SystemUtil.createTranslationKey( "upgrade", id ) + ".adjective", stack );
this( id, type, Util.makeTranslationKey( "upgrade", id ) + ".adjective", stack );
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
protected AbstractTurtleUpgrade( ResourceLocation id, TurtleUpgradeType type, IItemProvider item )
{
this( id, type, new ItemStack( item ) );
}
@Nonnull
@Override
public final Identifier getUpgradeID()
public final ResourceLocation getUpgradeID()
{
return id;
}

View File

@@ -20,18 +20,20 @@ import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The static entry point to the ComputerCraft API.
* Members in this class must be called after mod_ComputerCraft has been initialised,
* but may be called before it is fully loaded.
*
* Members in this class must be called after mod_ComputerCraft has been initialised, but may be called before it is
* fully loaded.
*/
public final class ComputerCraftAPI
{
@@ -188,7 +190,7 @@ public final class ComputerCraftAPI
}
/**
* Registers a media provider to provide {@link IMedia} implementations for Items
* Registers a media provider to provide {@link IMedia} implementations for Items.
*
* @param provider The media provider to register.
* @see IMediaProvider
@@ -219,7 +221,7 @@ public final class ComputerCraftAPI
}
/**
* Construct a new wired node for a given wired element
* Construct a new wired node for a given wired element.
*
* @param element The element to construct it for
* @return The element's node
@@ -232,7 +234,7 @@ public final class ComputerCraftAPI
}
/**
* Get the wired network element for a block in world
* Get the wired network element for a block in world.
*
* @param world The world the block exists in
* @param pos The position the block exists in
@@ -240,8 +242,8 @@ public final class ComputerCraftAPI
* @return The element's node
* @see IWiredElement#getNode()
*/
@Nullable
public static IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side )
@Nonnull
public static LazyOptional<IWiredElement> getWiredElementAt( @Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
return getInstance().getWiredElementAt( world, pos, side );
}
@@ -297,7 +299,7 @@ public final class ComputerCraftAPI
@Nonnull
IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element );
@Nullable
IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side );
@Nonnull
LazyOptional<IWiredElement> getWiredElementAt( @Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nonnull Direction side );
}
}

View File

@@ -0,0 +1,41 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.filesystem;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.Objects;
/**
* An {@link IOException} which occurred on a specific file.
*
* This may be thrown from a {@link IMount} or {@link IWritableMount} to give more information about a failure.
*/
public class FileOperationException extends IOException
{
private static final long serialVersionUID = -8809108200853029849L;
private final String filename;
public FileOperationException( @Nullable String filename, @Nonnull String message )
{
super( Objects.requireNonNull( message, "message cannot be null" ) );
this.filename = filename;
}
public FileOperationException( String message )
{
super( Objects.requireNonNull( message, "message cannot be null" ) );
this.filename = null;
}
@Nullable
public String getFilename()
{
return filename;
}
}

View File

@@ -19,7 +19,7 @@ import java.util.List;
/**
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using
* {@link IComputerAccess#mount(String, IMount)}
* {@link IComputerAccess#mount(String, IMount)}.
*
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(World, String, long)} or
@@ -60,7 +60,7 @@ public interface IMount
void list( @Nonnull String path, @Nonnull List<String> contents ) throws IOException;
/**
* Returns the size of a file with a given path, in bytes
* Returns the size of a file with a given path, in bytes.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return The size of the file, in bytes.
@@ -90,7 +90,6 @@ public interface IMount
* @throws IOException If the file does not exist, or could not be opened.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForRead( path ) );

View File

@@ -67,7 +67,6 @@ public interface IWritableMount extends IMount
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default WritableByteChannel openChannelForWrite( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForWrite( path ) );
@@ -94,7 +93,6 @@ public interface IWritableMount extends IMount
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default WritableByteChannel openChannelForAppend( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForAppend( path ) );

View File

@@ -0,0 +1,335 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.lua;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
/**
* Provides methods for extracting values and validating Lua arguments, such as those provided to
* {@link ILuaObject#callMethod(ILuaContext, int, Object[])} or
* {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}.
*
* This provides two sets of functions: the {@code get*} methods, which require an argument to be valid, and
* {@code opt*}, which accept a default value and return that if the argument was not present or was {@code null}.
* If the argument is of the wrong type, a suitable error message will be thrown, with a similar format to Lua's own
* error messages.
*
* <h2>Example usage:</h2>
* <pre>
* {@code
* int slot = getInt( args, 0 );
* int amount = optInt( args, 1, 64 );
* }
* </pre>
*/
public final class ArgumentHelper
{
private ArgumentHelper()
{
}
/**
* Get a string representation of the given value's type.
*
* @param value The value whose type we are trying to compute.
* @return A string representation of the given value's type, in a similar format to that provided by Lua's
* {@code type} function.
*/
@Nonnull
public static String getType( @Nullable Object value )
{
if( value == null ) return "nil";
if( value instanceof String ) return "string";
if( value instanceof Boolean ) return "boolean";
if( value instanceof Number ) return "number";
if( value instanceof Map ) return "table";
return "userdata";
}
/**
* Construct a "bad argument" exception, from an expected type and the actual value provided.
*
* @param index The argument number, starting from 0.
* @param expected The expected type for this argument.
* @param actual The actual value provided for this argument.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badArgumentOf( int index, @Nonnull String expected, @Nullable Object actual )
{
return badArgument( index, expected, getType( actual ) );
}
/**
* Construct a "bad argument" exception, from an expected and actual type.
*
* @param index The argument number, starting from 0.
* @param expected The expected type for this argument.
* @param actual The provided type for this argument.
* @return The constructed exception, which should be thrown immediately.
*/
@Nonnull
public static LuaException badArgument( int index, @Nonnull String expected, @Nonnull String actual )
{
return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" );
}
/**
* Get an argument as a double.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @return The argument's value.
* @throws LuaException If the value is not a number.
* @see #getFiniteDouble(Object[], int) if you require this to be finite (i.e. not infinite or NaN).
*/
public static double getDouble( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "number", "nil" );
Object value = args[index];
if( !(value instanceof Number) ) throw badArgumentOf( index, "number", value );
return ((Number) value).doubleValue();
}
/**
* Get an argument as an integer.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @return The argument's value.
* @throws LuaException If the value is not an integer.
*/
public static int getInt( @Nonnull Object[] args, int index ) throws LuaException
{
return (int) getLong( args, index );
}
/**
* Get an argument as a long.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @return The argument's value.
* @throws LuaException If the value is not a long.
*/
public static long getLong( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "number", "nil" );
Object value = args[index];
if( !(value instanceof Number) ) throw badArgumentOf( index, "number", value );
return checkFinite( index, (Number) value ).longValue();
}
/**
* Get an argument as a finite number (not infinite or NaN).
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @return The argument's value.
* @throws LuaException If the value is not finite.
*/
public static double getFiniteDouble( @Nonnull Object[] args, int index ) throws LuaException
{
return checkFinite( index, getDouble( args, index ) );
}
/**
* Get an argument as a boolean.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @return The argument's value.
* @throws LuaException If the value is not a boolean.
*/
public static boolean getBoolean( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "boolean", "nil" );
Object value = args[index];
if( !(value instanceof Boolean) ) throw badArgumentOf( index, "boolean", value );
return (Boolean) value;
}
/**
* Get an argument as a string.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @return The argument's value.
* @throws LuaException If the value is not a string.
*/
@Nonnull
public static String getString( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "string", "nil" );
Object value = args[index];
if( !(value instanceof String) ) throw badArgumentOf( index, "string", value );
return (String) value;
}
/**
* Get an argument as a table.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @return The argument's value.
* @throws LuaException If the value is not a table.
*/
@Nonnull
public static Map<?, ?> getTable( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "table", "nil" );
Object value = args[index];
if( !(value instanceof Map) ) throw badArgumentOf( index, "table", value );
return (Map<?, ?>) value;
}
/**
* Get an argument as a double.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
public static double optDouble( @Nonnull Object[] args, int index, double def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null ) return def;
if( !(value instanceof Number) ) throw badArgumentOf( index, "number", value );
return ((Number) value).doubleValue();
}
/**
* Get an argument as an int.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
public static int optInt( @Nonnull Object[] args, int index, int def ) throws LuaException
{
return (int) optLong( args, index, def );
}
/**
* Get an argument as a long.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
public static long optLong( @Nonnull Object[] args, int index, long def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null ) return def;
if( !(value instanceof Number) ) throw badArgumentOf( index, "number", value );
return checkFinite( index, (Number) value ).longValue();
}
/**
* Get an argument as a finite number (not infinite or NaN).
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not finite.
*/
public static double optFiniteDouble( @Nonnull Object[] args, int index, double def ) throws LuaException
{
return checkFinite( index, optDouble( args, index, def ) );
}
/**
* Get an argument as a boolean.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a boolean.
*/
public static boolean optBoolean( @Nonnull Object[] args, int index, boolean def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null ) return def;
if( !(value instanceof Boolean) ) throw badArgumentOf( index, "boolean", value );
return (Boolean) value;
}
/**
* Get an argument as a string.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a string.
*/
public static String optString( @Nonnull Object[] args, int index, String def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null ) return def;
if( !(value instanceof String) ) throw badArgumentOf( index, "string", value );
return (String) value;
}
/**
* Get an argument as a table.
*
* @param args The arguments to extract from.
* @param index The index into the argument array to read from.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a table.
*/
public static Map<?, ?> optTable( @Nonnull Object[] args, int index, Map<Object, Object> def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null ) return def;
if( !(value instanceof Map) ) throw badArgumentOf( index, "table", value );
return (Map<?, ?>) value;
}
private static Number checkFinite( int index, Number value ) throws LuaException
{
checkFinite( index, value.doubleValue() );
return value;
}
private static double checkFinite( int index, double value ) throws LuaException
{
if( !Double.isFinite( value ) ) throw badArgument( index, "number", getNumericType( value ) );
return value;
}
/**
* Returns a more detailed representation of this number's type. If this is finite, it will just return "number",
* otherwise it returns whether it is infinite or NaN.
*
* @param value The value to extract the type for.
* @return This value's numeric type.
*/
@Nonnull
public static String getNumericType( double value )
{
if( Double.isNaN( value ) ) return "nan";
if( value == Double.POSITIVE_INFINITY ) return "inf";
if( value == Double.NEGATIVE_INFINITY ) return "-inf";
return "number";
}
}

View File

@@ -26,7 +26,7 @@ public interface IComputerSystem extends IComputerAccess
IFileSystem getFileSystem();
/**
* Get the label for this computer
* Get the label for this computer.
*
* @return This computer's label, or {@code null} if it is not set.
*/

View File

@@ -9,7 +9,7 @@ package dan200.computercraft.api.media;
import dan200.computercraft.api.filesystem.IMount;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.SoundEvent;
import net.minecraft.world.World;
import javax.annotation.Nonnull;

View File

@@ -6,6 +6,7 @@
package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.lua.ArgumentHelper;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
@@ -58,9 +59,11 @@ public interface IPeripheral
* Lua values of type "table" will be represented by Object type Map.<br>
* Lua values of any other type will be represented by a null object.<br>
* This array will be empty if no arguments are passed.
*
* It is recommended you use {@link ArgumentHelper} in order to validate and process arguments.
* @return An array of objects, representing values you wish to return to the lua program. Integers, Doubles, Floats,
* Strings, Booleans, Maps and ILuaObject and null be converted to their corresponding lua type. All other types
* will be converted to nil.
* Strings, Booleans, Maps, ILuaObject and null be converted to their corresponding lua type. All other types will
* be converted to nil.
*
* You may return null to indicate no values should be returned.
* @throws LuaException If you throw any exception from this function, a lua error will be raised with the
@@ -70,6 +73,7 @@ public interface IPeripheral
* InterruptedException will be thrown. This exception must not be caught or
* intercepted, or the computer will leak memory and end up in a broken state.
* @see #getMethodNames
* @see ArgumentHelper
*/
@Nullable
Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;

View File

@@ -6,9 +6,9 @@
package dan200.computercraft.api.peripheral;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -17,8 +17,7 @@ import javax.annotation.Nullable;
/**
* This interface is used to create peripheral implementations for blocks.
*
* If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively implement
* {@link IPeripheralTile}.
* If you have a {@link TileEntity} which acts as a peripheral, you may alternatively implement {@link IPeripheralTile}.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/

View File

@@ -5,15 +5,15 @@
*/
package dan200.computercraft.api.peripheral;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* A {@link net.minecraft.block.entity.BlockEntity} which may act as a peripheral.
* A {@link net.minecraft.tileentity.TileEntity} which may act as a peripheral.
*
* If you need more complex capabilities (such as handling TEs not belonging to your mod), you should use
* {@link IPeripheralProvider}.

View File

@@ -1,9 +1,8 @@
/*
* 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
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.peripheral;
import javax.annotation.Nonnull;

View File

@@ -1,15 +1,14 @@
/*
* 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
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.pocket;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.SystemUtil;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Util;
import javax.annotation.Nonnull;
@@ -20,30 +19,30 @@ import javax.annotation.Nonnull;
*/
public abstract class AbstractPocketUpgrade implements IPocketUpgrade
{
private final Identifier id;
private final ResourceLocation id;
private final String adjective;
private final ItemStack stack;
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, ItemStack stack )
{
this.id = id;
this.adjective = adjective;
this.stack = stack;
}
protected AbstractPocketUpgrade( Identifier identifier, String adjective, ItemConvertible item )
protected AbstractPocketUpgrade( ResourceLocation id, String adjective, IItemProvider item )
{
this( identifier, adjective, new ItemStack( item ) );
this( id, adjective, new ItemStack( item ) );
}
protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
protected AbstractPocketUpgrade( ResourceLocation id, IItemProvider item )
{
this( id, SystemUtil.createTranslationKey( "upgrade", id ) + ".adjective", new ItemStack( item ) );
this( id, Util.makeTranslationKey( "upgrade", id ) + ".adjective", new ItemStack( item ) );
}
@Nonnull
@Override
public final Identifier getUpgradeID()
public final ResourceLocation getUpgradeID()
{
return id;
}

View File

@@ -8,15 +8,15 @@ package dan200.computercraft.api.pocket;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
/**
* Wrapper class for pocket computers
* Wrapper class for pocket computers.
*/
public interface IPocketAccess
{
@@ -75,7 +75,7 @@ public interface IPocketAccess
* @see #updateUpgradeNBTData()
*/
@Nonnull
CompoundTag getUpgradeNBTData();
CompoundNBT getUpgradeNBTData();
/**
* Mark the upgrade-specific NBT as dirty.
@@ -95,5 +95,5 @@ public interface IPocketAccess
* @return A collection of all upgrade names.
*/
@Nonnull
Map<Identifier, IPeripheral> getUpgrades();
Map<ResourceLocation, IPeripheral> getUpgrades();
}

View File

@@ -10,7 +10,7 @@ import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -36,7 +36,7 @@ public interface IPocketUpgrade
* @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade)
*/
@Nonnull
Identifier getUpgradeID();
ResourceLocation getUpgradeID();
/**
* Return an unlocalised string to describe the type of pocket computer this upgrade provides.

View File

@@ -6,8 +6,8 @@
package dan200.computercraft.api.redstone;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;

View File

@@ -10,12 +10,13 @@ import com.mojang.authlib.GameProfile;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.inventory.Inventory;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.inventory.IInventory;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandlerModifiable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -143,12 +144,28 @@ public interface ITurtleAccess
GameProfile getOwningPlayer();
/**
* Get the inventory of this turtle
* Get the inventory of this turtle.
*
* Note: this inventory should only be accessed and modified on the server thread.
*
* @return This turtle's inventory
* @see #getItemHandler()
*/
@Nonnull
Inventory getInventory();
IInventory getInventory();
/**
* Get the inventory of this turtle as an {@link IItemHandlerModifiable}.
*
* Note: this inventory should only be accessed and modified on the server thread.
*
* @return This turtle's inventory
* @see #getInventory()
* @see IItemHandlerModifiable
* @see net.minecraftforge.items.CapabilityItemHandler#ITEM_HANDLER_CAPABILITY
*/
@Nonnull
IItemHandlerModifiable getItemHandler();
/**
* Determine whether this turtle will require fuel when performing actions.
@@ -277,7 +294,7 @@ public interface ITurtleAccess
* @see #updateUpgradeNBTData(TurtleSide)
*/
@Nonnull
CompoundTag getUpgradeNBTData( @Nullable TurtleSide side );
CompoundNBT getUpgradeNBTData( @Nullable TurtleSide side );
/**
* Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the

View File

@@ -10,13 +10,15 @@ import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ModelResourceLocation;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import net.minecraftforge.event.world.BlockEvent;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
@@ -40,7 +42,7 @@ public interface ITurtleUpgrade
* @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade)
*/
@Nonnull
Identifier getUpgradeID();
ResourceLocation getUpgradeID();
/**
* Return an unlocalised string to describe this type of turtle in turtle item names.
@@ -96,8 +98,8 @@ public interface ITurtleUpgrade
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
* by the turtle, and the tool is required to do some work.
*
* Conforming implementations should fire {@code BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig}for digging,
* {@code AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
* Conforming implementations should fire {@link BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig} for
* digging, {@link AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
*
* @param turtle Access to the turtle that the tool resides on.
* @param side Which side of the turtle (left or right) the tool resides on.
@@ -119,8 +121,8 @@ public interface ITurtleUpgrade
/**
* Called to obtain the model to be used when rendering a turtle peripheral.
*
* This can be obtained from {@link net.minecraft.client.render.item.ItemModels#getModel(ItemStack)},
* {@link net.minecraft.client.render.model.BakedModelManager#getModel(ModelIdentifier)} or any other
* This can be obtained from {@link net.minecraft.client.renderer.ItemModelMesher#getItemModel(ItemStack)},
* {@link net.minecraft.client.renderer.model.ModelManager#getModel(ModelResourceLocation)} or any other
* source.
*
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models!
@@ -129,8 +131,8 @@ public interface ITurtleUpgrade
* a transformation of {@code null} has the same effect as the identify matrix.
*/
@Nonnull
@Environment( EnvType.CLIENT )
Pair<BakedModel, Matrix4f> getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side );
@OnlyIn( Dist.CLIENT )
Pair<IBakedModel, Matrix4f> getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side );
/**
* Called once per tick for each turtle which has the upgrade equipped.

View File

@@ -6,7 +6,7 @@
package dan200.computercraft.api.turtle;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Direction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

View File

@@ -12,12 +12,12 @@ package dan200.computercraft.api.turtle;
public enum TurtleSide
{
/**
* The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle)
* The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle).
*/
Left,
/**
* The turtle's right side (where the modem usually is on a Wireless Mining Turtle)
* The turtle's right side (where the modem usually is on a Wireless Mining Turtle).
*/
Right,
}

View File

@@ -6,7 +6,7 @@
package dan200.computercraft.api.turtle;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Direction;
/**
* An enum representing the different actions that an {@link ITurtleUpgrade} of type Tool may be called on to perform by
@@ -18,12 +18,12 @@ import net.minecraft.util.math.Direction;
public enum TurtleVerb
{
/**
* The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}
* The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}.
*/
Dig,
/**
* The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}
* The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}.
*/
Attack,
}

View File

@@ -1,286 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.turtle.event;
import com.mojang.authlib.GameProfile;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.block.entity.CommandBlockBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.command.arguments.EntityAnchorArgumentType;
import net.minecraft.container.Container;
import net.minecraft.container.NameableContainerProvider;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.passive.HorseBaseEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.NetworkState;
import net.minecraft.network.Packet;
import net.minecraft.network.chat.ChatMessageType;
import net.minecraft.network.chat.Component;
import net.minecraft.recipe.Recipe;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.server.network.packet.RequestCommandCompletionsC2SPacket;
import net.minecraft.server.network.packet.VehicleMoveC2SPacket;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.DefaultedList;
import net.minecraft.util.Hand;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.village.TraderOfferList;
import net.minecraft.world.GameMode;
import net.minecraft.world.dimension.DimensionType;
import javax.annotation.Nullable;
import javax.crypto.SecretKey;
import java.util.Collection;
import java.util.OptionalInt;
/**
* A wrapper for {@link ServerPlayerEntity} which denotes a "fake" player.
*
* Please note that this does not implement any of the traditional fake player behaviour. It simply exists to prevent
* me passing in normal players.
*/
public class FakePlayer extends ServerPlayerEntity
{
public FakePlayer( ServerWorld world, GameProfile gameProfile )
{
super( world.getServer(), world, gameProfile, new ServerPlayerInteractionManager( world ) );
networkHandler = new FakeNetHandler( this );
}
// region Direct networkHandler access
@Override
public void method_6000() { }
@Override
public void method_6044() { }
@Override
public void tick() { }
@Override
public void method_14226() { }
@Override
public void onDeath( DamageSource damage ) { }
@Nullable
@Override
public Entity changeDimension( DimensionType dimension )
{
return this;
}
@Override
public void wakeUp( boolean resetTimer, boolean notify, boolean setSpawn ) { }
@Override
public boolean startRiding( Entity entity, boolean flag )
{
return false;
}
@Override
public void stopRiding() { }
@Override
public void openEditSignScreen( SignBlockEntity tile ) { }
@Override
public OptionalInt openContainer( @Nullable NameableContainerProvider container )
{
return OptionalInt.empty();
}
@Override
public void sendTradeOffers( int id, TraderOfferList list, int level, int experience, boolean levelled ) { }
@Override
public void openHorseInventory( HorseBaseEntity horse, Inventory inventory ) { }
@Override
public void openEditBookScreen( ItemStack stack, Hand hand ) { }
@Override
public void openCommandBlockScreen( CommandBlockBlockEntity block ) { }
@Override
public void onContainerSlotUpdate( Container container, int slot, ItemStack stack ) { }
@Override
public void onContainerRegistered( Container container, DefaultedList<ItemStack> defaultedList ) { }
@Override
public void onContainerPropertyUpdate( Container container, int key, int value ) { }
@Override
public void closeContainer() { }
@Override
public void method_14241() { }
@Override
public void addChatMessage( Component textComponent, boolean status ) { }
@Override
protected void method_6040() { }
@Override
public void lookAt( EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d ) { }
@Override
public void method_14222( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) { }
@Override
protected void method_6020( StatusEffectInstance statusEffectInstance ) { }
@Override
protected void method_6009( StatusEffectInstance statusEffectInstance, boolean particles ) { }
@Override
protected void method_6129( StatusEffectInstance statusEffectInstance ) { }
@Override
public void requestTeleport( double x, double y, double z ) { }
@Override
public void setGameMode( GameMode gameMode ) { }
@Override
public void sendChatMessage( Component textComponent, ChatMessageType chatMessageType ) { }
@Override
public String getServerBrand()
{
return "[Fake Player]";
}
@Override
public void method_14255( String url, String hash ) { }
@Override
public void onStoppedTracking( Entity entity ) { }
@Override
public void setCameraEntity( Entity entity ) { }
@Override
public void teleport( ServerWorld serverWorld, double x, double y, double z, float pitch, float yaw ) { }
@Override
public void sendInitialChunkPackets( ChunkPos chunkPos, Packet<?> packet, Packet<?> packet2 ) { }
@Override
public void sendUnloadChunkPacket( ChunkPos chunkPos ) { }
@Override
public void playSound( SoundEvent soundEvent, SoundCategory soundCategory, float volume, float pitch ) { }
// endregion
// Indirect
@Override
public int lockRecipes( Collection<Recipe<?>> recipes )
{
return 0;
}
@Override
public int unlockRecipes( Collection<Recipe<?>> recipes )
{
return 0;
}
//
private static class FakeNetHandler extends ServerPlayNetworkHandler
{
FakeNetHandler( ServerPlayerEntity player )
{
super( player.server, new FakeConnection(), player );
}
@Override
public void disconnect( Component message ) { }
@Override
public void onRequestCommandCompletions( RequestCommandCompletionsC2SPacket packet ) { }
@Override
public void sendPacket( Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> listener ) { }
@Override
public void onVehicleMove( VehicleMoveC2SPacket move ) { }
}
private static class FakeConnection extends ClientConnection
{
FakeConnection()
{
super( NetworkSide.CLIENTBOUND );
}
@Override
public void channelActive( ChannelHandlerContext active )
{
}
@Override
public void setState( NetworkState state )
{
}
@Override
public void disconnect( Component message )
{
}
@Override
public void exceptionCaught( ChannelHandlerContext context, Throwable err )
{
}
@Override
protected void method_10770( ChannelHandlerContext context, Packet<?> packet )
{
}
@Override
public void tick()
{
}
@Override
public void setupEncryption( SecretKey key )
{
}
@Override
public void disableAutoRead()
{
}
@Override
public void setMinCompressedSize( int size )
{
}
@Override
public void send( Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> listener )
{
}
}
}

View File

@@ -71,7 +71,7 @@ public enum TurtleAction
EQUIP,
/**
* Inspect a block in world
* Inspect a block in world.
*
* @see TurtleBlockEvent.Inspect
*/

View File

@@ -8,6 +8,7 @@ package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import net.minecraftforge.eventbus.api.Cancelable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -16,11 +17,11 @@ import java.util.Objects;
/**
* An event fired when a turtle is performing a known action.
*/
@Cancelable
public class TurtleActionEvent extends TurtleEvent
{
private final TurtleAction action;
private String failureMessage;
private boolean cancelled = false;
public TurtleActionEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action )
{
@@ -44,6 +45,7 @@ public class TurtleActionEvent extends TurtleEvent
* @see TurtleCommandResult#failure()
* @deprecated Use {@link #setCanceled(boolean, String)} instead.
*/
@Override
@Deprecated
public void setCanceled( boolean cancel )
{
@@ -61,7 +63,7 @@ public class TurtleActionEvent extends TurtleEvent
*/
public void setCanceled( boolean cancel, @Nullable String failureMessage )
{
this.cancelled = true;
super.setCanceled( cancel );
this.failureMessage = cancel ? failureMessage : null;
}
@@ -77,15 +79,4 @@ public class TurtleActionEvent extends TurtleEvent
{
return failureMessage;
}
/**
* Determine if this event is cancelled
*
* @return If this event is cancelled
* @see #setCanceled(boolean, String)
*/
public boolean isCancelled()
{
return cancelled;
}
}

View File

@@ -11,7 +11,9 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.TurtleVerb;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Direction;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
import javax.annotation.Nonnull;
import java.util.Objects;
@@ -22,8 +24,7 @@ import java.util.Objects;
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)},
* as the base {@code turtle.attack()} command does not fire it.
*
* Note that such commands should also fire {@link net.fabricmc.fabric.api.event.player.AttackEntityCallback}, so you do
* not need to listen to both.
* Note that such commands should also fire {@link AttackEntityEvent}, so you do not need to listen to both.
*
* @see TurtleAction#ATTACK
*/

View File

@@ -14,9 +14,11 @@ import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.TurtleVerb;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.world.BlockEvent;
import javax.annotation.Nonnull;
import java.util.Map;
@@ -76,8 +78,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)},
* as the base {@code turtle.dig()} command does not fire it.
*
* Note that such commands should also fire {@link net.fabricmc.fabric.api.event.player.AttackBlockCallback}, so you
* do not need to listen to both.
* Note that such commands should also fire {@link BlockEvent.BreakEvent}, so you do not need to listen to both.
*
* @see TurtleAction#DIG
*/
@@ -111,7 +112,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
}
/**
* Get the upgrade doing the digging
* Get the upgrade doing the digging.
*
* @return The upgrade doing the digging.
*/

View File

@@ -6,8 +6,8 @@
package dan200.computercraft.api.turtle.event;
import com.google.common.eventbus.EventBus;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraftforge.eventbus.api.Event;
import javax.annotation.Nonnull;
import java.util.Objects;
@@ -20,10 +20,8 @@ import java.util.Objects;
*
* @see TurtleActionEvent
*/
public abstract class TurtleEvent
public abstract class TurtleEvent extends Event
{
public static final EventBus EVENT_BUS = new EventBus();
private final ITurtleAccess turtle;
protected TurtleEvent( @Nonnull ITurtleAccess turtle )
@@ -42,10 +40,4 @@ public abstract class TurtleEvent
{
return turtle;
}
public static boolean post( TurtleActionEvent event )
{
EVENT_BUS.post( event );
return event.isCancelled();
}
}

View File

@@ -1,9 +1,8 @@
/*
* 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
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.lua.ILuaContext;

View File

@@ -7,10 +7,11 @@
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -21,21 +22,21 @@ import java.util.Objects;
*/
public abstract class TurtleInventoryEvent extends TurtleBlockEvent
{
private final Inventory handler;
private final IItemHandler handler;
protected TurtleInventoryEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler )
protected TurtleInventoryEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler )
{
super( turtle, action, player, world, pos );
this.handler = handler;
}
/**
* Get the inventory being interacted with
* Get the inventory being interacted with.
*
* @return The inventory being interacted with, {@code null} if the item will be dropped to/sucked from the world.
*/
@Nullable
public Inventory getItemHandler()
public IItemHandler getItemHandler()
{
return handler;
}
@@ -47,7 +48,7 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
*/
public static class Suck extends TurtleInventoryEvent
{
public Suck( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler )
public Suck( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler )
{
super( turtle, TurtleAction.SUCK, player, world, pos, handler );
}
@@ -62,7 +63,7 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
{
private final ItemStack stack;
public Drop( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler, @Nonnull ItemStack stack )
public Drop( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable IItemHandler handler, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.DROP, player, world, pos, handler );

View File

@@ -7,6 +7,7 @@
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraftforge.common.util.FakePlayer;
import javax.annotation.Nonnull;
import java.util.Objects;

View File

@@ -1,9 +1,8 @@
/*
* 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
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;

View File

@@ -7,28 +7,35 @@
package dan200.computercraft.client;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.shared.common.IColouredItem;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import net.fabricmc.fabric.api.client.render.ColorProviderRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.ModelRotation;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.IUnbakedModel;
import net.minecraft.client.renderer.model.ModelResourceLocation;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.model.BasicState;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.util.HashSet;
import java.util.function.Consumer;
import java.util.Map;
/**
* Registers textures and models for items.
*/
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD )
public final class ClientRegistry
{
private static final String[] EXTRA_MODELS = new String[] {
@@ -52,8 +59,8 @@ public final class ClientRegistry
};
private static final String[] EXTRA_TEXTURES = new String[] {
// TODO: Gather these automatically from the model. I'm unable to get this working with Forge's current
// model loading code.
// TODO: Gather these automatically from the model. Sadly the model loader isn't available
// when stitching textures.
"block/turtle_colour",
"block/turtle_elf_overlay",
"block/turtle_crafty_face",
@@ -62,30 +69,70 @@ public final class ClientRegistry
private ClientRegistry() {}
public static void onTextureStitchEvent( SpriteAtlasTexture atlasTexture, ClientSpriteRegistryCallback.Registry registry )
@SubscribeEvent
public static void registerModels( ModelRegistryEvent event )
{
ModelLoaderRegistry.registerLoader( TurtleModelLoader.INSTANCE );
}
@SubscribeEvent
public static void onTextureStitchEvent( TextureStitchEvent.Pre event )
{
if( event.getMap() != Minecraft.getInstance().getTextureMap() ) return;
for( String extra : EXTRA_TEXTURES )
{
registry.register( new Identifier( ComputerCraft.MOD_ID, extra ) );
event.addSprite( new ResourceLocation( ComputerCraft.MOD_ID, extra ) );
}
}
public static void onModelBakeEvent( ResourceManager manager, Consumer<ModelIdentifier> out )
@SubscribeEvent
public static void onModelBakeEvent( ModelBakeEvent event )
{
// Load all extra models
ModelLoader loader = event.getModelLoader();
Map<ResourceLocation, IBakedModel> registry = event.getModelRegistry();
for( String model : EXTRA_MODELS )
{
out.accept( new ModelIdentifier( new Identifier( ComputerCraft.MOD_ID, model ), "inventory" ) );
IBakedModel bakedModel = bake( loader, loader.getUnbakedModel( new ResourceLocation( ComputerCraft.MOD_ID, "item/" + model ) ) );
if( bakedModel != null )
{
registry.put(
new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ),
bakedModel
);
}
}
// And load the custom turtle models in too.
registry.put(
new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_normal" ), "inventory" ),
bake( loader, TurtleModelLoader.INSTANCE.loadModel( new ResourceLocation( ComputerCraft.MOD_ID, "item/turtle_normal" ) ) )
);
registry.put(
new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_advanced" ), "inventory" ),
bake( loader, TurtleModelLoader.INSTANCE.loadModel( new ResourceLocation( ComputerCraft.MOD_ID, "item/turtle_advanced" ) ) )
);
}
public static void onItemColours()
@SubscribeEvent
public static void onItemColours( ColorHandlerEvent.Item event )
{
ColorProviderRegistry.ITEM.register(
if( ComputerCraft.Items.disk == null || ComputerCraft.Blocks.turtleNormal == null )
{
ComputerCraft.log.warn( "Block/item registration has failed. Skipping registration of item colours." );
return;
}
event.getItemColors().register(
( stack, layer ) -> layer == 1 ? ((ItemDisk) stack.getItem()).getColour( stack ) : 0xFFFFFF,
ComputerCraft.Items.disk
);
ColorProviderRegistry.ITEM.register( ( stack, layer ) -> {
event.getItemColors().register( ( stack, layer ) -> {
switch( layer )
{
case 0:
@@ -102,16 +149,20 @@ public final class ClientRegistry
}, ComputerCraft.Items.pocketComputerNormal, ComputerCraft.Items.pocketComputerAdvanced );
// Setup turtle colours
ColorProviderRegistry.ITEM.register(
event.getItemColors().register(
( stack, tintIndex ) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour( stack ) : 0xFFFFFF,
ComputerCraft.Blocks.turtleNormal, ComputerCraft.Blocks.turtleAdvanced
);
}
private static BakedModel bake( ModelLoader loader, UnbakedModel model )
private static IBakedModel bake( ModelLoader loader, IUnbakedModel model )
{
model.getTextureDependencies( loader::getOrLoadModel, new HashSet<>() );
SpriteAtlasTexture sprite = MinecraftClient.getInstance().getSpriteAtlas();
return model.bake( loader, sprite::getSprite, ModelRotation.X0_Y0 );
model.getTextures( loader::getUnbakedModel, new HashSet<>() );
return model.bake(
loader,
ModelLoader.defaultTextureGetter(),
new BasicState( model.getDefaultState(), false ), DefaultVertexFormats.BLOCK
);
}
}

View File

@@ -10,13 +10,13 @@ import dan200.computercraft.shared.command.text.ChatHelpers;
import dan200.computercraft.shared.command.text.TableBuilder;
import dan200.computercraft.shared.command.text.TableFormatter;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import net.minecraft.ChatFormat;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.hud.ChatHud;
import net.minecraft.client.util.TextComponentUtil;
import net.minecraft.network.chat.Component;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.NewChatGui;
import net.minecraft.client.gui.RenderComponentsUtil;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Nullable;
@@ -28,25 +28,25 @@ public class ClientTableFormatter implements TableFormatter
private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap();
private static TextRenderer renderer()
private static FontRenderer renderer()
{
return MinecraftClient.getInstance().textRenderer;
return Minecraft.getInstance().fontRenderer;
}
@Override
@Nullable
public Component getPadding( Component component, int width )
public ITextComponent getPadding( ITextComponent component, int width )
{
int extraWidth = width - getWidth( component );
if( extraWidth <= 0 ) return null;
TextRenderer renderer = renderer();
FontRenderer renderer = renderer();
float spaceWidth = renderer.getCharWidth( ' ' );
float spaceWidth = renderer.getStringWidth( " " );
int spaces = MathHelper.floor( extraWidth / spaceWidth );
int extra = extraWidth - (int) (spaces * spaceWidth);
return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), ChatFormat.GRAY );
return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), TextFormatting.GRAY );
}
@Override
@@ -56,34 +56,34 @@ public class ClientTableFormatter implements TableFormatter
}
@Override
public int getWidth( Component component )
public int getWidth( ITextComponent component )
{
return renderer().getStringWidth( component.getFormattedText() );
}
@Override
public void writeLine( int id, Component component )
public void writeLine( int id, ITextComponent component )
{
MinecraftClient mc = MinecraftClient.getInstance();
ChatHud chat = mc.inGameHud.getChatHud();
Minecraft mc = Minecraft.getInstance();
NewChatGui chat = mc.ingameGUI.getChatGUI();
// Trim the text if it goes over the allowed length
int maxWidth = MathHelper.floor( chat.getWidth() / chat.getScale() );
List<Component> list = TextComponentUtil.wrapLines( component, maxWidth, mc.textRenderer, false, false );
if( !list.isEmpty() ) chat.addMessage( list.get( 0 ), id );
int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() );
List<ITextComponent> list = RenderComponentsUtil.splitText( component, maxWidth, mc.fontRenderer, false, false );
if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
}
@Override
public int display( TableBuilder table )
{
ChatHud chat = MinecraftClient.getInstance().inGameHud.getChatHud();
NewChatGui chat = Minecraft.getInstance().ingameGUI.getChatGUI();
int lastHeight = lastHeights.get( table.getId() );
int height = TableFormatter.super.display( table );
lastHeights.put( table.getId(), height );
for( int i = height; i < lastHeight; i++ ) chat.removeMessage( i + table.getId() );
for( int i = height; i < lastHeight; i++ ) chat.deleteChatLine( i + table.getId() );
return height;
}
}

View File

@@ -6,6 +6,13 @@
package dan200.computercraft.client;
import dan200.computercraft.ComputerCraft;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class FrameInfo
{
private static int tick;
@@ -25,13 +32,15 @@ public final class FrameInfo
return renderFrame;
}
public static void onTick()
@SubscribeEvent
public static void onTick( TickEvent.ClientTickEvent event )
{
tick++;
if( event.phase == TickEvent.Phase.START ) tick++;
}
public static void onRenderFrame()
@SubscribeEvent
public static void onRenderTick( TickEvent.RenderTickEvent event )
{
renderFrame++;
if( event.phase == TickEvent.Phase.START ) renderFrame++;
}
}

View File

@@ -9,20 +9,20 @@ package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.util.Identifier;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import java.util.Arrays;
public final class FixedWidthFontRenderer
{
private static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" );
public static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/term_background.png" );
private static final ResourceLocation FONT = new ResourceLocation( "computercraft", "textures/gui/term_font.png" );
public static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/term_background.png" );
public static final int FONT_HEIGHT = 9;
public static final int FONT_WIDTH = 6;
@@ -39,7 +39,7 @@ public final class FixedWidthFontRenderer
private FixedWidthFontRenderer()
{
m_textureManager = MinecraftClient.getInstance().getTextureManager();
m_textureManager = Minecraft.getInstance().getTextureManager();
}
private static void greyscaleify( double[] rgb )
@@ -64,12 +64,12 @@ public final class FixedWidthFontRenderer
int xStart = 1 + column * (FONT_WIDTH + 2);
int yStart = 1 + row * (FONT_HEIGHT + 2);
renderer.vertex( x, y, 0.0 ).texture( xStart / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x, y + FONT_HEIGHT, 0.0 ).texture( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + FONT_WIDTH, y, 0.0 ).texture( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + FONT_WIDTH, y, 0.0 ).texture( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x, y + FONT_HEIGHT, 0.0 ).texture( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + FONT_WIDTH, y + FONT_HEIGHT, 0.0 ).texture( (xStart + FONT_WIDTH) / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).next();
renderer.pos( x, y, 0.0 ).tex( xStart / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x, y + FONT_HEIGHT, 0.0 ).tex( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + FONT_WIDTH, y, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + FONT_WIDTH, y, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, yStart / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x, y + FONT_HEIGHT, 0.0 ).tex( xStart / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + FONT_WIDTH, y + FONT_HEIGHT, 0.0 ).tex( (xStart + FONT_WIDTH) / 256.0, (yStart + FONT_HEIGHT) / 256.0 ).color( r, g, b, 1.0f ).endVertex();
}
private void drawQuad( BufferBuilder renderer, double x, double y, int color, double width, Palette p, boolean greyscale )
@@ -83,12 +83,12 @@ public final class FixedWidthFontRenderer
float g = (float) colour[1];
float b = (float) colour[2];
renderer.vertex( x, y, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + width, y, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + width, y, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( x + width, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.pos( x, y, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + width, y, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + width, y, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( x + width, y + FONT_HEIGHT, 0.0 ).color( r, g, b, 1.0f ).endVertex();
}
private boolean isGreyScale( int colour )
@@ -100,8 +100,8 @@ public final class FixedWidthFontRenderer
{
// Draw the quads
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBufferBuilder();
renderer.begin( GL11.GL_TRIANGLES, VertexFormats.POSITION_COLOR );
BufferBuilder renderer = tessellator.getBuffer();
renderer.begin( GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR );
if( leftMarginSize > 0.0 )
{
int colour1 = "0123456789abcdef".indexOf( backgroundColour.charAt( 0 ) );
@@ -138,8 +138,8 @@ public final class FixedWidthFontRenderer
{
// Draw the quads
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBufferBuilder();
renderer.begin( GL11.GL_TRIANGLES, VertexFormats.POSITION_UV_COLOR );
BufferBuilder renderer = tessellator.getBuffer();
renderer.begin( GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_TEX_COLOR );
for( int i = 0; i < s.length(); i++ )
{
// Switch colour

View File

@@ -10,23 +10,24 @@ import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.container.Container;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.util.Identifier;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import org.lwjgl.glfw.GLFW;
public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
public final class GuiComputer<T extends ContainerComputerBase> extends ContainerScreen<T>
{
public static final Identifier BACKGROUND_NORMAL = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_normal.png" );
public static final Identifier BACKGROUND_ADVANCED = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
public static final Identifier BACKGROUND_COMMAND = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
public static final Identifier BACKGROUND_COLOUR = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
public static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_normal.png" );
public static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" );
public static final ResourceLocation BACKGROUND_COMMAND = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" );
public static final ResourceLocation BACKGROUND_COLOUR = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" );
private final ComputerFamily m_family;
private final ClientComputer m_computer;
@@ -36,44 +37,58 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
private WidgetTerminal terminal;
private WidgetWrapper terminalWrapper;
public GuiComputer( T container, PlayerInventory player, ComputerFamily family, ClientComputer computer, int termWidth, int termHeight )
private GuiComputer(
T container, PlayerInventory player, ITextComponent title, int termWidth, int termHeight
)
{
super( container, player, new TextComponent( "" ) );
m_family = family;
m_computer = computer;
super( container, player, title );
m_family = container.getFamily();
m_computer = (ClientComputer) container.getComputer();
m_termWidth = termWidth;
m_termHeight = termHeight;
terminal = null;
}
public static GuiComputer<ContainerComputer> create( int id, TileComputer computer, PlayerInventory player )
public static GuiComputer<ContainerComputer> create( ContainerComputer container, PlayerInventory inventory, ITextComponent component )
{
return new GuiComputer<>(
new ContainerComputer( id, computer ), player,
computer.getFamily(),
computer.createClientComputer(),
ComputerCraft.terminalWidth_computer,
ComputerCraft.terminalHeight_computer
container, inventory, component,
ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer
);
}
public static GuiComputer<ContainerPocketComputer> createPocket( ContainerPocketComputer container, PlayerInventory inventory, ITextComponent component )
{
return new GuiComputer<>(
container, inventory, component,
ComputerCraft.terminalWidth_pocketComputer, ComputerCraft.terminalHeight_pocketComputer
);
}
public static GuiComputer<ContainerViewComputer> createView( ContainerViewComputer container, PlayerInventory inventory, ITextComponent component )
{
return new GuiComputer<>(
container, inventory, component,
container.getWidth(), container.getHeight()
);
}
@Override
protected void init()
{
minecraft.keyboard.enableRepeatEvents( true );
minecraft.keyboardListener.enableRepeatEvents( true );
int termPxWidth = m_termWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = m_termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
containerWidth = termPxWidth + 4 + 24;
containerHeight = termPxHeight + 4 + 24;
xSize = termPxWidth + 4 + 24;
ySize = termPxHeight + 4 + 24;
super.init();
terminal = new WidgetTerminal( minecraft, () -> m_computer, m_termWidth, m_termHeight, 2, 2, 2, 2 );
terminalWrapper = new WidgetWrapper( terminal, 2 + 12 + left, 2 + 12 + top, termPxWidth, termPxHeight );
terminalWrapper = new WidgetWrapper( terminal, 2 + 12 + guiLeft, 2 + 12 + guiTop, termPxWidth, termPxHeight );
children.add( terminalWrapper );
setFocused( terminalWrapper );
@@ -85,7 +100,7 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
super.removed();
children.remove( terminal );
terminal = null;
minecraft.keyboard.enableRepeatEvents( false );
minecraft.keyboardListener.enableRepeatEvents( false );
}
@Override
@@ -96,7 +111,19 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
}
@Override
public void drawBackground( float partialTicks, int mouseX, int mouseY )
public boolean keyPressed( int key, int scancode, int modifiers )
{
// Forward the tab key to the terminal, rather than moving between controls.
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper )
{
return getFocused().keyPressed( key, scancode, modifiers );
}
return super.keyPressed( key, scancode, modifiers );
}
@Override
public void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
// Work out where to draw
int startX = terminalWrapper.getX() - 2;
@@ -138,32 +165,15 @@ public class GuiComputer<T extends Container> extends AbstractContainerScreen<T>
@Override
public void render( int mouseX, int mouseY, float partialTicks )
{
renderBackground( 0 );
renderBackground();
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
}
@Override
public boolean keyPressed( int key, int scancode, int modifiers )
{
// When pressing tab, send it to the computer first
return (key == GLFW.GLFW_KEY_TAB && getFocused() == terminalWrapper && terminalWrapper.keyPressed( key, scancode, modifiers ))
|| super.keyPressed( key, scancode, modifiers );
renderHoveredToolTip( mouseX, mouseY );
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
// Make sure drag events are propagated to children
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY );
}
@Override
public boolean mouseReleased( double x, double y, int button )
{
// Make sure release events are propagated to children
return (getFocused() != null && getFocused().mouseReleased( x, y, button ))
|| super.mouseReleased( x, y, button );
}
}

View File

@@ -7,36 +7,35 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
public class GuiDiskDrive extends AbstractContainerScreen<ContainerDiskDrive>
public class GuiDiskDrive extends ContainerScreen<ContainerDiskDrive>
{
private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/disk_drive.png" );
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/disk_drive.png" );
public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory inventory )
public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory player, ITextComponent title )
{
super( container, inventory, ComputerCraft.Blocks.diskDrive.getTextComponent() );
super( container, player, title );
}
@Override
protected void drawForeground( int par1, int par2 )
protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY )
{
String title = getTitle().getFormattedText();
font.draw( title, (containerWidth - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
font.draw( I18n.translate( "container.inventory" ), 8, (containerHeight - 96) + 2, 0x404040 );
String title = this.title.getFormattedText();
font.drawString( title, (xSize - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
font.drawString( title, 8, ySize - 96 + 2, 0x404040 );
}
@Override
protected void drawBackground( float partialTicks, int mouseX, int mouseY )
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( BACKGROUND );
blit( left, top, 0, 0, containerWidth, containerHeight );
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
}
@Override
@@ -44,6 +43,6 @@ public class GuiDiskDrive extends AbstractContainerScreen<ContainerDiskDrive>
{
renderBackground();
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
renderHoveredToolTip( mouseX, mouseY );
}
}

View File

@@ -1,35 +0,0 @@
/*
* 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.gui;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
public class GuiPocketComputer extends GuiComputer<ContainerPocketComputer>
{
public GuiPocketComputer( ContainerPocketComputer container, PlayerInventory player )
{
super(
container, player,
getFamily( container.getStack() ),
ItemPocketComputer.createClientComputer( container.getStack() ),
ComputerCraft.terminalWidth_pocketComputer,
ComputerCraft.terminalHeight_pocketComputer
);
}
private static ComputerFamily getFamily( ItemStack stack )
{
Item item = stack.getItem();
return item instanceof ItemPocketComputer ? ((ItemPocketComputer) item).getFamily() : ComputerFamily.Normal;
}
}

View File

@@ -7,38 +7,38 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
public class GuiPrinter extends AbstractContainerScreen<ContainerPrinter>
public class GuiPrinter extends ContainerScreen<ContainerPrinter>
{
private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/printer.png" );
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/printer.png" );
public GuiPrinter( ContainerPrinter container, PlayerInventory player )
public GuiPrinter( ContainerPrinter container, PlayerInventory player, ITextComponent title )
{
super( container, player, ComputerCraft.Blocks.printer.getTextComponent() );
super( container, player, title );
}
@Override
protected void drawForeground( int mouseX, int mouseY )
protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY )
{
String title = getTitle().getFormattedText();
font.draw( title, (containerWidth - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
font.draw( I18n.translate( "container.inventory" ), 8, containerHeight - 96 + 2, 0x404040 );
font.drawString( title, (xSize - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
font.drawString( I18n.format( "container.inventory" ), 8, ySize - 96 + 2, 0x404040 );
}
@Override
protected void drawBackground( float f, int i, int j )
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( BACKGROUND );
blit( left, top, 0, 0, containerWidth, containerHeight );
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
if( container.isPrinting() ) blit( left + 34, top + 21, 176, 0, 25, 45 );
if( getContainer().isPrinting() ) blit( guiLeft + 34, guiTop + 21, 176, 0, 25, 45 );
}
@Override
@@ -46,6 +46,6 @@ public class GuiPrinter extends AbstractContainerScreen<ContainerPrinter>
{
renderBackground();
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
renderHoveredToolTip( mouseX, mouseY );
}
}

View File

@@ -10,13 +10,14 @@ import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.common.ContainerHeldItem;
import dan200.computercraft.shared.media.items.ItemPrintout;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent;
import org.lwjgl.glfw.GLFW;
import static dan200.computercraft.client.render.PrintoutRenderer.*;
public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
public class GuiPrintout extends ContainerScreen<ContainerHeldItem>
{
private final boolean m_book;
private final int m_pages;
@@ -24,11 +25,11 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
private final TextBuffer[] m_colours;
private int m_page;
public GuiPrintout( ContainerHeldItem container, PlayerInventory player )
public GuiPrintout( ContainerHeldItem container, PlayerInventory player, ITextComponent title )
{
super( container, player, container.getStack().getDisplayName() );
super( container, player, title );
containerHeight = Y_SIZE;
ySize = Y_SIZE;
String[] text = ItemPrintout.getText( container.getStack() );
m_text = new TextBuffer[text.length];
@@ -85,14 +86,14 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
}
@Override
public void drawBackground( float partialTicks, int mouseX, int mouseY )
public void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
// Draw the printout
GlStateManager.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
GlStateManager.enableDepthTest();
drawBorder( left, top, blitOffset, m_page, m_pages, m_book );
drawText( left + X_TEXT_MARGIN, top + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * m_page, m_text, m_colours );
drawBorder( guiLeft, guiTop, blitOffset, m_page, m_pages, m_book );
drawText( guiLeft + X_TEXT_MARGIN, guiTop + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * m_page, m_text, m_colours );
}
@Override
@@ -104,6 +105,6 @@ public class GuiPrintout extends AbstractContainerScreen<ContainerHeldItem>
blitOffset++;
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
renderHoveredToolTip( mouseX, mouseY );
}
}

View File

@@ -12,17 +12,17 @@ import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.client.gui.screen.ingame.AbstractContainerScreen;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import org.lwjgl.glfw.GLFW;
public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
public class GuiTurtle extends ContainerScreen<ContainerTurtle>
{
private static final Identifier BACKGROUND_NORMAL = new Identifier( "computercraft", "textures/gui/turtle_normal.png" );
private static final Identifier BACKGROUND_ADVANCED = new Identifier( "computercraft", "textures/gui/turtle_advanced.png" );
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( "computercraft", "textures/gui/turtle_normal.png" );
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( "computercraft", "textures/gui/turtle_advanced.png" );
private ContainerTurtle m_container;
@@ -32,23 +32,23 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
private WidgetTerminal terminal;
private WidgetWrapper terminalWrapper;
public GuiTurtle( TileTurtle turtle, ContainerTurtle container, PlayerInventory player )
public GuiTurtle( ContainerTurtle container, PlayerInventory player, ITextComponent title )
{
super( container, player, turtle.getDisplayName() );
super( container, player, title );
m_container = container;
m_family = turtle.getFamily();
m_computer = turtle.getClientComputer();
m_family = container.getFamily();
m_computer = (ClientComputer) container.getComputer();
containerWidth = 254;
containerHeight = 217;
xSize = 254;
ySize = 217;
}
@Override
protected void init()
{
super.init();
minecraft.keyboard.enableRepeatEvents( true );
minecraft.keyboardListener.enableRepeatEvents( true );
int termPxWidth = ComputerCraft.terminalWidth_turtle * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = ComputerCraft.terminalHeight_turtle * FixedWidthFontRenderer.FONT_HEIGHT;
@@ -59,7 +59,7 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
ComputerCraft.terminalHeight_turtle,
2, 2, 2, 2
);
terminalWrapper = new WidgetWrapper( terminal, 2 + 8 + left, 2 + 8 + top, termPxWidth, termPxHeight );
terminalWrapper = new WidgetWrapper( terminal, 2 + 8 + guiLeft, 2 + 8 + guiTop, termPxWidth, termPxHeight );
children.add( terminalWrapper );
setFocused( terminalWrapper );
@@ -71,7 +71,7 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
super.removed();
children.remove( terminal );
terminal = null;
minecraft.keyboard.enableRepeatEvents( false );
minecraft.keyboardListener.enableRepeatEvents( false );
}
@Override
@@ -81,6 +81,18 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
terminal.update();
}
@Override
public boolean keyPressed( int key, int scancode, int modifiers )
{
// Forward the tab key to the terminal, rather than moving between controls.
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper )
{
return getFocused().keyPressed( key, scancode, modifiers );
}
return super.keyPressed( key, scancode, modifiers );
}
private void drawSelectionSlot( boolean advanced )
{
// Draw selection slot
@@ -91,12 +103,12 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
int slotX = slot % 4;
int slotY = slot / 4;
minecraft.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
blit( left + m_container.m_turtleInvStartX - 2 + slotX * 18, top + m_container.m_playerInvStartY - 2 + slotY * 18, 0, 217, 24, 24 );
blit( guiLeft + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, guiTop + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18, 0, 217, 24, 24 );
}
}
@Override
protected void drawBackground( float partialTicks, int mouseX, int mouseY )
protected void drawGuiContainerBackgroundLayer( float partialTicks, int mouseX, int mouseY )
{
// Draw term
boolean advanced = m_family == ComputerFamily.Advanced;
@@ -105,7 +117,7 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
// Draw border/inventory
GlStateManager.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
minecraft.getTextureManager().bindTexture( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
blit( left, top, 0, 0, containerWidth, containerHeight );
blit( guiLeft, guiTop, 0, 0, xSize, ySize );
drawSelectionSlot( advanced );
}
@@ -115,14 +127,7 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
{
renderBackground();
super.render( mouseX, mouseY, partialTicks );
drawMouseoverTooltip( mouseX, mouseY );
}
@Override
public boolean keyPressed( int key, int scancode, int modifiers )
{
return (key == GLFW.GLFW_KEY_TAB && getFocused() == terminalWrapper && terminalWrapper.keyPressed( key, scancode, modifiers ))
|| super.keyPressed( key, scancode, modifiers );
renderHoveredToolTip( mouseX, mouseY );
}
@Override
@@ -131,11 +136,4 @@ public class GuiTurtle extends AbstractContainerScreen<ContainerTurtle>
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY );
}
@Override
public boolean mouseReleased( double x, double y, int button )
{
return (getFocused() != null && getFocused().mouseReleased( x, y, button ))
|| super.mouseReleased( x, y, button );
}
}

View File

@@ -15,12 +15,12 @@ import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.SharedConstants;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.Element;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.SharedConstants;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
@@ -29,18 +29,18 @@ import java.util.function.Supplier;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.BACKGROUND;
public class WidgetTerminal implements Element
public class WidgetTerminal implements IGuiEventListener
{
private static final float TERMINATE_TIME = 0.5f;
private final MinecraftClient minecraft;
private final Minecraft client;
private boolean focused;
private final Supplier<ClientComputer> computer;
private final int termWidth;
private final int termHeight;
private boolean focused;
private float terminateTimer = -1;
private float rebootTimer = -1;
private float shutdownTimer = -1;
@@ -56,9 +56,9 @@ public class WidgetTerminal implements Element
private final BitSet keysDown = new BitSet( 256 );
public WidgetTerminal( MinecraftClient minecraft, Supplier<ClientComputer> computer, int termWidth, int termHeight, int leftMargin, int rightMargin, int topMargin, int bottomMargin )
public WidgetTerminal( Minecraft client, Supplier<ClientComputer> computer, int termWidth, int termHeight, int leftMargin, int rightMargin, int topMargin, int bottomMargin )
{
this.minecraft = minecraft;
this.client = client;
this.computer = computer;
this.termWidth = termWidth;
this.termHeight = termHeight;
@@ -100,7 +100,7 @@ public class WidgetTerminal implements Element
case GLFW.GLFW_KEY_V:
// Ctrl+V for paste
String clipboard = minecraft.keyboard.getClipboard();
String clipboard = client.keyboardListener.getClipboardString();
if( clipboard != null )
{
// Clip to the first occurrence of \r or \n
@@ -120,7 +120,7 @@ public class WidgetTerminal implements Element
}
// Filter the string
clipboard = SharedConstants.stripInvalidChars( clipboard );
clipboard = SharedConstants.filterAllowedCharacters( clipboard );
if( !clipboard.isEmpty() )
{
// Clip to 512 characters and queue the event
@@ -241,11 +241,12 @@ public class WidgetTerminal implements Element
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
computer.mouseDrag( button + 1, charX + 1, charY + 1 );
lastMouseX = charX;
lastMouseY = charY;
lastMouseButton = button;
if( button == lastMouseButton && (charX != lastMouseX || charY != lastMouseY) )
{
computer.mouseDrag( button + 1, charX + 1, charY + 1 );
lastMouseX = charX;
lastMouseY = charY;
}
}
return false;
@@ -295,7 +296,7 @@ public class WidgetTerminal implements Element
}
@Override
public boolean changeFocus( boolean reverse )
public boolean changeFocus( boolean reversed )
{
if( focused )
{
@@ -316,7 +317,6 @@ public class WidgetTerminal implements Element
shutdownTimer = terminateTimer = rebootTimer = -1;
}
focused = !focused;
return true;
}
@@ -398,15 +398,15 @@ public class WidgetTerminal implements Element
int width = termWidth * FixedWidthFontRenderer.FONT_WIDTH + leftMargin + rightMargin;
int height = termHeight * FixedWidthFontRenderer.FONT_HEIGHT + topMargin + bottomMargin;
minecraft.getTextureManager().bindTexture( BACKGROUND );
client.getTextureManager().bindTexture( BACKGROUND );
Tessellator tesslector = Tessellator.getInstance();
BufferBuilder buffer = tesslector.getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_UV );
buffer.vertex( x, y + height, 0 ).texture( 0 / 256.0, height / 256.0 ).next();
buffer.vertex( x + width, y + height, 0 ).texture( width / 256.0, height / 256.0 ).next();
buffer.vertex( x + width, y, 0 ).texture( width / 256.0, 0 / 256.0 ).next();
buffer.vertex( x, y, 0 ).texture( 0 / 256.0, 0 / 256.0 ).next();
BufferBuilder buffer = tesslector.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX );
buffer.pos( x, y + height, 0 ).tex( 0 / 256.0, height / 256.0 ).endVertex();
buffer.pos( x + width, y + height, 0 ).tex( width / 256.0, height / 256.0 ).endVertex();
buffer.pos( x + width, y, 0 ).tex( width / 256.0, 0 / 256.0 ).endVertex();
buffer.pos( x, y, 0 ).tex( 0 / 256.0, 0 / 256.0 ).endVertex();
tesslector.draw();
}
finally
@@ -428,4 +428,10 @@ public class WidgetTerminal implements Element
ClientComputer computer = this.computer.get();
if( computer != null ) computer.queueEvent( event, args );
}
@Override
public boolean isMouseOver( double x, double y )
{
return true;
}
}

View File

@@ -6,17 +6,17 @@
package dan200.computercraft.client.gui.widgets;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.IGuiEventListener;
public class WidgetWrapper implements Element
public class WidgetWrapper implements IGuiEventListener
{
private final Element listener;
private final IGuiEventListener listener;
private final int x;
private final int y;
private final int width;
private final int height;
public WidgetWrapper( Element listener, int x, int y, int width, int height )
public WidgetWrapper( IGuiEventListener listener, int x, int y, int width, int height )
{
this.listener = listener;
this.x = x;
@@ -26,16 +26,9 @@ public class WidgetWrapper implements Element
}
@Override
public void mouseMoved( double x, double y )
public boolean changeFocus( boolean b )
{
double dx = x - this.x, dy = y - this.y;
if( dx >= 0 && dx < width && dy >= 0 && dy < height ) listener.mouseMoved( dx, dy );
}
@Override
public boolean changeFocus( boolean reverse )
{
return listener.changeFocus( reverse );
return listener.changeFocus( b );
}
@Override
@@ -62,8 +55,7 @@ public class WidgetWrapper implements Element
@Override
public boolean mouseScrolled( double x, double y, double delta )
{
double dx = x - this.x, dy = y - this.y;
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseScrolled( dx, dy, delta );
return listener.mouseScrolled( x, y, delta );
}
@Override

View File

@@ -7,78 +7,58 @@
package dan200.computercraft.client.proxy;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.ClientRegistry;
import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.client.gui.*;
import dan200.computercraft.client.render.TileEntityCableRenderer;
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.common.ContainerHeldItem;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.network.container.*;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
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.peripheral.printer.ContainerPrinter;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.render.BlockEntityRendererRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.fabricmc.fabric.api.event.client.ClientTickCallback;
import net.minecraft.container.ArrayPropertyDelegate;
import net.minecraft.inventory.BasicInventory;
import net.minecraft.client.gui.ScreenManager;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD )
public final class ComputerCraftProxyClient
{
public static void setup()
@SubscribeEvent
public static void setupClient( FMLClientSetupEvent event )
{
registerContainers();
// Setup TESRs
BlockEntityRendererRegistry.INSTANCE.register( TileMonitor.class, new TileEntityMonitorRenderer() );
BlockEntityRendererRegistry.INSTANCE.register( TileCable.class, new TileEntityCableRenderer() );
BlockEntityRendererRegistry.INSTANCE.register( TileTurtle.class, new TileEntityTurtleRenderer() );
ClientRegistry.onItemColours();
ClientSpriteRegistryCallback.registerBlockAtlas( ClientRegistry::onTextureStitchEvent );
ModelLoadingRegistry.INSTANCE.registerAppender( ClientRegistry::onModelBakeEvent );
ModelLoadingRegistry.INSTANCE.registerResourceProvider( loader -> ( name, context ) ->
TurtleModelLoader.INSTANCE.accepts( name ) ? TurtleModelLoader.INSTANCE.loadModel( name ) : null
);
ClientTickCallback.EVENT.register( client -> FrameInfo.onTick() );
ClientRegistry.bindTileEntitySpecialRenderer( TileMonitor.class, new TileEntityMonitorRenderer() );
ClientRegistry.bindTileEntitySpecialRenderer( TileCable.class, new TileEntityCableRenderer() );
ClientRegistry.bindTileEntitySpecialRenderer( TileTurtle.class, new TileEntityTurtleRenderer() );
}
private static void registerContainers()
{
ContainerType.registerGui( TileEntityContainerType::computer, ( id, packet, player ) ->
GuiComputer.create( id, (TileComputer) packet.getTileEntity( player ), player.inventory ) );
ContainerType.registerGui( TileEntityContainerType::diskDrive, GuiDiskDrive::new );
ContainerType.registerGui( TileEntityContainerType::printer, GuiPrinter::new );
ContainerType.registerGui( TileEntityContainerType::turtle, ( id, packet, player ) -> {
TileTurtle turtle = (TileTurtle) packet.getTileEntity( player );
return new GuiTurtle( turtle,
new ContainerTurtle( id, player.inventory, new BasicInventory( TileTurtle.INVENTORY_SIZE ), new ArrayPropertyDelegate( 1 ) ),
player.inventory
);
} );
// My IDE doesn't think so, but we do actually need these generics.
ContainerType.registerGui( PocketComputerContainerType::new, GuiPocketComputer::new );
ContainerType.registerGui( PrintoutContainerType::new, GuiPrintout::new );
ContainerType.registerGui( ViewComputerContainerType::new, ( id, packet, player ) -> {
ClientComputer computer = ComputerCraft.clientComputerRegistry.get( packet.instanceId );
if( computer == null )
{
ComputerCraft.clientComputerRegistry.add( packet.instanceId, computer = new ClientComputer( packet.instanceId ) );
}
ScreenManager.<ContainerComputer, GuiComputer<ContainerComputer>>registerFactory( ContainerComputer.TYPE, GuiComputer::create );
ScreenManager.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>registerFactory( ContainerPocketComputer.TYPE, GuiComputer::createPocket );
ScreenManager.registerFactory( ContainerTurtle.TYPE, GuiTurtle::new );
ContainerViewComputer container = new ContainerViewComputer( id, computer );
return new GuiComputer<>( container, player.inventory, packet.family, computer, packet.width, packet.height );
} );
ScreenManager.registerFactory( ContainerPrinter.TYPE, GuiPrinter::new );
ScreenManager.registerFactory( ContainerDiskDrive.TYPE, GuiDiskDrive::new );
ScreenManager.registerFactory( ContainerHeldItem.PRINTOUT_TYPE, GuiPrintout::new );
ScreenManager.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>registerFactory( ContainerViewComputer.TYPE, GuiComputer::createView );
}
/*
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public static final class ForgeHandlers
{
@@ -91,5 +71,4 @@ public final class ComputerCraftProxyClient
}
}
}
*/
}

View File

@@ -12,17 +12,22 @@ import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
import dan200.computercraft.shared.peripheral.modem.wired.CableShapes;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.lwjgl.opengl.GL11;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class CableHighlightRenderer
{
private CableHighlightRenderer()
@@ -32,43 +37,54 @@ public final class CableHighlightRenderer
/**
* Draw an outline for a specific part of a cable "Multipart".
*
* @see WorldRenderer#drawHighlightedBlockOutline(Entity, HitResult, int, float)
* @param event The event to observe
* @see WorldRenderer#drawSelectionBox(ActiveRenderInfo, RayTraceResult, int)
*/
public static boolean drawHighlight( Camera camera, BlockHitResult hit )
@SubscribeEvent
public static void drawHighlight( DrawBlockHighlightEvent event )
{
MinecraftClient mc = MinecraftClient.getInstance();
BlockPos pos = hit.getBlockPos();
World world = mc.world;
if( event.getTarget().getType() != RayTraceResult.Type.BLOCK ) return;
BlockRayTraceResult hit = (BlockRayTraceResult) event.getTarget();
BlockPos pos = hit.getPos();
World world = event.getInfo().getRenderViewEntity().getEntityWorld();
ActiveRenderInfo info = event.getInfo();
BlockState state = world.getBlockState( pos );
// We only care about instances with both cable and modem.
if( state.getBlock() != ComputerCraft.Blocks.cable || state.get( BlockCable.MODEM ).getFacing() == null || !state.get( BlockCable.CABLE ) )
{
return false;
return;
}
event.setCanceled( true );
Minecraft mc = Minecraft.getInstance();
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate( GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO );
GlStateManager.lineWidth( Math.max( 2.5F, mc.window.getFramebufferWidth() / 1920.0F * 2.5F ) );
GlStateManager.lineWidth( Math.max( 2.5F, mc.mainWindow.getFramebufferWidth() / 1920.0F * 2.5F ) );
GlStateManager.disableTexture();
GlStateManager.depthMask( false );
GlStateManager.matrixMode( GL11.GL_PROJECTION );
GlStateManager.pushMatrix();
GlStateManager.scalef( 1.0F, 1.0F, 0.999F );
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) )
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getHitVec().subtract( pos.getX(), pos.getY(), pos.getZ() ) )
? CableShapes.getModemShape( state )
: CableShapes.getCableShape( state );
WorldRenderer.drawShapeOutline( shape, pos.getX() - camera.getPos().getX(), pos.getY() - camera.getPos().getY(), pos.getZ() - camera.getPos().getZ(), 0.0F, 0.0F, 0.0F, 0.4F );
Vec3d cameraPos = info.getProjectedView();
WorldRenderer.drawShape(
shape, pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ(),
0.0F, 0.0F, 0.0F, 0.4F
);
GlStateManager.popMatrix();
GlStateManager.matrixMode( GL11.GL_MODELVIEW );
GlStateManager.depthMask( true );
GlStateManager.enableTexture();
GlStateManager.disableBlend();
return true;
}
}

View File

@@ -7,38 +7,37 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.shared.mixed.MixedFirstPersonRenderer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.FirstPersonRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.FirstPersonRenderer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AbsoluteHand;
import net.minecraft.util.Hand;
import net.minecraft.util.HandSide;
import net.minecraft.util.math.MathHelper;
public abstract class ItemMapLikeRenderer
{
/**
* The main rendering method for the item
* The main rendering method for the item.
*
* @param stack The stack to render
* @see FirstPersonRenderer#renderFirstPersonMap(ItemStack)
* @see FirstPersonRenderer#renderMapFirstPerson(ItemStack)
*/
protected abstract void renderItem( ItemStack stack );
public void renderItemFirstPerson( Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
protected void renderItemFirstPerson( Hand hand, float pitch, float equipProgress, float swingProgress, ItemStack stack )
{
PlayerEntity player = MinecraftClient.getInstance().player;
PlayerEntity player = Minecraft.getInstance().player;
GlStateManager.pushMatrix();
if( hand == Hand.MAIN_HAND && player.getOffHandStack().isEmpty() )
if( hand == Hand.MAIN_HAND && player.getHeldItemOffhand().isEmpty() )
{
renderItemFirstPersonCenter( pitch, equipProgress, swingProgress, stack );
}
else
{
renderItemFirstPersonSide(
hand == Hand.MAIN_HAND ? player.getMainHand() : player.getMainHand().getOpposite(),
hand == Hand.MAIN_HAND ? player.getPrimaryHand() : player.getPrimaryHand().opposite(),
equipProgress, swingProgress, stack
);
}
@@ -52,12 +51,12 @@ public abstract class ItemMapLikeRenderer
* @param equipProgress The equip progress of this item
* @param swingProgress The swing progress of this item
* @param stack The stack to render
* @see FirstPersonRenderer#method_3222(float, AbsoluteHand, float, ItemStack) // renderMapFirstPersonSide
* @see FirstPersonRenderer#renderMapFirstPersonSide(float, HandSide, float, ItemStack)
*/
private void renderItemFirstPersonSide( AbsoluteHand side, float equipProgress, float swingProgress, ItemStack stack )
private void renderItemFirstPersonSide( HandSide side, float equipProgress, float swingProgress, ItemStack stack )
{
MinecraftClient minecraft = MinecraftClient.getInstance();
float offset = side == AbsoluteHand.RIGHT ? 1f : -1f;
Minecraft minecraft = Minecraft.getInstance();
float offset = side == HandSide.RIGHT ? 1f : -1f;
GlStateManager.translatef( offset * 0.125f, -0.125f, 0f );
// If the player is not invisible then render a single arm
@@ -65,7 +64,7 @@ public abstract class ItemMapLikeRenderer
{
GlStateManager.pushMatrix();
GlStateManager.rotatef( offset * 10f, 0f, 0f, 1f );
((MixedFirstPersonRenderer) minecraft.getFirstPersonRenderer()).renderArmFirstPerson_CC( equipProgress, swingProgress, side );
minecraft.getFirstPersonRenderer().renderArmFirstPerson( equipProgress, swingProgress, side );
GlStateManager.popMatrix();
}
@@ -88,17 +87,17 @@ public abstract class ItemMapLikeRenderer
}
/**
* Render an item in the middle of the screen
* Render an item in the middle of the screen.
*
* @param pitch The pitch of the player
* @param equipProgress The equip progress of this item
* @param swingProgress The swing progress of this item
* @param stack The stack to render
* @see FirstPersonRenderer#renderFirstPersonMap(float, float, float)
* @see FirstPersonRenderer#renderMapFirstPerson(float, float, float)
*/
private void renderItemFirstPersonCenter( float pitch, float equipProgress, float swingProgress, ItemStack stack )
{
MixedFirstPersonRenderer renderer = (MixedFirstPersonRenderer) MinecraftClient.getInstance().getFirstPersonRenderer();
FirstPersonRenderer renderer = Minecraft.getInstance().getFirstPersonRenderer();
// Setup the appropriate transformations. This is just copied from the
// corresponding method in ItemRenderer.
@@ -106,10 +105,10 @@ public abstract class ItemMapLikeRenderer
float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI );
float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI );
GlStateManager.translatef( 0f, -tX / 2f, tZ );
float pitchAngle = renderer.getMapAngleFromPitch_CC( pitch );
float pitchAngle = renderer.getMapAngleFromPitch( pitch );
GlStateManager.translatef( 0f, 0.04f + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f );
GlStateManager.rotatef( pitchAngle * -85f, 1f, 0f, 0f );
renderer.renderArms_CC();
renderer.renderArms();
float rX = MathHelper.sin( swingRt * (float) Math.PI );
GlStateManager.rotatef( rX * 20f, 1f, 0f, 0f );
GlStateManager.scalef( 2f, 2f, 2f );

View File

@@ -17,34 +17,46 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.Palette;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderSpecificHandEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
import static dan200.computercraft.client.gui.GuiComputer.*;
/**
* Emulates map rendering for pocket computers
* Emulates map rendering for pocket computers.
*/
@Environment( EnvType.CLIENT )
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class ItemPocketRenderer extends ItemMapLikeRenderer
{
private static final int MARGIN = 2;
private static final int FRAME = 12;
private static final int LIGHT_HEIGHT = 8;
public static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
private static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
private ItemPocketRenderer()
{
}
@SubscribeEvent
public static void renderItem( RenderSpecificHandEvent event )
{
ItemStack stack = event.getItemStack();
if( !(stack.getItem() instanceof ItemPocketComputer) ) return;
event.setCanceled( true );
INSTANCE.renderItemFirstPerson( event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() );
}
@Override
protected void renderItem( ItemStack stack )
{
@@ -100,13 +112,13 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
else
{
// Otherwise render a plain background
MinecraftClient.getInstance().getTextureManager().bindTexture( BACKGROUND );
Minecraft.getInstance().getTextureManager().bindTexture( BACKGROUND );
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
BufferBuilder buffer = tessellator.getBuffer();
Colour black = Colour.Black;
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION );
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION );
renderTexture( buffer, 0, 0, 0, 0, width, height, black.getR(), black.getG(), black.getB() );
tessellator.draw();
}
@@ -119,7 +131,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
private static void renderFrame( ComputerFamily family, int colour, int width, int height )
{
MinecraftClient.getInstance().getTextureManager().bindTexture( colour != -1
Minecraft.getInstance().getTextureManager().bindTexture( colour != -1
? BACKGROUND_COLOUR
: family == ComputerFamily.Normal ? BACKGROUND_NORMAL : BACKGROUND_ADVANCED
);
@@ -129,8 +141,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
float b = (colour & 0xFF) / 255.0f;
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_UV_COLOR );
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR );
// Top left, middle, right
renderTexture( buffer, -FRAME, -FRAME, 12, 28, FRAME, FRAME, r, g, b );
@@ -168,12 +180,12 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
float b = (colour & 0xFF) / 255.0f;
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR );
buffer.vertex( width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).next();
buffer.vertex( width, height + LIGHT_HEIGHT + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).next();
buffer.vertex( width, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).next();
buffer.vertex( width - LIGHT_HEIGHT * 2, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).next();
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR );
buffer.pos( width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( width, height + LIGHT_HEIGHT + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( width, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex();
buffer.pos( width - LIGHT_HEIGHT * 2, height + FRAME / 2.0f, 0.0D ).color( r, g, b, 1.0f ).endVertex();
tessellator.draw();
GlStateManager.enableTexture();
@@ -234,9 +246,9 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
private static void renderTexture( BufferBuilder builder, int x, int y, int textureX, int textureY, int width, int height, int textureWidth, int textureHeight, float r, float g, float b )
{
float scale = 1 / 255.0f;
builder.vertex( x, y + height, 0 ).texture( textureX * scale, (textureY + textureHeight) * scale ).color( r, g, b, 1.0f ).next();
builder.vertex( x + width, y + height, 0 ).texture( (textureX + textureWidth) * scale, (textureY + textureHeight) * scale ).color( r, g, b, 1.0f ).next();
builder.vertex( x + width, y, 0 ).texture( (textureX + textureWidth) * scale, textureY * scale ).color( r, g, b, 1.0f ).next();
builder.vertex( x, y, 0 ).texture( textureX * scale, textureY * scale ).color( r, g, b, 1.0f ).next();
builder.pos( x, y + height, 0 ).tex( textureX * scale, (textureY + textureHeight) * scale ).color( r, g, b, 1.0f ).endVertex();
builder.pos( x + width, y + height, 0 ).tex( (textureX + textureWidth) * scale, (textureY + textureHeight) * scale ).color( r, g, b, 1.0f ).endVertex();
builder.pos( x + width, y, 0 ).tex( (textureX + textureWidth) * scale, textureY * scale ).color( r, g, b, 1.0f ).endVertex();
builder.pos( x, y, 0 ).tex( textureX * scale, textureY * scale ).color( r, g, b, 1.0f ).endVertex();
}
}

View File

@@ -7,11 +7,14 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.media.items.ItemPrintout;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.entity.decoration.ItemFrameEntity;
import net.minecraft.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderItemInFrameEvent;
import net.minecraftforge.client.event.RenderSpecificHandEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
@@ -20,18 +23,17 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAG
import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENGTH;
/**
* Emulates map and item-frame rendering for printouts
* Emulates map and item-frame rendering for printouts.
*/
@Environment( EnvType.CLIENT )
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
{
public static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer();
private static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer();
private ItemPrintoutRenderer()
{
}
/*
@SubscribeEvent
public static void onRenderInHand( RenderSpecificHandEvent event )
{
@@ -41,7 +43,6 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
event.setCanceled( true );
INSTANCE.renderItemFirstPerson( event.getHand(), event.getInterpolatedPitch(), event.getEquipProgress(), event.getSwingProgress(), event.getItemStack() );
}
*/
@Override
protected void renderItem( ItemStack stack )
@@ -60,12 +61,15 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
GlStateManager.enableLighting();
}
public void renderInFrame( ItemFrameEntity entity, ItemStack stack )
@SubscribeEvent
public static void onRenderInFrame( RenderItemInFrameEvent event )
{
GlStateManager.disableLighting();
ItemStack stack = event.getItem();
if( !(stack.getItem() instanceof ItemPrintout) ) return;
int rotation = entity.getRotation();
GlStateManager.rotatef( (float) rotation * 360.0F / 8.0F, 0.0F, 0.0F, 1.0F );
event.setCanceled( true );
GlStateManager.disableLighting();
// Move a little bit forward to ensure we're not clipping with the frame
GlStateManager.translatef( 0.0f, 0.0f, -0.001f );

View File

@@ -6,13 +6,19 @@
package dan200.computercraft.client.render;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormatElement;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.Direction;
import net.minecraftforge.client.model.pipeline.IVertexConsumer;
import net.minecraftforge.client.model.pipeline.LightUtil;
import net.minecraftforge.client.model.pipeline.VertexTransformer;
import net.minecraftforge.common.model.TRSRTransformation;
import javax.annotation.Nonnull;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector4f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import java.util.List;
/**
@@ -34,11 +40,6 @@ public final class ModelTransformer
}
public static void transformQuadsTo( List<BakedQuad> output, List<BakedQuad> input, Matrix4f transform )
{
transformQuadsTo( VertexFormats.POSITION_COLOR_UV_NORMAL, output, input, transform );
}
public static void transformQuadsTo( VertexFormat format, List<BakedQuad> output, List<BakedQuad> input, Matrix4f transform )
{
if( transform == null || transform.equals( identity ) )
{
@@ -46,55 +47,224 @@ public final class ModelTransformer
}
else
{
for( BakedQuad quad : input ) output.add( doTransformQuad( format, quad, transform ) );
Matrix4f normalMatrix = new Matrix4f( transform );
normalMatrix.invert();
normalMatrix.transpose();
for( BakedQuad quad : input ) output.add( doTransformQuad( quad, transform, normalMatrix ) );
}
}
public static BakedQuad transformQuad( VertexFormat format, BakedQuad input, Matrix4f transform )
public static BakedQuad transformQuad( BakedQuad input, Matrix4f transform )
{
if( transform == null || transform.equals( identity ) ) return input;
return doTransformQuad( format, input, transform );
Matrix4f normalMatrix = new Matrix4f( transform );
normalMatrix.invert();
normalMatrix.transpose();
return doTransformQuad( input, transform, normalMatrix );
}
private static BakedQuad doTransformQuad( VertexFormat format, BakedQuad quad, Matrix4f transform )
private static BakedQuad doTransformQuad( BakedQuad input, Matrix4f positionMatrix, Matrix4f normalMatrix )
{
int[] vertexData = quad.getVertexData().clone();
int offset = 0;
BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), quad.getSprite() );
for( int i = 0; i < format.getElementCount(); ++i ) // For each vertex element
BakedQuadBuilder builder = new BakedQuadBuilder( input.getFormat() );
NormalAwareTransformer transformer = new NormalAwareTransformer( builder, positionMatrix, normalMatrix );
input.pipe( transformer );
if( transformer.areNormalsInverted() )
{
VertexFormatElement element = format.getElement( i );
if( element.isPosition() &&
element.getFormat() == VertexFormatElement.Format.FLOAT &&
element.getCount() == 3 ) // When we find a position element
{
for( int j = 0; j < 4; ++j ) // For each corner of the quad
{
int start = offset + j * format.getVertexSize();
if( (start % 4) == 0 )
{
start = start / 4;
// Extract the position
Vector4f pos = new Vector4f(
Float.intBitsToFloat( vertexData[start] ),
Float.intBitsToFloat( vertexData[start + 1] ),
Float.intBitsToFloat( vertexData[start + 2] ),
1
);
// Transform the position
transform.transform( pos );
// Insert the position
vertexData[start] = Float.floatToRawIntBits( pos.x );
vertexData[start + 1] = Float.floatToRawIntBits( pos.y );
vertexData[start + 2] = Float.floatToRawIntBits( pos.z );
}
}
}
offset += element.getSize();
builder.swap( 1, 3 );
transformer.areNormalsInverted();
}
return builder.build();
}
/**
* A vertex transformer that tracks whether the normals have been inverted and so the vertices
* should be reordered so backface culling works as expected.
*/
private static class NormalAwareTransformer extends VertexTransformer
{
private final Matrix4f positionMatrix;
private final Matrix4f normalMatrix;
private int vertexIndex = 0, elementIndex = 0;
private final Point3f[] before = new Point3f[4];
private final Point3f[] after = new Point3f[4];
NormalAwareTransformer( IVertexConsumer parent, Matrix4f positionMatrix, Matrix4f normalMatrix )
{
super( parent );
this.positionMatrix = positionMatrix;
this.normalMatrix = normalMatrix;
}
@Override
public void setQuadOrientation( @Nonnull Direction orientation )
{
super.setQuadOrientation( orientation == null ? orientation : TRSRTransformation.rotate( positionMatrix, orientation ) );
}
@Override
public void put( int element, @Nonnull float... data )
{
switch( getVertexFormat().getElement( element ).getUsage() )
{
case POSITION:
{
Point3f vec = new Point3f( data );
Point3f newVec = new Point3f();
positionMatrix.transform( vec, newVec );
float[] newData = new float[4];
newVec.get( newData );
super.put( element, newData );
before[vertexIndex] = vec;
after[vertexIndex] = newVec;
break;
}
case NORMAL:
{
Vector3f vec = new Vector3f( data );
normalMatrix.transform( vec );
float[] newData = new float[4];
vec.get( newData );
super.put( element, newData );
break;
}
default:
super.put( element, data );
break;
}
elementIndex++;
if( elementIndex == getVertexFormat().getElementCount() )
{
vertexIndex++;
elementIndex = 0;
}
}
public boolean areNormalsInverted()
{
Vector3f temp1 = new Vector3f(), temp2 = new Vector3f();
Vector3f crossBefore = new Vector3f(), crossAfter = new Vector3f();
// Determine what cross product we expect to have
temp1.sub( before[1], before[0] );
temp2.sub( before[1], before[2] );
crossBefore.cross( temp1, temp2 );
normalMatrix.transform( crossBefore );
// And determine what cross product we actually have
temp1.sub( after[1], after[0] );
temp2.sub( after[1], after[2] );
crossAfter.cross( temp1, temp2 );
// If the angle between expected and actual cross product is greater than
// pi/2 radians then we will need to reorder our quads.
return Math.abs( crossBefore.angle( crossAfter ) ) >= Math.PI / 2;
}
}
/**
* A vertex consumer which is capable of building {@link BakedQuad}s.
*
* Equivalent to {@link net.minecraftforge.client.model.pipeline.UnpackedBakedQuad.Builder} but more memory
* efficient.
*
* This also provides the ability to swap vertices through {@link #swap(int, int)} to allow reordering.
*/
private static final class BakedQuadBuilder implements IVertexConsumer
{
private final VertexFormat format;
private final int[] vertexData;
private int vertexIndex = 0, elementIndex = 0;
private Direction orientation;
private int quadTint;
private boolean diffuse;
private TextureAtlasSprite texture;
private BakedQuadBuilder( VertexFormat format )
{
this.format = format;
vertexData = new int[format.getSize()];
}
@Nonnull
@Override
public VertexFormat getVertexFormat()
{
return format;
}
@Override
public void setQuadTint( int tint )
{
quadTint = tint;
}
@Override
public void setQuadOrientation( @Nonnull Direction orientation )
{
this.orientation = orientation;
}
@Override
public void setApplyDiffuseLighting( boolean diffuse )
{
this.diffuse = diffuse;
}
@Override
public void setTexture( @Nonnull TextureAtlasSprite texture )
{
this.texture = texture;
}
@Override
public void put( int element, @Nonnull float... data )
{
LightUtil.pack( data, vertexData, format, vertexIndex, element );
elementIndex++;
if( elementIndex == getVertexFormat().getElementCount() )
{
vertexIndex++;
elementIndex = 0;
}
}
public void swap( int a, int b )
{
int length = vertexData.length / 4;
for( int i = 0; i < length; i++ )
{
int temp = vertexData[a * length + i];
vertexData[a * length + i] = vertexData[b * length + i];
vertexData[b * length + i] = temp;
}
}
public BakedQuad build()
{
if( elementIndex != 0 || vertexIndex != 4 )
{
throw new IllegalStateException( "Got an unexpected number of elements/vertices" );
}
if( texture == null )
{
throw new IllegalStateException( "Texture has not been set" );
}
return new BakedQuad( vertexData, quadTint, orientation, texture, diffuse, format );
}
return copy;
}
}

View File

@@ -7,23 +7,30 @@
package dan200.computercraft.client.render;
import com.mojang.blaze3d.platform.GlStateManager;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.lwjgl.opengl.GL11;
import java.util.EnumSet;
import static net.minecraft.util.math.Direction.*;
import static net.minecraft.util.Direction.*;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
public final class MonitorHighlightRenderer
{
private static final float EXPAND = 0.002f;
@@ -32,18 +39,22 @@ public final class MonitorHighlightRenderer
{
}
public static boolean drawHighlight( Camera camera, BlockHitResult hit )
@SubscribeEvent
public static void drawHighlight( DrawBlockHighlightEvent event )
{
MinecraftClient mc = MinecraftClient.getInstance();
if( mc.player.isSneaking() ) return false;
if( event.getTarget().getType() != RayTraceResult.Type.BLOCK || event.getInfo().getRenderViewEntity().isSneaking() )
{
return;
}
BlockPos pos = hit.getBlockPos();
World world = mc.world;
World world = event.getInfo().getRenderViewEntity().getEntityWorld();
BlockPos pos = ((BlockRayTraceResult) event.getTarget()).getPos();
BlockEntity tile = world.getBlockEntity( pos );
if( !(tile instanceof TileMonitor) ) return false;
TileEntity tile = world.getTileEntity( pos );
if( !(tile instanceof TileMonitor) ) return;
TileMonitor monitor = (TileMonitor) tile;
event.setCanceled( true );
// Determine which sides are part of the external faces of the monitor, and so which need to be rendered.
EnumSet<Direction> faces = EnumSet.allOf( Direction.class );
@@ -56,16 +67,17 @@ public final class MonitorHighlightRenderer
GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate( GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO );
GlStateManager.lineWidth( Math.max( 2.5F, (float) mc.window.getFramebufferWidth() / 1920.0F * 2.5F ) );
GlStateManager.lineWidth( Math.max( 2.5F, (float) Minecraft.getInstance().mainWindow.getFramebufferWidth() / 1920.0F * 2.5F ) );
GlStateManager.disableTexture();
GlStateManager.depthMask( false );
GlStateManager.pushMatrix();
GlStateManager.translated( pos.getX() - camera.getPos().getX(), pos.getY() - camera.getPos().getY(), pos.getZ() - camera.getPos().getZ() );
Vec3d cameraPos = event.getInfo().getProjectedView();
GlStateManager.translated( pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ() );
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
buffer.begin( GL11.GL_LINES, VertexFormats.POSITION_COLOR );
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR );
// I wish I could think of a better way to do this
if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, 0, 0, 0, UP );
@@ -87,8 +99,6 @@ public final class MonitorHighlightRenderer
GlStateManager.depthMask( true );
GlStateManager.enableTexture();
GlStateManager.disableBlend();
return true;
}
private static void line( BufferBuilder buffer, int x, int y, int z, Direction direction )
@@ -97,11 +107,11 @@ public final class MonitorHighlightRenderer
double minY = y == 0 ? -EXPAND : 1 + EXPAND;
double minZ = z == 0 ? -EXPAND : 1 + EXPAND;
buffer.vertex( minX, minY, minZ ).color( 0, 0, 0, 0.4f ).next();
buffer.vertex(
minX + direction.getOffsetX() * (1 + EXPAND * 2),
minY + direction.getOffsetY() * (1 + EXPAND * 2),
minZ + direction.getOffsetZ() * (1 + EXPAND * 2)
).color( 0, 0, 0, 0.4f ).next();
buffer.pos( minX, minY, minZ ).color( 0, 0, 0, 0.4f ).endVertex();
buffer.pos(
minX + direction.getXOffset() * (1 + EXPAND * 2),
minY + direction.getYOffset() * (1 + EXPAND * 2),
minZ + direction.getZOffset() * (1 + EXPAND * 2)
).color( 0, 0, 0, 0.4f ).endVertex();
}
}

View File

@@ -12,11 +12,11 @@ import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.TextBuffer;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.util.Identifier;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
@@ -24,36 +24,36 @@ import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAG
public final class PrintoutRenderer
{
private static final Identifier BG = new Identifier( "computercraft", "textures/gui/printout.png" );
private static final ResourceLocation BG = new ResourceLocation( "computercraft", "textures/gui/printout.png" );
private static final double BG_SIZE = 256.0;
/**
* Width of a page
* Width of a page.
*/
public static final int X_SIZE = 172;
/**
* Height of a page
* Height of a page.
*/
public static final int Y_SIZE = 209;
/**
* Padding between the left and right of a page and the text
* Padding between the left and right of a page and the text.
*/
public static final int X_TEXT_MARGIN = 13;
/**
* Padding between the top and bottom of a page and the text
* Padding between the top and bottom of a page and the text.
*/
public static final int Y_TEXT_MARGIN = 11;
/**
* Width of the extra page texture
* Width of the extra page texture.
*/
private static final int X_FOLD_SIZE = 12;
/**
* Size of the leather cover
* Size of the leather cover.
*/
public static final int COVER_SIZE = 12;
@@ -94,11 +94,11 @@ public final class PrintoutRenderer
GlStateManager.enableTexture();
GlStateManager.blendFuncSeparate( SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ZERO );
MinecraftClient.getInstance().getTextureManager().bindTexture( BG );
Minecraft.getInstance().getTextureManager().bindTexture( BG );
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_UV );
BufferBuilder buffer = tessellator.getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX );
int leftPages = page;
int rightPages = pages - page - 1;
@@ -159,18 +159,18 @@ public final class PrintoutRenderer
private static void drawTexture( BufferBuilder buffer, double x, double y, double z, double u, double v, double width, double height )
{
buffer.vertex( x, y + height, z ).texture( u / BG_SIZE, (v + height) / BG_SIZE ).next();
buffer.vertex( x + width, y + height, z ).texture( (u + width) / BG_SIZE, (v + height) / BG_SIZE ).next();
buffer.vertex( x + width, y, z ).texture( (u + width) / BG_SIZE, v / BG_SIZE ).next();
buffer.vertex( x, y, z ).texture( u / BG_SIZE, v / BG_SIZE ).next();
buffer.pos( x, y + height, z ).tex( u / BG_SIZE, (v + height) / BG_SIZE ).endVertex();
buffer.pos( x + width, y + height, z ).tex( (u + width) / BG_SIZE, (v + height) / BG_SIZE ).endVertex();
buffer.pos( x + width, y, z ).tex( (u + width) / BG_SIZE, v / BG_SIZE ).endVertex();
buffer.pos( x, y, z ).tex( u / BG_SIZE, v / BG_SIZE ).endVertex();
}
private static void drawTexture( BufferBuilder buffer, double x, double y, double z, double width, double height, double u, double v, double tWidth, double tHeight )
{
buffer.vertex( x, y + height, z ).texture( u / BG_SIZE, (v + tHeight) / BG_SIZE ).next();
buffer.vertex( x + width, y + height, z ).texture( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ).next();
buffer.vertex( x + width, y, z ).texture( (u + tWidth) / BG_SIZE, v / BG_SIZE ).next();
buffer.vertex( x, y, z ).texture( u / BG_SIZE, v / BG_SIZE ).next();
buffer.pos( x, y + height, z ).tex( u / BG_SIZE, (v + tHeight) / BG_SIZE ).endVertex();
buffer.pos( x + width, y + height, z ).tex( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ).endVertex();
buffer.pos( x + width, y, z ).tex( (u + tWidth) / BG_SIZE, v / BG_SIZE ).endVertex();
buffer.pos( x, y, z ).tex( u / BG_SIZE, v / BG_SIZE ).endVertex();
}
public static double offsetAt( int page )

View File

@@ -15,18 +15,22 @@ import dan200.computercraft.shared.peripheral.modem.wired.TileCable;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
import org.lwjgl.opengl.GL11;
import javax.annotation.Nonnull;
@@ -35,10 +39,19 @@ import java.util.Random;
/**
* Render breaking animation only over part of a {@link TileCable}.
*/
public class TileEntityCableRenderer extends BlockEntityRenderer<TileCable>
public class TileEntityCableRenderer extends TileEntityRenderer<TileCable>
{
private static final ResourceLocation[] DESTROY_STAGES = new ResourceLocation[10];
private static final Random random = new Random();
static
{
for( int i = 0; i < DESTROY_STAGES.length; i++ )
{
DESTROY_STAGES[i] = new ResourceLocation( "block/destroy_stage_" + i );
}
}
@Override
public void render( @Nonnull TileCable te, double x, double y, double z, float partialTicks, int destroyStage )
{
@@ -46,40 +59,54 @@ public class TileEntityCableRenderer extends BlockEntityRenderer<TileCable>
BlockPos pos = te.getPos();
MinecraftClient mc = MinecraftClient.getInstance();
Minecraft mc = Minecraft.getInstance();
HitResult hit = mc.hitResult;
if( !(hit instanceof BlockHitResult) || !((BlockHitResult) hit).getBlockPos().equals( pos ) ) return;
RayTraceResult hit = mc.objectMouseOver;
if( hit == null || hit.getType() != RayTraceResult.Type.BLOCK || !((BlockRayTraceResult) hit).getPos().equals( pos ) )
{
return;
}
World world = te.getWorld();
BlockState state = te.getCachedState();
BlockState state = world.getBlockState( pos );
Block block = state.getBlock();
if( block != ComputerCraft.Blocks.cable ) return;
state = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) )
state = WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getHitVec().subtract( pos.getX(), pos.getY(), pos.getZ() ) )
? block.getDefaultState().with( BlockCable.MODEM, state.get( BlockCable.MODEM ) )
: state.with( BlockCable.MODEM, CableModemVariant.None );
BakedModel model = mc.getBlockRenderManager().getModel( state );
IBakedModel model = mc.getBlockRendererDispatcher().getModelForState( state );
preRenderDamagedBlocks();
BufferBuilder buffer = Tessellator.getInstance().getBufferBuilder();
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_UV_LMAP );
buffer.setOffset( x - pos.getX(), y - pos.getY(), z - pos.getZ() );
buffer.disableColor();
ForgeHooksClient.setRenderLayer( block.getRenderLayer() );
// See BlockRendererDispatcher#renderBlockDamage
Sprite breakingTexture = mc.getSpriteAtlas().getSprite( DESTROY_STAGE_TEXTURES[destroyStage] );
mc.getBlockRenderManager().tesselateDamage( state, pos, breakingTexture, world );
TextureAtlasSprite breakingTexture = mc.getTextureMap().getSprite( DESTROY_STAGES[destroyStage] );
buffer.setOffset( 0, 0, 0 );
BufferBuilder buffer = Tessellator.getInstance().getBuffer();
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.BLOCK );
buffer.setTranslation( x - pos.getX(), y - pos.getY(), z - pos.getZ() );
buffer.noColor();
mc.getBlockRendererDispatcher().getBlockModelRenderer().renderModel(
world,
ForgeHooksClient.getDamageModel( model, breakingTexture, state, world, pos, 0 ),
state, pos, buffer, true, random, state.getPositionRandom( pos ), EmptyModelData.INSTANCE
);
ForgeHooksClient.setRenderLayer( BlockRenderLayer.SOLID );
buffer.setTranslation( 0, 0, 0 );
Tessellator.getInstance().draw();
postRenderDamagedBlocks();
}
/**
* Set up the state for rendering block-breaking progress.
*
* @see WorldRenderer#preRenderDamagedBlocks()
*/
private void preRenderDamagedBlocks()
@@ -98,6 +125,8 @@ public class TileEntityCableRenderer extends BlockEntityRenderer<TileCable>
}
/**
* Tear down the state for rendering block-breaking progress.
*
* @see WorldRenderer#postRenderDamagedBlocks()
*/
private void postRenderDamagedBlocks()

View File

@@ -17,16 +17,16 @@ import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.Palette;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import org.lwjgl.opengl.GL11;
public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
{
@Override
public void render( TileMonitor tileEntity, double posX, double posY, double posZ, float f, int i )
@@ -66,7 +66,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
// Determine orientation
Direction dir = origin.getDirection();
Direction front = origin.getFront();
float yaw = dir.asRotation();
float yaw = dir.getHorizontalAngle();
float pitch = DirectionUtil.toPitchAngle( front );
GlStateManager.pushMatrix();
@@ -85,9 +85,9 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
// Get renderers
MinecraftClient mc = MinecraftClient.getInstance();
Minecraft mc = Minecraft.getInstance();
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder renderer = tessellator.getBufferBuilder();
BufferBuilder renderer = tessellator.getBuffer();
// Get terminal
boolean redraw = originTerminal.pollTerminalChanged();
@@ -251,11 +251,11 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
final float g = colour.getG();
final float b = colour.getB();
renderer.begin( GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION_UV_COLOR );
renderer.vertex( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).texture( 0.0, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).texture( 0.0, 1.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).texture( 1.0, 0.0 ).color( r, g, b, 1.0f ).next();
renderer.vertex( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).texture( 1.0, 1.0 ).color( r, g, b, 1.0f ).next();
renderer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_COLOR );
renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 0.0, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 0.0, 1.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0D ).tex( 1.0, 0.0 ).color( r, g, b, 1.0f ).endVertex();
renderer.pos( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).tex( 1.0, 1.0 ).color( r, g, b, 1.0f ).endVertex();
tessellator.draw();
}
}
@@ -271,11 +271,11 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
try
{
mc.getTextureManager().bindTexture( FixedWidthFontRenderer.BACKGROUND );
renderer.begin( GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION );
renderer.vertex( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).next();
renderer.vertex( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).next();
renderer.vertex( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).next();
renderer.vertex( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).next();
renderer.begin( GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION );
renderer.pos( -TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
renderer.pos( -TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
renderer.pos( xSize + TileMonitor.RENDER_MARGIN, TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
renderer.pos( xSize + TileMonitor.RENDER_MARGIN, -ySize - TileMonitor.RENDER_MARGIN, 0.0 ).endVertex();
tessellator.draw();
}
finally

View File

@@ -15,36 +15,39 @@ import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.*;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.util.Identifier;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.Direction;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ModelManager;
import net.minecraft.client.renderer.model.ModelResourceLocation;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.pipeline.LightUtil;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import javax.vecmath.Matrix4f;
import java.nio.FloatBuffer;
import java.util.List;
import java.util.Random;
public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
public class TileEntityTurtleRenderer extends TileEntityRenderer<TileTurtle>
{
private static final ModelIdentifier NORMAL_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_normal", "inventory" );
private static final ModelIdentifier ADVANCED_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_advanced", "inventory" );
private static final ModelIdentifier COLOUR_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_colour", "inventory" );
private static final ModelIdentifier ELF_OVERLAY_MODEL = new ModelIdentifier( "computercraft:turtle_elf_overlay", "inventory" );
private static final FloatBuffer matrixBuf = BufferUtils.createFloatBuffer( 16 );
private static final ModelResourceLocation NORMAL_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_normal", "inventory" );
private static final ModelResourceLocation ADVANCED_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_advanced", "inventory" );
private static final ModelResourceLocation COLOUR_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_colour", "inventory" );
private static final ModelResourceLocation ELF_OVERLAY_MODEL = new ModelResourceLocation( "computercraft:turtle_elf_overlay", "inventory" );
@Override
public void render( TileTurtle tileEntity, double posX, double posY, double posZ, float partialTicks, int breaking )
@@ -52,7 +55,7 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
if( tileEntity != null ) renderTurtleAt( tileEntity, posX, posY, posZ, partialTicks );
}
public static ModelIdentifier getTurtleModel( ComputerFamily family, boolean coloured )
public static ModelResourceLocation getTurtleModel( ComputerFamily family, boolean coloured )
{
switch( family )
{
@@ -64,11 +67,11 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
}
}
public static ModelIdentifier getTurtleOverlayModel( Identifier overlay, boolean christmas )
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
{
if( overlay != null )
{
return new ModelIdentifier( overlay, "inventory" );
return new ModelResourceLocation( overlay, "inventory" );
}
else if( christmas )
{
@@ -84,21 +87,22 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
{
// Render the label
String label = turtle.createProxy().getLabel();
if( label != null && renderManager.hitResult != null && renderManager.hitResult instanceof BlockHitResult && turtle.getPos().equals( ((BlockHitResult) renderManager.hitResult).getBlockPos() ) )
RayTraceResult hit = rendererDispatcher.cameraHitResult;
if( label != null && hit.getType() == RayTraceResult.Type.BLOCK && turtle.getPos().equals( ((BlockRayTraceResult) hit).getPos() ) )
{
disableLightmap( true );
GameRenderer.renderFloatingText(
setLightmapDisabled( true );
GameRenderer.drawNameplate(
getFontRenderer(), label,
(float) posX + 0.5F, (float) posY + 1.2F, (float) posZ + 0.5F, 0,
renderManager.cameraEntity.getYaw(), renderManager.cameraEntity.getPitch(), false
rendererDispatcher.renderInfo.getYaw(), rendererDispatcher.renderInfo.getPitch(), false
);
disableLightmap( false );
setLightmapDisabled( false );
}
GlStateManager.pushMatrix();
try
{
BlockState state = turtle.getCachedState();
BlockState state = turtle.getBlockState();
// Setup the transform
Vec3d offset = turtle.getRenderOffset( partialTicks );
float yaw = turtle.getRenderYaw( partialTicks );
@@ -110,18 +114,18 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
{
// Flip the model and swap the cull face as winding order will have changed.
GlStateManager.scalef( 1.0f, -1.0f, 1.0f );
GlStateManager.cullFace( GlStateManager.FaceSides.FRONT );
GlStateManager.cullFace( GlStateManager.CullFace.FRONT );
}
GlStateManager.translatef( -0.5f, -0.5f, -0.5f );
// Render the turtle
int colour = turtle.getColour();
ComputerFamily family = turtle.getFamily();
Identifier overlay = turtle.getOverlay();
ResourceLocation overlay = turtle.getOverlay();
renderModel( state, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
// Render the overlay
ModelIdentifier overlayModel = getTurtleOverlayModel(
ModelResourceLocation overlayModel = getTurtleOverlayModel(
overlay,
HolidayUtil.getCurrentHoliday() == Holiday.Christmas
);
@@ -148,7 +152,7 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
finally
{
GlStateManager.popMatrix();
GlStateManager.cullFace( GlStateManager.FaceSides.BACK );
GlStateManager.cullFace( GlStateManager.CullFace.BACK );
}
}
@@ -165,21 +169,12 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
GlStateManager.rotatef( -toolAngle, 1.0f, 0.0f, 0.0f );
GlStateManager.translatef( 0.0f, -0.5f, -0.5f );
Pair<BakedModel, Matrix4f> pair = upgrade.getModel( turtle.getAccess(), side );
Pair<IBakedModel, Matrix4f> pair = upgrade.getModel( turtle.getAccess(), side );
if( pair != null )
{
if( pair.getRight() != null )
{
matrixBuf.clear();
float[] t = new float[4];
for( int i = 0; i < 4; i++ )
{
pair.getRight().getColumn( i, t );
matrixBuf.put( t );
}
matrixBuf.flip();
GlStateManager.multMatrix( matrixBuf );
ForgeHooksClient.multiplyCurrentGlMatrix( pair.getRight() );
}
if( pair.getLeft() != null )
{
@@ -194,43 +189,48 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
}
}
private void renderModel( BlockState state, ModelIdentifier modelLocation, int[] tints )
private void renderModel( BlockState state, ModelResourceLocation modelLocation, int[] tints )
{
MinecraftClient mc = MinecraftClient.getInstance();
BakedModelManager modelManager = mc.getItemRenderer().getModels().getModelManager();
Minecraft mc = Minecraft.getInstance();
ModelManager modelManager = mc.getItemRenderer().getItemModelMesher().getModelManager();
renderModel( state, modelManager.getModel( modelLocation ), tints );
}
private void renderModel( BlockState state, BakedModel model, int[] tints )
private void renderModel( BlockState state, IBakedModel model, int[] tints )
{
Random random = new Random( 0 );
Tessellator tessellator = Tessellator.getInstance();
renderManager.textureManager.bindTexture( SpriteAtlasTexture.BLOCK_ATLAS_TEX );
renderQuads( tessellator, model.getQuads( state, null, random ), tints );
rendererDispatcher.textureManager.bindTexture( AtlasTexture.LOCATION_BLOCKS_TEXTURE );
renderQuads( tessellator, model.getQuads( state, null, random, EmptyModelData.INSTANCE ), tints );
for( Direction facing : DirectionUtil.FACINGS )
{
renderQuads( tessellator, model.getQuads( state, facing, random ), tints );
renderQuads( tessellator, model.getQuads( state, facing, random, EmptyModelData.INSTANCE ), tints );
}
}
private static void renderQuads( Tessellator tessellator, List<BakedQuad> quads, int[] tints )
{
BufferBuilder buffer = tessellator.getBufferBuilder();
VertexFormat format = VertexFormats.POSITION_COLOR_UV_NORMAL;
BufferBuilder buffer = tessellator.getBuffer();
VertexFormat format = DefaultVertexFormats.ITEM;
buffer.begin( GL11.GL_QUADS, format );
for( BakedQuad quad : quads )
{
int colour = 0xFFFFFFFF;
if( quad.hasColor() && tints != null )
VertexFormat quadFormat = quad.getFormat();
if( quadFormat != format )
{
int index = quad.getColorIndex();
tessellator.draw();
format = quadFormat;
buffer.begin( GL11.GL_QUADS, format );
}
int colour = 0xFFFFFFFF;
if( quad.hasTintIndex() && tints != null )
{
int index = quad.getTintIndex();
if( index >= 0 && index < tints.length ) colour = tints[index] | 0xFF000000;
}
buffer.putVertexData( quad.getVertexData() );
buffer.setQuadColor( colour );
Vec3i normal = quad.getFace().getVector();
buffer.postNormal( normal.getX(), normal.getY(), normal.getZ() );
LightUtil.renderQuadColor( buffer, quad, colour );
}
tessellator.draw();
}

View File

@@ -7,26 +7,28 @@
package dan200.computercraft.client.render;
import dan200.computercraft.ComputerCraft;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelBakeSettings;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.Identifier;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.IUnbakedModel;
import net.minecraft.client.renderer.model.ModelBakery;
import net.minecraft.client.renderer.texture.ISprite;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.ICustomModelLoader;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
public final class TurtleModelLoader
public final class TurtleModelLoader implements ICustomModelLoader
{
private static final Identifier NORMAL_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_normal" );
private static final Identifier ADVANCED_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_advanced" );
private static final Identifier COLOUR_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_colour" );
private static final ResourceLocation NORMAL_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_normal" );
private static final ResourceLocation ADVANCED_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_advanced" );
private static final ResourceLocation COLOUR_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_colour" );
public static final TurtleModelLoader INSTANCE = new TurtleModelLoader();
@@ -34,14 +36,21 @@ public final class TurtleModelLoader
{
}
public boolean accepts( @Nonnull Identifier name )
@Override
public void onResourceManagerReload( @Nonnull IResourceManager manager )
{
}
@Override
public boolean accepts( @Nonnull ResourceLocation name )
{
return name.getNamespace().equals( ComputerCraft.MOD_ID )
&& (name.getPath().equals( "item/turtle_normal" ) || name.getPath().equals( "item/turtle_advanced" ));
}
@Nonnull
public UnbakedModel loadModel( @Nonnull Identifier name )
@Override
public IUnbakedModel loadModel( @Nonnull ResourceLocation name )
{
if( name.getNamespace().equals( ComputerCraft.MOD_ID ) )
{
@@ -57,35 +66,38 @@ public final class TurtleModelLoader
throw new IllegalStateException( "Loader does not accept " + name );
}
private static final class TurtleModel implements UnbakedModel
private static final class TurtleModel implements IUnbakedModel
{
private final Identifier family;
private final ResourceLocation family;
private TurtleModel( Identifier family ) {this.family = family;}
private TurtleModel( ResourceLocation family )
{
this.family = family;
}
@Nonnull
@Override
public Collection<Identifier> getModelDependencies()
public Collection<ResourceLocation> getDependencies()
{
return Arrays.asList( family, COLOUR_TURTLE_MODEL );
}
@Nonnull
@Override
public Collection<Identifier> getTextureDependencies( @Nonnull Function<Identifier, UnbakedModel> modelGetter, @Nonnull Set<String> missingTextureErrors )
public Collection<ResourceLocation> getTextures( @Nonnull Function<ResourceLocation, IUnbakedModel> modelGetter, @Nonnull Set<String> missingTextureErrors )
{
return getModelDependencies().stream()
.flatMap( x -> modelGetter.apply( x ).getTextureDependencies( modelGetter, missingTextureErrors ).stream() )
return getDependencies().stream()
.flatMap( x -> modelGetter.apply( x ).getTextures( modelGetter, missingTextureErrors ).stream() )
.collect( Collectors.toSet() );
}
@Nullable
@Nonnull
@Override
public BakedModel bake( @Nonnull ModelLoader loader, @Nonnull Function<Identifier, Sprite> spriteGetter, @Nonnull ModelBakeSettings state )
public IBakedModel bake( @Nonnull ModelBakery bakery, @Nonnull Function<ResourceLocation, TextureAtlasSprite> spriteGetter, @Nonnull ISprite sprite, @Nonnull VertexFormat format )
{
return new TurtleSmartItemModel(
loader.getOrLoadModel( family ).bake( loader, spriteGetter, state ),
loader.getOrLoadModel( COLOUR_TURTLE_MODEL ).bake( loader, spriteGetter, state )
bakery.getBakedModel( family, sprite, spriteGetter, format ),
bakery.getBakedModel( COLOUR_TURTLE_MODEL, sprite, spriteGetter, format )
);
}
}

View File

@@ -7,30 +7,31 @@
package dan200.computercraft.client.render;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelItemPropertyOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.util.math.Direction;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ItemOverrideList;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.Direction;
import net.minecraftforge.client.model.data.EmptyModelData;
import net.minecraftforge.client.model.data.IModelData;
import javax.annotation.Nonnull;
import javax.vecmath.Matrix4f;
import java.util.*;
public class TurtleMultiModel implements BakedModel
public class TurtleMultiModel implements IBakedModel
{
private final BakedModel m_baseModel;
private final BakedModel m_overlayModel;
private final IBakedModel m_baseModel;
private final IBakedModel m_overlayModel;
private final Matrix4f m_generalTransform;
private final BakedModel m_leftUpgradeModel;
private final IBakedModel m_leftUpgradeModel;
private final Matrix4f m_leftUpgradeTransform;
private final BakedModel m_rightUpgradeModel;
private final IBakedModel m_rightUpgradeModel;
private final Matrix4f m_rightUpgradeTransform;
private List<BakedQuad> m_generalQuads = null;
private Map<Direction, List<BakedQuad>> m_faceQuads = new EnumMap<>( Direction.class );
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, Matrix4f generalTransform, BakedModel leftUpgradeModel, Matrix4f leftUpgradeTransform, BakedModel rightUpgradeModel, Matrix4f rightUpgradeTransform )
public TurtleMultiModel( IBakedModel baseModel, IBakedModel overlayModel, Matrix4f generalTransform, IBakedModel leftUpgradeModel, Matrix4f leftUpgradeTransform, IBakedModel rightUpgradeModel, Matrix4f rightUpgradeTransform )
{
// Get the models
m_baseModel = baseModel;
@@ -44,7 +45,15 @@ public class TurtleMultiModel implements BakedModel
@Nonnull
@Override
@Deprecated
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand )
{
return getQuads( state, side, rand, EmptyModelData.INSTANCE );
}
@Nonnull
@Override
public List<BakedQuad> getQuads( BlockState state, Direction side, @Nonnull Random rand, @Nonnull IModelData data )
{
if( side != null )
{
@@ -61,10 +70,10 @@ public class TurtleMultiModel implements BakedModel
private List<BakedQuad> buildQuads( BlockState state, Direction side, Random rand )
{
ArrayList<BakedQuad> quads = new ArrayList<>();
ModelTransformer.transformQuadsTo( quads, m_baseModel.getQuads( state, side, rand ), m_generalTransform );
ModelTransformer.transformQuadsTo( quads, m_baseModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), m_generalTransform );
if( m_overlayModel != null )
{
ModelTransformer.transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand ), m_generalTransform );
ModelTransformer.transformQuadsTo( quads, m_overlayModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), m_generalTransform );
}
if( m_leftUpgradeModel != null )
{
@@ -74,7 +83,7 @@ public class TurtleMultiModel implements BakedModel
upgradeTransform = new Matrix4f( m_generalTransform );
upgradeTransform.mul( m_leftUpgradeTransform );
}
ModelTransformer.transformQuadsTo( quads, m_leftUpgradeModel.getQuads( state, side, rand ), upgradeTransform );
ModelTransformer.transformQuadsTo( quads, m_leftUpgradeModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
}
if( m_rightUpgradeModel != null )
{
@@ -84,45 +93,50 @@ public class TurtleMultiModel implements BakedModel
upgradeTransform = new Matrix4f( m_generalTransform );
upgradeTransform.mul( m_rightUpgradeTransform );
}
ModelTransformer.transformQuadsTo( quads, m_rightUpgradeModel.getQuads( state, side, rand ), upgradeTransform );
ModelTransformer.transformQuadsTo( quads, m_rightUpgradeModel.getQuads( state, side, rand, EmptyModelData.INSTANCE ), upgradeTransform );
}
quads.trimToSize();
return quads;
}
@Override
public boolean useAmbientOcclusion()
public boolean isAmbientOcclusion()
{
return m_baseModel.useAmbientOcclusion();
return m_baseModel.isAmbientOcclusion();
}
@Override
public boolean hasDepthInGui()
public boolean isGui3d()
{
return m_baseModel.hasDepthInGui();
return m_baseModel.isGui3d();
}
@Override
public boolean isBuiltin()
public boolean isBuiltInRenderer()
{
return m_baseModel.isBuiltin();
return m_baseModel.isBuiltInRenderer();
}
@Nonnull
@Override
public Sprite getSprite()
@Deprecated
public TextureAtlasSprite getParticleTexture()
{
return m_baseModel.getSprite();
return m_baseModel.getParticleTexture();
}
@Nonnull
@Override
public ModelTransformation getTransformation()
@Deprecated
public net.minecraft.client.renderer.model.ItemCameraTransforms getItemCameraTransforms()
{
return m_baseModel.getTransformation();
return m_baseModel.getItemCameraTransforms();
}
@Nonnull
@Override
public ModelItemPropertyOverrideList getItemPropertyOverrides()
public ItemOverrideList getOverrides()
{
return ModelItemPropertyOverrideList.EMPTY;
return ItemOverrideList.EMPTY;
}
}

View File

@@ -13,30 +13,25 @@ import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.client.render.model.BakedQuad;
import net.minecraft.client.render.model.json.ModelItemPropertyOverrideList;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.model.*;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.client.model.data.IModelData;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.vecmath.Matrix4f;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
public class TurtleSmartItemModel implements BakedModel
public class TurtleSmartItemModel implements IBakedModel
{
private static final Matrix4f s_identity, s_flip;
@@ -56,11 +51,11 @@ public class TurtleSmartItemModel implements BakedModel
final boolean m_colour;
final ITurtleUpgrade m_leftUpgrade;
final ITurtleUpgrade m_rightUpgrade;
final Identifier m_overlay;
final ResourceLocation m_overlay;
final boolean m_christmas;
final boolean m_flip;
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas, boolean flip )
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, ResourceLocation overlay, boolean christmas, boolean flip )
{
m_colour = colour;
m_leftUpgrade = leftUpgrade;
@@ -100,35 +95,35 @@ public class TurtleSmartItemModel implements BakedModel
}
}
private final BakedModel familyModel;
private final BakedModel colourModel;
private final IBakedModel familyModel;
private final IBakedModel colourModel;
private HashMap<TurtleModelCombination, BakedModel> m_cachedModels;
private ModelItemPropertyOverrideList m_overrides;
private HashMap<TurtleModelCombination, IBakedModel> m_cachedModels;
private ItemOverrideList m_overrides;
public TurtleSmartItemModel( BakedModel familyModel, BakedModel colourModel )
public TurtleSmartItemModel( IBakedModel familyModel, IBakedModel colourModel )
{
this.familyModel = familyModel;
this.colourModel = colourModel;
m_cachedModels = new HashMap<>();
m_overrides = new ModelItemPropertyOverrideList( null, null, null, Collections.emptyList() )
m_overrides = new ItemOverrideList()
{
@Nonnull
@Override
public BakedModel apply( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable LivingEntity entity )
public IBakedModel getModelWithOverrides( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable LivingEntity entity )
{
ItemTurtle turtle = (ItemTurtle) stack.getItem();
int colour = turtle.getColour( stack );
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.Left );
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.Right );
Identifier overlay = turtle.getOverlay( stack );
ResourceLocation overlay = turtle.getOverlay( stack );
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( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
BakedModel model = m_cachedModels.get( combo );
IBakedModel model = m_cachedModels.get( combo );
if( model == null ) m_cachedModels.put( combo, model = buildModel( combo ) );
return model;
}
@@ -137,22 +132,22 @@ public class TurtleSmartItemModel implements BakedModel
@Nonnull
@Override
public ModelItemPropertyOverrideList getItemPropertyOverrides()
public ItemOverrideList getOverrides()
{
return m_overrides;
}
private BakedModel buildModel( TurtleModelCombination combo )
private IBakedModel buildModel( TurtleModelCombination combo )
{
MinecraftClient mc = MinecraftClient.getInstance();
BakedModelManager modelManager = mc.getItemRenderer().getModels().getModelManager();
ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_overlay, combo.m_christmas );
Minecraft mc = Minecraft.getInstance();
ModelManager modelManager = mc.getItemRenderer().getItemModelMesher().getModelManager();
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.m_overlay, combo.m_christmas );
BakedModel baseModel = combo.m_colour ? colourModel : familyModel;
BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null;
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<BakedModel, Matrix4f> leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
Pair<BakedModel, Matrix4f> rightModel = combo.m_rightUpgrade != null ? combo.m_rightUpgrade.getModel( null, TurtleSide.Right ) : null;
Pair<IBakedModel, Matrix4f> leftModel = combo.m_leftUpgrade != null ? combo.m_leftUpgrade.getModel( null, TurtleSide.Left ) : null;
Pair<IBakedModel, Matrix4f> rightModel = combo.m_rightUpgrade != null ? combo.m_rightUpgrade.getModel( null, TurtleSide.Right ) : null;
if( leftModel != null && rightModel != null )
{
return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel.getLeft(), leftModel.getRight(), rightModel.getLeft(), rightModel.getRight() );
@@ -174,38 +169,51 @@ public class TurtleSmartItemModel implements BakedModel
@Nonnull
@Override
@Deprecated
public List<BakedQuad> getQuads( BlockState state, Direction facing, Random rand )
public List<BakedQuad> getQuads( BlockState state, Direction facing, @Nonnull Random rand )
{
return familyModel.getQuads( state, facing, rand );
}
@Nonnull
@Override
public boolean useAmbientOcclusion()
@Deprecated
public List<BakedQuad> getQuads( BlockState state, Direction facing, @Nonnull Random rand, @Nonnull IModelData data )
{
return familyModel.useAmbientOcclusion();
return familyModel.getQuads( state, facing, rand, data );
}
@Override
public boolean hasDepthInGui()
public boolean isAmbientOcclusion()
{
return familyModel.hasDepthInGui();
return familyModel.isAmbientOcclusion();
}
@Override
public boolean isBuiltin()
public boolean isGui3d()
{
return familyModel.isBuiltin();
return familyModel.isGui3d();
}
@Override
public Sprite getSprite()
public boolean isBuiltInRenderer()
{
return null;
return familyModel.isBuiltInRenderer();
}
@Nonnull
@Override
public ModelTransformation getTransformation()
@Deprecated
public TextureAtlasSprite getParticleTexture()
{
return familyModel.getTransformation();
return familyModel.getParticleTexture();
}
@Nonnull
@Override
@Deprecated
public ItemCameraTransforms getItemCameraTransforms()
{
return familyModel.getItemCameraTransforms();
}
}

View File

@@ -160,7 +160,7 @@ public class AddressPredicate
}
/**
* Determine whether the given address matches a series of patterns
* Determine whether the given address matches a series of patterns.
*
* @param address The address to check.
* @return Whether it matches any of these patterns.

View File

@@ -13,256 +13,106 @@ import javax.annotation.Nullable;
import java.util.Map;
/**
* Various helpers for arguments
* A stub for any mods which depended on this version of the argument helper.
*
* @deprecated Use {@link dan200.computercraft.api.lua.ArgumentHelper}.
*/
@Deprecated
public final class ArgumentHelper
{
private ArgumentHelper()
{
throw new IllegalStateException( "Cannot instantiate singleton " + getClass().getName() );
}
@Nonnull
public static String getType( @Nullable Object type )
{
if( type == null ) return "nil";
if( type instanceof String ) return "string";
if( type instanceof Boolean ) return "boolean";
if( type instanceof Number ) return "number";
if( type instanceof Map ) return "table";
Class<?> klass = type.getClass();
if( klass.isArray() )
{
StringBuilder name = new StringBuilder();
while( klass.isArray() )
{
name.append( "[]" );
klass = klass.getComponentType();
}
name.insert( 0, klass.getName() );
return name.toString();
}
else
{
return klass.getName();
}
return dan200.computercraft.api.lua.ArgumentHelper.getType( type );
}
@Nonnull
public static LuaException badArgument( int index, @Nonnull String expected, @Nullable Object actual )
{
return badArgument( index, expected, getType( actual ) );
return dan200.computercraft.api.lua.ArgumentHelper.badArgumentOf( index, expected, actual );
}
@Nonnull
public static LuaException badArgument( int index, @Nonnull String expected, @Nonnull String actual )
{
return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" );
return dan200.computercraft.api.lua.ArgumentHelper.badArgument( index, expected, actual );
}
public static double getNumber( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "number", "nil" );
Object value = args[index];
if( value instanceof Number )
{
return ((Number) value).doubleValue();
}
else
{
throw badArgument( index, "number", value );
}
return dan200.computercraft.api.lua.ArgumentHelper.getDouble( args, index );
}
public static int getInt( @Nonnull Object[] args, int index ) throws LuaException
{
return (int) getLong( args, index );
return dan200.computercraft.api.lua.ArgumentHelper.getInt( args, index );
}
public static long getLong( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "number", "nil" );
Object value = args[index];
if( value instanceof Number )
{
return checkReal( index, (Number) value ).longValue();
}
else
{
throw badArgument( index, "number", value );
}
return dan200.computercraft.api.lua.ArgumentHelper.getLong( args, index );
}
public static double getReal( @Nonnull Object[] args, int index ) throws LuaException
{
return checkReal( index, getNumber( args, index ) );
return dan200.computercraft.api.lua.ArgumentHelper.getFiniteDouble( args, index );
}
public static boolean getBoolean( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "boolean", "nil" );
Object value = args[index];
if( value instanceof Boolean )
{
return (Boolean) value;
}
else
{
throw badArgument( index, "boolean", value );
}
return dan200.computercraft.api.lua.ArgumentHelper.getBoolean( args, index );
}
@Nonnull
public static String getString( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "string", "nil" );
Object value = args[index];
if( value instanceof String )
{
return (String) value;
}
else
{
throw badArgument( index, "string", value );
}
return dan200.computercraft.api.lua.ArgumentHelper.getString( args, index );
}
@SuppressWarnings( "unchecked" )
@Nonnull
@SuppressWarnings( "unchecked" )
public static Map<Object, Object> getTable( @Nonnull Object[] args, int index ) throws LuaException
{
if( index >= args.length ) throw badArgument( index, "table", "nil" );
Object value = args[index];
if( value instanceof Map )
{
return (Map<Object, Object>) value;
}
else
{
throw badArgument( index, "table", value );
}
return (Map<Object, Object>) dan200.computercraft.api.lua.ArgumentHelper.getTable( args, index );
}
public static double optNumber( @Nonnull Object[] args, int index, double def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null )
{
return def;
}
else if( value instanceof Number )
{
return ((Number) value).doubleValue();
}
else
{
throw badArgument( index, "number", value );
}
return dan200.computercraft.api.lua.ArgumentHelper.optDouble( args, index, def );
}
public static int optInt( @Nonnull Object[] args, int index, int def ) throws LuaException
{
return (int) optLong( args, index, def );
return dan200.computercraft.api.lua.ArgumentHelper.optInt( args, index, def );
}
public static long optLong( @Nonnull Object[] args, int index, long def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null )
{
return def;
}
else if( value instanceof Number )
{
return checkReal( index, (Number) value ).longValue();
}
else
{
throw badArgument( index, "number", value );
}
return dan200.computercraft.api.lua.ArgumentHelper.optLong( args, index, def );
}
public static double optReal( @Nonnull Object[] args, int index, double def ) throws LuaException
{
return checkReal( index, optNumber( args, index, def ) );
return dan200.computercraft.api.lua.ArgumentHelper.optFiniteDouble( args, index, def );
}
public static boolean optBoolean( @Nonnull Object[] args, int index, boolean def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null )
{
return def;
}
else if( value instanceof Boolean )
{
return (Boolean) value;
}
else
{
throw badArgument( index, "boolean", value );
}
return dan200.computercraft.api.lua.ArgumentHelper.optBoolean( args, index, def );
}
public static String optString( @Nonnull Object[] args, int index, String def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null )
{
return def;
}
else if( value instanceof String )
{
return (String) value;
}
else
{
throw badArgument( index, "string", value );
}
return dan200.computercraft.api.lua.ArgumentHelper.optString( args, index, def );
}
@SuppressWarnings( "unchecked" )
public static Map<Object, Object> optTable( @Nonnull Object[] args, int index, Map<Object, Object> def ) throws LuaException
{
Object value = index < args.length ? args[index] : null;
if( value == null )
{
return def;
}
else if( value instanceof Map )
{
return (Map<Object, Object>) value;
}
else
{
throw badArgument( index, "table", value );
}
}
private static Number checkReal( int index, Number value ) throws LuaException
{
checkReal( index, value.doubleValue() );
return value;
}
private static double checkReal( int index, double value ) throws LuaException
{
if( Double.isNaN( value ) )
{
throw badArgument( index, "number", "nan" );
}
else if( value == Double.POSITIVE_INFINITY )
{
throw badArgument( index, "number", "inf" );
}
else if( value == Double.NEGATIVE_INFINITY )
{
throw badArgument( index, "number", "-inf" );
}
else
{
return value;
}
return (Map<Object, Object>) dan200.computercraft.api.lua.ArgumentHelper.optTable( args, index, def );
}
}

View File

@@ -27,7 +27,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
import static dan200.computercraft.api.lua.ArgumentHelper.getString;
public class FSAPI implements ILuaAPI
{
@@ -43,9 +43,7 @@ public class FSAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"fs"
};
return new String[] { "fs" };
}
@Override

View File

@@ -23,7 +23,7 @@ import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import static dan200.computercraft.core.apis.ArgumentHelper.*;
import static dan200.computercraft.api.lua.ArgumentHelper.*;
import static dan200.computercraft.core.apis.TableHelper.*;
public class HTTPAPI implements ILuaAPI
@@ -42,9 +42,7 @@ public class HTTPAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"http"
};
return new String[] { "http" };
}
@Override
@@ -83,6 +81,7 @@ public class HTTPAPI implements ILuaAPI
}
@Override
@SuppressWarnings( "resource" )
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
{
switch( method )
@@ -90,12 +89,12 @@ public class HTTPAPI implements ILuaAPI
case 0: // request
{
String address, postString, requestMethod;
Map<Object, Object> headerTable;
Map<?, ?> headerTable;
boolean binary, redirect;
if( args.length >= 1 && args[0] instanceof Map )
{
Map<?, ?> options = (Map) args[0];
Map<?, ?> options = (Map<?, ?>) args[0];
address = getStringField( options, "url" );
postString = optStringField( options, "body", null );
headerTable = optTableField( options, "headers", Collections.emptyMap() );
@@ -135,7 +134,6 @@ public class HTTPAPI implements ILuaAPI
try
{
URI uri = HttpRequest.checkUri( address );
HttpRequest request = new HttpRequest( requests, m_apiEnvironment, address, postString, headers, binary, redirect );
long requestBody = request.body().readableBytes() + HttpRequest.getHeaderSize( headers );
@@ -174,7 +172,7 @@ public class HTTPAPI implements ILuaAPI
case 2: // websocket
{
String address = getString( args, 0 );
Map<Object, Object> headerTbl = optTable( args, 1, Collections.emptyMap() );
Map<?, ?> headerTbl = optTable( args, 1, Collections.emptyMap() );
if( !ComputerCraft.http_websocket_enable )
{

View File

@@ -10,6 +10,7 @@ package dan200.computercraft.core.apis;
* This exists purely to ensure binary compatibility.
*
* @see dan200.computercraft.api.lua.ILuaAPI
* @deprecated Use the version in the public API. Only exists for compatibility with CCEmuX.
*/
@Deprecated
public interface ILuaAPI extends dan200.computercraft.api.lua.ILuaAPI

View File

@@ -19,7 +19,7 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;
import static dan200.computercraft.core.apis.ArgumentHelper.*;
import static dan200.computercraft.api.lua.ArgumentHelper.*;
public class OSAPI implements ILuaAPI
{
@@ -36,9 +36,9 @@ public class OSAPI implements ILuaAPI
private static class Timer
{
public int m_ticksLeft;
int m_ticksLeft;
public Timer( int ticksLeft )
Timer( int ticksLeft )
{
m_ticksLeft = ticksLeft;
}
@@ -46,10 +46,10 @@ public class OSAPI implements ILuaAPI
private static class Alarm implements Comparable<Alarm>
{
public final double m_time;
public final int m_day;
final double m_time;
final int m_day;
public Alarm( double time, int day )
Alarm( double time, int day )
{
m_time = time;
m_day = day;
@@ -78,9 +78,7 @@ public class OSAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"os"
};
return new String[] { "os" };
}
@Override
@@ -231,7 +229,7 @@ public class OSAPI implements ILuaAPI
case 1:
{
// startTimer
double timer = getReal( args, 0 );
double timer = getFiniteDouble( args, 0 );
synchronized( m_timers )
{
m_timers.put( m_nextTimerToken, new Timer( (int) Math.round( timer / 0.05 ) ) );
@@ -241,7 +239,7 @@ public class OSAPI implements ILuaAPI
case 2:
{
// setAlarm
double time = getReal( args, 0 );
double time = getFiniteDouble( args, 0 );
if( time < 0.0 || time >= 24.0 )
{
throw new LuaException( "Number out of range" );
@@ -385,9 +383,7 @@ public class OSAPI implements ILuaAPI
// Get in-game epoch
synchronized( m_alarms )
{
return new Object[] {
m_day * 86400000 + (int) (m_time * 3600000.0f)
};
return new Object[] { m_day * 86400000 + (int) (m_time * 3600000.0f) };
}
default:
throw new LuaException( "Unsupported operation" );
@@ -401,7 +397,6 @@ public class OSAPI implements ILuaAPI
Instant instant = Instant.ofEpochSecond( time );
ZonedDateTime date;
ZoneOffset offset;
boolean isDst;
if( format.startsWith( "!" ) )
{
offset = ZoneOffset.UTC;

View File

@@ -22,7 +22,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static dan200.computercraft.core.apis.ArgumentHelper.getString;
import static dan200.computercraft.api.lua.ArgumentHelper.getString;
public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener
{
@@ -36,7 +36,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
private Map<String, Integer> m_methodMap;
private boolean m_attached;
public PeripheralWrapper( IPeripheral peripheral, String side )
PeripheralWrapper( IPeripheral peripheral, String side )
{
super( m_environment );
m_side = side;
@@ -282,9 +282,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
@Override
public String[] getNames()
{
return new String[] {
"peripheral"
};
return new String[] { "peripheral" };
}
@Override
@@ -326,7 +324,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
"isPresent",
"getType",
"getMethods",
"call"
"call",
};
}
@@ -356,7 +354,6 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
ComputerSide side = ComputerSide.valueOfInsensitive( getString( args, 0 ) );
if( side != null )
{
String type = null;
synchronized( m_peripherals )
{
PeripheralWrapper p = m_peripherals[side.ordinal()];

View File

@@ -15,7 +15,7 @@ import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.Map;
import static dan200.computercraft.core.apis.ArgumentHelper.*;
import static dan200.computercraft.api.lua.ArgumentHelper.*;
public class RedstoneAPI implements ILuaAPI
{
@@ -29,9 +29,7 @@ public class RedstoneAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"rs", "redstone"
};
return new String[] { "rs", "redstone" };
}
@Nonnull

View File

@@ -6,14 +6,17 @@
package dan200.computercraft.core.apis;
import dan200.computercraft.api.lua.ArgumentHelper;
import dan200.computercraft.api.lua.LuaException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import static dan200.computercraft.api.lua.ArgumentHelper.getNumericType;
/**
* Various helpers for tables
* Various helpers for tables.
*/
public final class TableHelper
{
@@ -200,21 +203,7 @@ public final class TableHelper
private static double checkReal( @Nonnull String key, double value ) throws LuaException
{
if( Double.isNaN( value ) )
{
throw badKey( key, "number", "nan" );
}
else if( value == Double.POSITIVE_INFINITY )
{
throw badKey( key, "number", "inf" );
}
else if( value == Double.NEGATIVE_INFINITY )
{
throw badKey( key, "number", "-inf" );
}
else
{
return value;
}
if( !Double.isFinite( value ) ) throw badKey( key, "number", getNumericType( value ) );
return value;
}
}

View File

@@ -17,7 +17,7 @@ import org.apache.commons.lang3.ArrayUtils;
import javax.annotation.Nonnull;
import static dan200.computercraft.core.apis.ArgumentHelper.*;
import static dan200.computercraft.api.lua.ArgumentHelper.*;
public class TermAPI implements ILuaAPI
{
@@ -33,9 +33,7 @@ public class TermAPI implements ILuaAPI
@Override
public String[] getNames()
{
return new String[] {
"term"
};
return new String[] { "term" };
}
@Nonnull
@@ -89,9 +87,7 @@ public class TermAPI implements ILuaAPI
public static Object[] encodeColour( int colour ) throws LuaException
{
return new Object[] {
1 << colour
};
return new Object[] { 1 << colour };
}
public static void setColour( Terminal terminal, int colour, double r, double g, double b )
@@ -246,9 +242,9 @@ public class TermAPI implements ILuaAPI
}
else
{
double r = getReal( args, 1 );
double g = getReal( args, 2 );
double b = getReal( args, 3 );
double r = getFiniteDouble( args, 1 );
double g = getFiniteDouble( args, 2 );
double b = getFiniteDouble( args, 3 );
setColour( m_terminal, colour, r, g, b );
}
return null;

View File

@@ -21,8 +21,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static dan200.computercraft.core.apis.ArgumentHelper.getInt;
import static dan200.computercraft.core.apis.ArgumentHelper.optBoolean;
import static dan200.computercraft.api.lua.ArgumentHelper.getInt;
import static dan200.computercraft.api.lua.ArgumentHelper.optBoolean;
public class BinaryReadableHandle extends HandleGeneric
{
@@ -212,6 +212,7 @@ public class BinaryReadableHandle extends HandleGeneric
}
}
case 3: // close
checkOpen();
close();
return null;
case 4: // seek

View File

@@ -7,9 +7,9 @@
package dan200.computercraft.core.apis.handles;
import com.google.common.collect.ObjectArrays;
import dan200.computercraft.api.lua.ArgumentHelper;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.core.apis.ArgumentHelper;
import dan200.computercraft.shared.util.StringUtil;
import javax.annotation.Nonnull;
@@ -73,7 +73,7 @@ public class BinaryWritableHandle extends HandleGeneric
}
else
{
throw ArgumentHelper.badArgument( 0, "string or number", args.length > 0 ? args[0] : null );
throw ArgumentHelper.badArgumentOf( 0, "string or number", args.length > 0 ? args[0] : null );
}
return null;
}
@@ -95,6 +95,7 @@ public class BinaryWritableHandle extends HandleGeneric
return null;
}
case 2: // close
checkOpen();
close();
return null;
case 3: // seek

View File

@@ -20,8 +20,8 @@ import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import static dan200.computercraft.core.apis.ArgumentHelper.optBoolean;
import static dan200.computercraft.core.apis.ArgumentHelper.optInt;
import static dan200.computercraft.api.lua.ArgumentHelper.optBoolean;
import static dan200.computercraft.api.lua.ArgumentHelper.optInt;
public class EncodedReadableHandle extends HandleGeneric
{
@@ -152,6 +152,7 @@ public class EncodedReadableHandle extends HandleGeneric
return null;
}
case 3: // close
checkOpen();
close();
return null;
default:

View File

@@ -93,6 +93,7 @@ public class EncodedWritableHandle extends HandleGeneric
return null;
}
case 3: // close
checkOpen();
close();
return null;
default:

View File

@@ -16,8 +16,8 @@ import java.io.IOException;
import java.nio.channels.Channel;
import java.nio.channels.SeekableByteChannel;
import static dan200.computercraft.core.apis.ArgumentHelper.optLong;
import static dan200.computercraft.core.apis.ArgumentHelper.optString;
import static dan200.computercraft.api.lua.ArgumentHelper.optLong;
import static dan200.computercraft.api.lua.ArgumentHelper.optString;
public abstract class HandleGeneric implements ILuaObject
{
@@ -37,12 +37,17 @@ public abstract class HandleGeneric implements ILuaObject
protected final void close()
{
m_open = false;
IoUtil.closeQuietly( m_closable );
m_closable = null;
Closeable closeable = m_closable;
if( closeable != null )
{
IoUtil.closeQuietly( closeable );
m_closable = null;
}
}
/**
* Shared implementation for various file handle types
* Shared implementation for various file handle types.
*
* @param channel The channel to seek in
* @param args The Lua arguments to process, like Lua's {@code file:seek}.

View File

@@ -99,7 +99,7 @@ public final class NetworkUtils
}
/**
* Checks a host is allowed
* Checks a host is allowed.
*
* @param host The domain to check against
* @throws HTTPRequestException If the host is not permitted.

View File

@@ -20,6 +20,8 @@ import java.util.function.Consumer;
/**
* A holder for one or more resources, with a lifetime.
*
* @param <T> The type of this resource. Should be the class extending from {@link Resource}.
*/
public abstract class Resource<T extends Resource<T>> implements Closeable
{
@@ -42,8 +44,9 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
}
/**
* Checks if this has been cancelled. If so, it'll clean up any
* existing resources and cancel any pending futures.
* Checks if this has been cancelled. If so, it'll clean up any existing resources and cancel any pending futures.
*
* @return Whether this resource has been closed.
*/
public final boolean checkClosed()
{
@@ -72,13 +75,15 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
*/
protected void dispose()
{
@SuppressWarnings( "unchecked" ) T thisT = (T) this;
@SuppressWarnings( "unchecked" )
T thisT = (T) this;
limiter.release( thisT );
}
/**
* Create a {@link WeakReference} which will close {@code this} when collected.
*
* @param <R> The object we are wrapping in a reference.
* @param object The object to reference to
* @return The weak reference.
*/
@@ -95,7 +100,8 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
public boolean queue( Consumer<T> task )
{
@SuppressWarnings( "unchecked" ) T thisT = (T) this;
@SuppressWarnings( "unchecked" )
T thisT = (T) this;
return limiter.queue( thisT, () -> task.accept( thisT ) );
}

View File

@@ -14,6 +14,8 @@ import java.util.function.Supplier;
/**
* A collection of {@link Resource}s, with an upper bound on capacity.
*
* @param <T> The type of the resource this group manages.
*/
public class ResourceGroup<T extends Resource<T>>
{

View File

@@ -12,6 +12,8 @@ import java.util.function.Supplier;
/**
* A {@link ResourceGroup} which will queue items when the group at capacity.
*
* @param <T> The type of the resource this queue manages.
*/
public class ResourceQueue<T extends Resource<T>> extends ResourceGroup<T>
{

View File

@@ -40,7 +40,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Represents one or more
* Represents an in-progress HTTP request.
*/
public class HttpRequest extends Resource<HttpRequest>
{

View File

@@ -226,7 +226,11 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
}
/**
* Determine the redirect from this response
* Determine the redirect from this response.
*
* @param status The status of the HTTP response.
* @param headers The headers of the HTTP response.
* @return The URI to redirect to, or {@code null} if no redirect should occur.
*/
private URI getRedirect( HttpResponseStatus status, HttpHeaders headers )
{

View File

@@ -23,7 +23,7 @@ import javax.annotation.Nullable;
import java.io.Closeable;
import java.util.Arrays;
import static dan200.computercraft.core.apis.ArgumentHelper.optBoolean;
import static dan200.computercraft.api.lua.ArgumentHelper.optBoolean;
import static dan200.computercraft.core.apis.http.websocket.Websocket.CLOSE_EVENT;
import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT;

View File

@@ -56,9 +56,6 @@ final class ComputerExecutor
{
private static final int QUEUE_LIMIT = 256;
private static IMount romMount;
private static final Object romMountLock = new Object();
private final Computer computer;
private final List<ILuaAPI> apis = new ArrayList<>();
final TimeoutState timeout = new TimeoutState();
@@ -268,7 +265,7 @@ final class ComputerExecutor
}
/**
* Queue an event if the computer is on
* Queue an event if the computer is on.
*
* @param event The event's name
* @param args The event's arguments
@@ -329,16 +326,10 @@ final class ComputerExecutor
private IMount getRomMount()
{
if( romMount != null ) return romMount;
synchronized( romMountLock )
{
if( romMount != null ) return romMount;
return romMount = computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" );
}
return computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" );
}
IWritableMount getRootMount()
private IWritableMount getRootMount()
{
if( rootMount == null )
{

View File

@@ -6,11 +6,13 @@
package dan200.computercraft.core.computer;
import net.minecraft.util.Direction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* A side on a computer. Unlike {@link net.minecraft.util.EnumFacing}, this is relative to the direction the computer is
* A side on a computer. Unlike {@link Direction}, this is relative to the direction the computer is
* facing..
*/
public enum ComputerSide
@@ -30,7 +32,10 @@ public enum ComputerSide
private final String name;
ComputerSide( String name ) {this.name = name;}
ComputerSide( String name )
{
this.name = name;
}
@Nonnull
public static ComputerSide valueOf( int side )

Some files were not shown because too many files have changed in this diff Show More