MightyPirates / OpenComputers

Home of the OpenComputers mod for Minecraft.
https://oc.cil.li
Other
1.59k stars 433 forks source link

autorun.lua no longer autoboot, what's replacing it? #2390

Closed LemADEC closed 7 years ago

LemADEC commented 7 years ago

As of OC 1.7.10-1.6.0-beta.1, autorun.lua scripts provided by my mod were automatically executed. As of OC 1.7.10-1.6.2, the same scripts are no longer loaded when starting the computer. However, they'll run if I break/place my block. From a LUA console, filesystem autorun is reported as enabled (filesystem.isAutorunEnabled() returns true). If I "install" them, they are copied in / but still won't autorun. Same goes if I copy them in /home.

How are we supposed to have autoboot now with OpenOS? Is there a wiki on how the boot sequence works?

payonel commented 7 years ago

I am planning on making a wiki page discussing this topic in detail And I expected to continue to improve this experience for users in openos (i'm definitely actively working on openos still) duplicate of #2171 and i will close this ticket - but, let's discuss your specific issue here a bit. can you paste the code here that your autorun is trying to do? Thanks

LemADEC commented 7 years ago

My tile entities are providing a filesystem which includes an autorun.lua (boot program) and a WarpDriveCommon.lua (common library). Those LUA scripts are providing the user interface for my tile entities. The library serves as a common base for different blocks but also as a wrapper between CC and OC.

Here's a simplified version of the TileEntity code:

Node     OC_node = null;
boolean  OC_addedToNetwork = false;
ManagedEnvironment OC_fileSystem = null;

public void updateEntity() {
    super.updateEntity();

    if (!OC_addedToNetwork && OC_enable) {
        OC_addedToNetwork = true;
        Network.joinOrCreateNetwork(this);
    }
}

@Override
public void validate() {
    // deferred constructor so the derived class can finish it's initialization first
    if (OC_node == null) {
        OC_constructor();
    }
    super.validate();
}

public void invalidate() {
    if (OC_node != null) {
        OC_node.remove();
        OC_node = null;
    }
    super.invalidate();
}

public void onChunkUnload() {
    if (OC_node != null) {
        OC_node.remove();
        OC_node = null;
    }
    super.onChunkUnload();
}

public void readFromNBT(NBTTagCompound tag) {
    super.readFromNBT(tag);
    if (OC_node == null) {
        OC_constructor();
    }
    if (OC_node != null && OC_node.host() == this) {
        OC_node.load(tag.getCompoundTag("oc:node"));
    }
    if (OC_fileSystem != null && OC_fileSystem.node() != null) {
        OC_fileSystem.node().load(tag.getCompoundTag("oc:fs"));
    }
}

public void writeToNBT(NBTTagCompound tag) {
    super.writeToNBT(tag);
    if (OC_node != null && OC_node.host() == this) {
        final NBTTagCompound nbtNode = new NBTTagCompound();
        OC_node.save(nbtNode);
        tag.setTag("oc:node", nbtNode);
    }
    if (OC_fileSystem != null && OC_fileSystem.node() != null) {
        final NBTTagCompound nbtFileSystem = new NBTTagCompound();
        OC_fileSystem.node().save(nbtFileSystem);
        tag.setTag("oc:fs", nbtFileSystem);
    }
}

private void OC_constructor() {
    final String OC_path = "/assets/warpdrive/lua.OpenComputers/" + peripheralName;
    OC_node = Network.newNode(this, Visibility.Network).withComponent(peripheralName).create();
    if (OC_node != null) {
        OC_fileSystem = FileSystem.asManagedEnvironment(FileSystem.fromClass(getClass(), "warpdrive", "lua.OpenComputers/" + peripheralName), peripheralName);
        ((Component) OC_fileSystem.node()).setVisibility(Visibility.Network);
    }
}

public Node node() {
    return OC_node;
}

public void onConnect(Node node) {
    if (node.host() instanceof Context) {
        if (OC_fileSystem != null) {
            node.connect(OC_fileSystem.node());
        }
    }
}

public void onDisconnect(Node node) {
    if (OC_fileSystem != null) {
        if (node.host() instanceof Context) {
            // Disconnecting from a single computer
            node.disconnect(OC_fileSystem.node());
        } else if (node == OC_node) {
            // Disconnecting from the network
            OC_fileSystem.node().remove();
        }
    }
}

public void onMessage(Message message) {
    // nothing special
}

Here's what my autorun.lua looks like:

package.loaded.warpdriveCommons = nil 
local w = require("warpdriveCommons")

... (declaring all local variables and functions) ...

----------- Boot sequence

w.page_setEndText(" Home (0), Laser batteries (1), Laser stations (2)")
w.page_register('0', connections_page, nil)
w.page_register('1', laser_battery_page, laser_battery_key)
w.page_register('2', laser_station_page, laser_station_key)
laser_register()

w.boot()
w.run()
w.close()

and here's the warpdriveCommons library:

local w

-- APIs
local component = require("component")
local computer = require("computer")
local term = require("term")
local event = require("event")
local fs = require("filesystem")
local serialization = require("serialization")

... (declaring all local variables and functions) ...

local function close()
  w.clear(colors.white, colors.black)
  for key, handlers in pairs(device_handlers) do
    w.writeLn("Closing " .. key)
    if handlers.unregister ~= nil then
      handlers.unregister(key)
    end
  end

  w.clear(colors.white, colors.black)
  w.setCursorPos(1, 1)
  w.writeLn("Program closed")
  w.writeLn("Type reboot to return to home page")
end

w = {
... declaring all exported methods ...
  device_get = device_get,
  device_getMonitors = device_getMonitors,
  device_register = device_register,
  boot = boot,
  run = run,
  close = close,
}

return w, local_env

OpenOS autorun has several issues impacting me here: 1- autorun only executes when placing a block, not at boot. This is a regression with no documented replacement to "autoboot" my scripts. 2- when executing autorun, the require() statement can't find a library in the same folder as the autorun script. We're probably missing a 'change current' folder before running autorun or some changes in the require() statement.

I've tried using the 'install' command but the autoboot still fails and the library seems to be in an invalid location. Also it forces me to duplicate my library with all my tile entities, which is prone to errors.

SaphireLattice commented 7 years ago

Magical filesystems built into the machine are kinda outdated. Better to use a craftable floppy disk with everything, for consistency.

On Thu, May 18, 2017, 15:26 LemADEC notifications@github.com wrote:

My tile entities are providing a filesystem which includes an autorun.lua (boot program) and a WarpDriveCommon.lua (common library). Those LUA scripts are providing the user interface for my tile entities. The library serves as a common base for different blocks but also as a wrapper between CC and OC.

Here's a simplified version of the TileEntity code:

Node OC_node = null;boolean OC_addedToNetwork = false;ManagedEnvironment OC_fileSystem = null; public void updateEntity() { super.updateEntity();

if (!OC_addedToNetwork && OC_enable) { OC_addedToNetwork = true; Network.joinOrCreateNetwork(this); } } @Overridepublic void validate() { // deferred constructor so the derived class can finish it's initialization first if (OC_node == null) { OC_constructor(); } super.validate(); } public void invalidate() { if (OC_node != null) { OC_node.remove(); OC_node = null; } super.invalidate(); } public void onChunkUnload() { if (OC_node != null) { OC_node.remove(); OC_node = null; } super.onChunkUnload(); } public void readFromNBT(NBTTagCompound tag) { super.readFromNBT(tag); if (OC_node == null) { OC_constructor(); } if (OC_node != null && OC_node.host() == this) { OC_node.load(tag.getCompoundTag("oc:node")); } if (OC_fileSystem != null && OC_fileSystem.node() != null) { OC_fileSystem.node().load(tag.getCompoundTag("oc:fs")); } } public void writeToNBT(NBTTagCompound tag) { super.writeToNBT(tag); if (OC_node != null && OC_node.host() == this) { final NBTTagCompound nbtNode = new NBTTagCompound(); OC_node.save(nbtNode); tag.setTag("oc:node", nbtNode); } if (OC_fileSystem != null && OC_fileSystem.node() != null) { final NBTTagCompound nbtFileSystem = new NBTTagCompound(); OC_fileSystem.node().save(nbtFileSystem); tag.setTag("oc:fs", nbtFileSystem); } } private void OC_constructor() { final String OC_path = "/assets/warpdrive/lua.OpenComputers/" + peripheralName; OC_node = Network.newNode(this, Visibility.Network).withComponent(peripheralName).create(); if (OC_node != null) { OC_fileSystem = FileSystem.asManagedEnvironment(FileSystem.fromClass(getClass(), "warpdrive", "lua.OpenComputers/" + peripheralName), peripheralName); ((Component) OC_fileSystem.node()).setVisibility(Visibility.Network); } } public Node node() { return OC_node; } public void onConnect(Node node) { if (node.host() instanceof Context) { if (OC_fileSystem != null) { node.connect(OC_fileSystem.node()); } } } public void onDisconnect(Node node) { if (OC_fileSystem != null) { if (node.host() instanceof Context) { // Disconnecting from a single computer node.disconnect(OC_fileSystem.node()); } else if (node == OC_node) { // Disconnecting from the network OC_fileSystem.node().remove(); } } } public void onMessage(Message message) { // nothing special }

Here's what my autorun.lua looks like:

package.loaded.warpdriveCommons = nil local w = require("warpdriveCommons") ... (declaring all local variables and functions) ... ----------- Boot sequence

w.page_setEndText(" Home (0), Laser batteries (1), Laser stations (2)") w.page_register('0', connections_page, nil) w.page_register('1', laser_battery_page, laser_battery_key) w.page_register('2', laser_station_page, laser_station_key)laser_register()

w.boot() w.run() w.close()

and here's the warpdriveCommons library:

local w -- APIslocal component = require("component")local computer = require("computer")local term = require("term")local event = require("event")local fs = require("filesystem")local serialization = require("serialization") ... (declaring all local variables and functions) ... local function close() w.clear(colors.white, colors.black) for key, handlers in pairs(device_handlers) do w.writeLn("Closing " .. key) if handlers.unregister ~= nil then handlers.unregister(key) end end

w.clear(colors.white, colors.black) w.setCursorPos(1, 1) w.writeLn("Program closed") w.writeLn("Type reboot to return to home page")end

w = {... declaring all exported methods ... device_get = device_get, device_getMonitors = device_getMonitors, device_register = device_register, boot = boot, run = run, close = close, } return w, local_env

OpenOS autorun has several issues impacting me here: 1- autorun only executes when placing a block, not at boot. This is a regression with no documented replacement to "autoboot" my scripts. 2- when executing autorun, the require() statement can't find a library in the same folder as the autorun script. We're probably missing a 'change current' folder before running autorun or some changes in the require() statement.

I've tried using the 'install' command but the autoboot still fails and the library seems to be in an invalid location. Also it forces me to duplicate my library with all my tile entities, which is prone to errors.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/MightyPirates/OpenComputers/issues/2390#issuecomment-302336518, or mute the thread https://github.com/notifications/unsubscribe-auth/AEFMuPNMFZFmg3gmpCsKMciZ9rY4e47Iks5r7ADBgaJpZM4NemKt .

LemADEC commented 7 years ago

Using floppy is outdated. Every hardware nowadays comes with pre-loaded scripts and driver installers.

skyem123 commented 7 years ago

OC is "outdated", that's kinda sorta the whole theme.

I do understand that autorun.lua only running after boot is a breaking change, but it's a tradeoff that I think is a good idea, it avoids the issue of a malicious / crashing autorun of require('computer').shutdown().

What you could do is have the software that's installed onto the computer do only a few tasks:

  1. Check if the hardware with its own FS is there
  2. Load up all the other code from your hardware with its own FS.
  3. (optionally) unmount the integrated hardware FS to look nicer.

What would be good is a way for the install tool to be more flexible, maybe allowing a way to detect if something is already installed...

LemADEC commented 7 years ago

To me, the current autorun approach is only good to hack into another computer or some form of one time execution. A malicious deadlock is easily fixed by connecting the filesystem after booting the OS, so I don't understand why it would be considered a major motivation to change autorun.lua behavior. Since an option was added to disable autorun execution on connection, we could as well have an option to enable it at boot. Maybe even have its default value as a mod configuration for sake of backward compatibility, at least until the feature gets re-implemented in another way.

I've no problem with requiring players to type "install" the first time they connect to the block, especially since it already integrates a menu to choose which filesystem is used as a source. Sadly, it seems to just copy into the root folder, which is not sufficient to make my script "boot" and my library "accessible".

skyem123 commented 7 years ago

The autorun system does feel a bit pointless, to be honest. It might be better if it was more of a request to run a program, so when you were at a shell, it would tell you that an FS wants to run a program, and you could accept it manually.

There is no good way to stop a malicious autorun right after boot other than not running it right after boot. Which is the current state of it, thus making it useless for your usecase...

I am not sure if there is documentation for install, I do know that it copes files over if it sees a certain file in the root of the drive indicating it's a software disk. It copies over everything into the root, so you should have things like usr/bin/runnable_command.lua, usr/lib/library_thing.lua. What I am not sure about is running code on boot, because I haven't tried that myself.

Hopefully this helps a little.

payonel commented 7 years ago

this is a great discussion with some good ideas. i'm working on some hardening for openos currently, but install and autorun-like features is something I understand needs a careful review and nth pass. I'll update this ticket when I have a report of my progress. Ideas and questions are welcome, though I won't be working on this area of the code for a couple of weeks.

thiakil commented 7 years ago

@LemADEC I don't quite understand what your autorun does; does it display anything on the computer? If so that seems like a bad idea.

Sadly, it seems to just copy into the root folder, which is not sufficient to make my script "boot" and my library "accessible".

Do you have the correct folder structure on your mounted FS? It sounds like in your fs you just have the lua files. They should be in usr/lib/ and usr/bin (if user runnable).

With installing it, you could also add a boot script to /boot/ that does what it is you want.

You could also link them like the robot component does, see https://github.com/MightyPirates/OpenComputers/blob/master-MC1.7.10/src/main/resources/assets/opencomputers/lua/component/robot/.autorun.lua

LemADEC commented 7 years ago

install copies the filesystem folder structure, overwriting existing files, aborts if copy fails for whatever reason. That's the good news. On the other end, install appears to have no documentation, no way to run a script during installation, no "append to existing file" (.shrc for example), and no option to manage an existing file (confirm overwrite, rename or abort?). I've made a dirty gradle patch for now so I can mimic the older behavior. Thanks for the help!

@payonel I'm a bit confused that you've closed a ticket while at the same time hope to work on it. May I suggest to keep it open and assign it to you with a "OpenOS" tag? this would be easier to find and a bit more explicit for others users.

SaphireLattice commented 7 years ago

@LemADEC The things that you are asking for are perfect example of what kind of work the install.lua requires. For now such things would require modification to it, or separate program. The second variant is so far the best one, and only requires to add a documentation line asking person to run a something like thing_firsttime. Also I would suggest to look into the OpenPrograms repository. You could use such a repo to distribute up-to-date copies for both OC and CC, and if required, let users to install older versions.

On Fri, May 19, 2017, 14:42 LemADEC notifications@github.com wrote:

install copies the filesystem folder structure, overwriting existing files, aborts if copy fails for whatever reason. That's the good news. On the other end, install appears to have no documentation, no way to run a script during installation, no "append to existing file" (.shrc for example), and no option to manage an existing file (confirm overwrite, rename or abort?). I've made a dirty gradle patch for now so I can mimic the older behavior. Thanks for the help!

@payonel https://github.com/payonel I'm a bit confused that you've closed a ticket while at the same time hope to work on it. May I suggest to keep it open and assign it to you with a "OpenOS" tag? this would be easier to find and a bit more explicit for others users.

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/MightyPirates/OpenComputers/issues/2390#issuecomment-302632920, or mute the thread https://github.com/notifications/unsubscribe-auth/AEFMuFimL4y-BjG43QmfDpVUa8HcP6Srks5r7UfYgaJpZM4NemKt .

LemADEC commented 7 years ago

@thiakil those autorun are full screen GUIs. My library is built upon OpenOS libraries as common API between OC and CC. Notably, it's not a full fledged operating system. image

I did add a folder structure to my filesystem so the install put the files in the right location. Issue arise when my common library needs to copied in all my filesystems. Currently, each block of the same class creates a new read-only filesystem, when in fact it's the same asset folder in my jar. This causes a lot of clutter for players. I found no simple way to address that so far. I'm also not sure if there's an hard limit on the number of filesystems attachments or globally for all CPU instances. Consequently, for now, I'm using gradle to duplicate the library between blocks at compilation time. This way I've only 1 filesystem per block instance instead of 2 (library + startup).

I've considered adding to the /boot/ folder but documentation is fuzzy on the sequencing of all the scripts, so I wasn't sure if some background thingies still needed to run after the boot scripts or whatnot. Also @payonel said it should be considered as 'deprecated' or something.

Checking the robot, I see there's .autorun.lua instead of autorun.lua , that's new to me. This is an interesting approach through I doubt it would work when multiple blocks share the same files like my library: connect A (adds links), connect B (keep links), disconnect A (remove links) then B no longer have the required common library.

LemADEC commented 7 years ago

@dangranos what's plan9k? I've seen references to it but no wiki entries for it. I thought it was an alpha project of sort?

thiakil commented 7 years ago

Personally I would not like a gui to auto popup just because a particular block is placed down next to a computer, but maybe your use case is unique.

Have you tried not recreating the OC_fileSystem in each constructor call? Just attach the existing one. No idea if this works.

LemADEC commented 7 years ago

LUA is the only GUI for my block. You can still terminate/interrupt/exit it and make your own.

I've asked help on filesystem handling through the forum but got no answer so far. I've no simple way to know if my other blocks are still there when the current one gets removed. I've no idea if the OC even supports sharing the same filesystem UUID between computers.

SaphireLattice commented 7 years ago

You can use the IRC (or Discord) in case of needing some real-time support concerning the development. Github works too, but it can be slightly slower. Please keep in mind the timezone difference.

Also yes, autoload of GUI for your bock when it gets attached to the computer is rather... Inconvenient. Imagine what would hairbrush if you accidently put it into the network. Also, such method of losing would force the users to build complicated networks to avoid this autoload script​ triggering on the component connection or computer boot up, if there are more computers than the controller. Yet again I suggest abandoning using built-in filesystem into component and use external method of installation of the program, like the install floppy (honestly the "floppy" is just a name, as it can be renamed and retextured to me anything starting from CD and Flash Memory, ending with"redstone data storage" or something similarly esoteric.) or oppm repo/program. If you're worried that your program will be out of date when the mod is updated for the game, you can always expose a function that states some kind of number used for versioning (like yourblock.getVersion()) and compare it with what the program on computer is made for (on side of the program). Point is, your solution sounds rather inconvinient in long run and hacky.

On Fri, May 19, 2017, 15:32 LemADEC notifications@github.com wrote:

LUA is the only GUI for my block. You can still terminate/interrupt/exit it and make your own.

I've asked help on filesystem handling through the forum but got no answer so far. I've no simple way to know if my other blocks are still there when the current one gets removed. I've no idea if the OC even supports sharing the same filesystem UUID between computers.

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/MightyPirates/OpenComputers/issues/2390#issuecomment-302642999, or mute the thread https://github.com/notifications/unsubscribe-auth/AEFMuD9nl7U59PY-838FY_qQyMDCgtmkks5r7VOUgaJpZM4NemKt .

skyem123 commented 7 years ago

IIRC you can add scripts to run on install.

What I would advice is installing the program and the library as normal, then have the script ask the user if they want the program to start on boot. Make sure to give an option to disable it to avoid frustration.

Also yeah I kinda agree, install isn't documented very well.

Vexatos commented 7 years ago

IIRC you can add scripts to run on install.

Yes, you can.

LemADEC commented 7 years ago

@dangranos I was referring to support on the OC forum. It seems limited to players self-help to me.

CC does the autoboot very nicely: if a startup file already exists on the main computer, then it takes priority. It's plain and simple, doesn't require some commands or editing a configuration file.

More importantly, OC is limiting the GPU load and number of connected devices. The general processing speed limitation makes it 2 to 4 times slower than CC, which means there's no reason to have a large network. While CC isn't perfect, it does allow me to connect 50+ blocks and have a central LUA based GUI for it. With OC, I had to disable features to make it work, very slowly. Those 50 blocks are only a basic setup, players usually wants multiple of it.

To me, adding a floppy means:

@Vexatos that's good to know. I don't quite understand what is this install object being used here. Is there a description of it?

payonel commented 7 years ago

@LemADEC

  1. I closed this ticket because it is, in my mind, a duplicate of #2171 and I definitely didn't anticipate such an enormous discussion on this ticket. I thought you'd have some code samples and we'd be done.
  2. install is young and needs some work. There is some documentation in the man page. install needs more features, needs refinement and improvements. It's on my docket. install was recently made to allow us to stop using what we called "magic filesystems", where our loot disks used autorun to inject libraries and code. Instead, install should be used with our loot disks, and if you are writing software we recommend you use install for it as well. If install doesn't meet your needs and autorun is the better fit, that's up to you, and I should figure out the right way moving forward to support that. install basic functionality is a cp -rxv $source_path $target_path and that's it. When you need something better/different than just a copy, you can define your own .install, which is what oppm does.
  3. I'll reopen this ticket and consider this ticket as an issue for legacy programs that no longer work with autorun
SaphireLattice commented 7 years ago

Hmm. Well, you must have noticed that OC is trying to be rather realistic. While in CC you have practically unlimited power for computing, that is not the case in OC. The GPU "slowness" is a feature. It makes users optimize the programs, to make them work better with less resource usage. If you're redrawing whole screen after pushing a button, it will obviously lag, especially if you set colour on every cell of screen instead of using the built in rectangular set function. OC users just now got used to the floppies used for installing programs. Adding an old mean of using filesystem would be rather confusing in the end.

And the components limit is another realism feature. It requires users to use multiple computers and networking if they need complicated things. If your program requires all of those 50+ components to be connected to computer, you might consider using two different programs for OC and CC, as the architectures are rather different. Or use a combination of two different "backends" that are made specifically for OC or CC and that do all the data processing and machines control, and a simple networked frontend that would use some abstraction library. But please, don't try to use the approach you use on CC with OC (and vice-versa) as that would result in tears for everyone involved.

As for forums.. OC community is centered around GitHub and IRC since the beginning, and forums were made more for those who need them, and for the program sharing. The latter got taken over by previously mentioned OPPM.

Yet again, I recommend using OPPM for distribution of your program. And pleasedon't forcibly autorun the program on the computer that had this block for, again, previously mentioned reasons. That's like if you put a USB modem in computer and it suddenly run a fullscreen app. There's plug-and-play, and there's "I don't want this to pop up all the time, stop it!"

On Sat, May 20, 2017, 03:07 LemADEC notifications@github.com wrote:

@dangranos https://github.com/dangranos I was referring to support on the OC forum. It seems limited to players self-help to me.

CC does the autoboot very nicely: if a startup file already exists on the main computer, then it takes priority. It's plain and simple, doesn't require some commands or editing a configuration file.

More importantly, OC is limiting the GPU load and number of connected devices. The general processing speed limitation makes it 2 to 4 times slower than CC, which means there's no reason to have a large network. While CC isn't perfect, it does allow me to connect 50+ blocks and have a central LUA based GUI for it. With OC, I had to disable features to make it work, very slowly. Those 50 blocks are only a basic setup, players usually wants multiple of it.

To me, adding a floppy means:

  • adding a new crafting step with a new item
  • replacing an existing working feature
  • providing no benefit to players
  • and in the long run, more complicated updating for me and players I understand that OC and CC have different approaches to computer, and I'm fine with it. Yet, I still don't understand why adding crafting and setup steps with floppy makes it easier for players or myself.

@Vexatos https://github.com/vexatos that's good to know. I don't quite understand what is this install object being used here. Is there a description of it?

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/MightyPirates/OpenComputers/issues/2390#issuecomment-302799364, or mute the thread https://github.com/notifications/unsubscribe-auth/AEFMuIhoSK-uAJpmWTMzLpAsMFP9azNmks5r7facgaJpZM4NemKt .

LemADEC commented 7 years ago

@dangranos pushing your ideas without listening to others will get you nowhere.

SaphireLattice commented 7 years ago

@LemADEC Sorry if that feels like pushing the opinion. What do you want as the end result? I mean, what it should look/feel like in the end? Player just grabs the block, computer, slaps them together and it works, or what?

skyem123 commented 7 years ago

@LemADEC, I think it would be better if we discussed this on a more real-time platform, like IRC or Discord, I do want to help work out the best solution here. Personally, I find the fact that you've made a working way to share code between OC and CC quite neat, I tried that once and didn't get far.

I do want to note that the GPU limitations are not arbitrary, every GPU operation sends data to the client. If there were no limitations, someone could be nasty and spam GPU limitations, affecting people with poor connections. It should be possible to optimise stuff to be faster, because I have seen someone get recognisable video playing on OC,

From my understanding, the component limits are pretty arbitrary, however they are there to help provide balance and are one of the main differences of the CPU tiers. Component limits are per in-game computer, and the way to get the most components allowed is a Tier 3 server case with a Tier 3 CPU and many Tier 3 component buses.

I think you have different blocks with different functions, each with their own program, all sharing a common library? I am guessing you are talking about this? I have a suggestion that shouldn't change things too much, maybe you could keep only the blocks that need to have code on them (are they controller blocks?), and make the other blocks send and receive network messages instead of acting as components. It would probably suit if your mod relies on computers a lot!

With regards to the actual auto-start, it would be nice if there was a proper method to have auto-starting scripts / programs that didn't clobber each other somehow, maybe there should be a command to manage what program should be loaded on startup, like a choice between the shell and some other program (like yours).

Anyway, that was my rambling, please talk to us on Discord or IRC, it might help.

LemADEC commented 7 years ago

@skyem123 Indeed, my scripts are mostly the same between CC and OC, just some minor tweaks like text positioning. The rest is handled by the library.

Regarding component limits, let me illustrate with a use case. Initially, I wanted all my 'active' blocks to provide some form of LUA APIs:

A basic laser cannon is made of a laser head with up to 10 laser mediums; it's controlled by a monitor and a laser camera. This single laser cannon requires up to 14 blocks. An advanced cannon consist of adding 4 boosting lasers to the main one, hence up to 44 additional blocks. A ship usually have multiple cannons.

When we've tried initially to integrate OpenComputers, there was more than 100 components detected. We simply couldn't make it work because the mod connects through other blocks. With ComputerCraft, we need to wire every single components, which is a bit bulky but allows to choose which one I connect, so we had only about 30 peripherals to consider. I prefer the OC connection approach, it's just that the component limit those catch up with that connection feature.

From my experience with network messages, they are relatively slow to process. We also had issues with transferring parameter values, so, in practice, those messages are just 'event' and LUA still need to call the block to get the data.

thiakil commented 7 years ago

@LemADEC Sounds to me like you need one block that provides the OC driver, through which then passes the messages / method calls to the other blocks via your API. E.g. Computer Interface (block), or the central controller if one such already exists.

Then, you have 2 options.

LemADEC commented 7 years ago

@thiakil That sounds like components virtualization, while removing the components restriction it makes it a bit more complicated to program on both ends. For example, not all blocks provides the same API and we would no longer use the native "component" wrapper from the computers. StargateTech did that and it doesn't qualify as a major success :). It would make more sense to have a WarpDrive APU or Component Bus that allows to connect 64+ WarpDrive components. Assuming that's not over complicated to code.

The other option is to consider that those blocks are not components at all, but they are just networked "embedded computers". I guess this could be handled by block upgrades, probably major changes to my library and some extensive testing.

thiakil commented 7 years ago

In a way, perhaps "virtualisation." In my understanding you would do it as each multiblock (e.g. each laser cannon) is a component, with the sub-components being userdata objects or integer index addressed.

If you wish to do each block as separate components, I believe component busses with a server are the way to go, as others have mentioned, or using multiple OC computers on a data network.

SaphireLattice commented 7 years ago

Even with buses you'll apparently easily hit the limit of components. From what I understand, the structures in that mod are rather huge, and will obviously have dozens of blocks. And afaik, the computers can't really choose what components they delegate between each other.

On Mon, May 22, 2017, 19:34 Xander notifications@github.com wrote:

In a way, perhaps "virtualisation." In my understanding you would do it as each multiblock (e.g. each laser cannon) is a component, with the sub-components being userdata objects or integer index addressed.

If you wish to do each block as separate components, I believe component busses with a server are the way to go, as others have mentioned, or using multiple OC computers on a data network.

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/MightyPirates/OpenComputers/issues/2390#issuecomment-303087152, or mute the thread https://github.com/notifications/unsubscribe-auth/AEFMuM0QT8RABajQ3gppw82iXzyc5iDPks5r8YDggaJpZM4NemKt .

thiakil commented 7 years ago

You would use a Relay, to create a network of computers which exchange data

SaphireLattice commented 7 years ago

Uh, you didn't understand me. I mean that the whole laser night be composed of more than 44 blocks from what I understood. And at some point this amount will be bigger than what any computer in OC can handle (except for creative ones). Which cannot be fixed in any way on OC side, except for editing config. Which is practically a hack because the laser /shouldn't spam components in first place/, okay? It's a singular structure and it should be controlled as one.

On Mon, May 22, 2017, 20:32 Xander notifications@github.com wrote:

You would use a Relay, to create a network of computers which exchange data

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/MightyPirates/OpenComputers/issues/2390#issuecomment-303101024, or mute the thread https://github.com/notifications/unsubscribe-auth/AEFMuHRbKb2TlqiTde4TI38S5WtlOy-Eks5r8Y6EgaJpZM4NemKt .

thiakil commented 7 years ago

Yeah that was my point about having one control block

LemADEC commented 7 years ago

The latest addition, a particle accelerator was built with a single controller, notably to address the chunkloading issue of such a large structure. So far, it makes the LUA interface a bit more constraint, and more complicated.

It's still a bit unclear in the wiki, but my feeling is that OC Components are supposed to be more internal to the computer, while CC Peripherals are really thought as external blocks. I'm not sure what a pure network approach would be like in term of mod maintenance, player usability and CPU usage.

SaphireLattice commented 7 years ago

OC components are both explicitly external and internal. There's not that much difference between those, except for the fact that internal component only available to one computer and that they aren't a block.

The other option is to consider that those blocks are not components at all, but they are just networked "embedded computers". I guess this could be handled by block upgrades, probably major changes to my library and some extensive testing.

What exactly did you meant by "embedded computers" in there? If you meant to make the whole strcture present itself as a computer and exchange messages... Just no.

As for concerns about "CPU usage", uh... creating dozens of components for a multiblock strcture is hardly CPU efficient, nor it's giving any usability points to the OC users, most of which know programming and would be rather annoyed to find a huge list of components.

The latest addition, a particle accelerator was built with a single controller, notably to address the chunkloading issue of such a large structure. So far, it makes the LUA interface a bit more constraint, and more complicated.

How exactly that constraints the Lua interface? I would like to hear an explaination. Also, the chunkloading issue sounds like somethign that can happen with the laser multiblock that you have mentioned before.

LemADEC commented 7 years ago

Tile entities are already "embedded processors" by nature. It's only about defining how we interact with it. If Components are also intended as external 'Peripherals', and Network isn't an option, then OC design needs some serious revision.

I don't see why having more components increase the CPU load. I could understand a (slight) RAM impact but not CPU.

The laser multiblock extends to just 1 or 2 chunks around. The LHC is at least 10x8 chunks wide. We're not talking the same scale. Also, the laser original design is much older and needs a refresh for other reasons.

skyem123 commented 7 years ago

My understanding of the whole OC code isn't perfect, but I have read the network system a few times to try to understand how it works, and my understanding is that if you want many devices devices (and have no other way to reduce the component count), your best bet is to use the networking, which would probably be different but also would actually be unique and interesting. Networking uses the same system as component messages (I think) internally, so it shouldn't have any different effect on CPU.

Minor nitpick here, while it doesn't directly translate to OC concepts, in real life, lower powered CPUs have less "address space", and so will have less "room" for memory and devices. It's also worth noting that in real life, you can only connect a maximum of 255 USB devices to each USB controller (including via hubs, and each hub also counts as a device). The higher end a system, the more controllers it would have.

I do want to note that components are for both internal and external. The reason why internal and external components are the same thing is because at some point, OC has to simplify, and unlike CC, it doesn't have the "components" built in, so they can't be part of the "core" (and also the difference between internal and external could get confusing once you talk about robots and tablet and drones and microcontrollers which do have some components built in but depend on the configuration of that specific thing).

I don't know how possible it would be to make a custom component bus, but it should be possible, as one can make custom RAM.

thiakil commented 7 years ago

If Components are also intended as external 'Peripherals', and Network isn't an option, then OC design needs some serious revision.

Component is a unified api for talking to the different components ("parts") you can add. I believe it is done this way because some blocks can be added as upgrades to a robot/drone/tablet/microcontroller, and it would be silly to have a different way to access them based on that.

Also, by that logic, if your planned method of doing things isn't going to work, YOUR design needs some serious revision. Keep in mind that comparing OC and CC, OC is by no means 'simple'.

Why do you say network is not an option? How many OC components do your multiblocks currently have?

I don't see why having more components increase the CPU load. I could understand a (slight) RAM impact but not CPU.

Perhaps while it works out where to send the message? Keeping in mind there would be an impact of some sort to the Minecraft server CPU running it all.

payonel commented 7 years ago

@LemADEC autorun IS run on boot, I've been testing different builds and I do not see a regression. The difference you are probably seeing is that the terminal is NOT available at the time autorun is executed, whereas prior to 1.6 it was.

autorun code that needs to use the terminal is inadvisable for multiple reasons, one of which is that the terminal has not be fully initialized that early in the boot stage. These changes were made for good reasons that make openos robust during boot, e.g. setups involving multiple screens that are being removed and added ad nauseum during boot up.

If you do want to have a UI that is executed from autorun, I have a code snippet below that will let you do that. Regardless of advisories and opinions, it is your code and the spirit of this mod is that you should have the freedom to build a custom software package and be creative!

so..with all that said:

autorun.lua snippet:

local event = require("event")                                                                                                                                          
local term = require("term")                                                                                                                                              

local startup_action                                                                                                                                                    
startup_action = function()                                                                                                                                             
  event.ignore("term_available", startup_action)                                                                                                                        
  term.clear()                                                                                                                                                           
  print("hello from my autorun")                                                                                                                                        
  print(term.read())                                                                                                                                                   
end                                                                                                                                                                     
event.listen("term_available", startup_action)