Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal

Leaderboard


Popular Content

Showing content with the highest reputation since 06/03/19 in all areas

  1. 6 points
    MoonlightOwl

    Stem - easy internet bridge

    What is STEM? Did you ever want to have a linked card, but without this pair-to-pair limitations? Well, you have internet card. And that is already half of the solution. The other half is to use Stem. Stem is a message transmitter for your OpenComputers devices with internet cards. Using a small OpenOS library you can use Stem to send and receive messages. Unlike the standard `modem` component, Stem-messaging uses not addresses, but `channels`. You can send messages to any channels, and you can subscribe to any number of channels to listen for messages from them. Installation The best way is to use HPM: hpm install stem If you do not have HPM, install it like this: pastebin run vf6upeAN If you do not want to use HPM repository, you can just use wget: wget https://gitlab.com/UnicornFreedom/stem/raw/master/stem.lua Example of a program using STEM local event = require('event') -- use STEM client library local stem = require('stem') -- open a connection to a STEM server -- the `stem.fomalhaut.me` is a default one local server = stem.connect('stem.fomalhaut.me') -- subscribe for messages from the channel with ID 'my-channel-id' server:subscribe('my-channel-id') -- then listen for events in a loop... while true do local name, channel_id, message = event.pull('stem_message') if name ~= nil then print(channel_id, message) end end -- ...or register an event listener event.listen('stem_message', function(_, _, channel_id, message) print(channel_id, message) end) -- you can also send message to the channel -- (you do not need to be subscribed to this channel, to send a message) server:send('my-channel-id', 'hello there') -- unsubscribe from channel server:unsubscribe('my-channel-id') -- completely close the connection to the STEM server server:disconnect() That is all. But there is more. Web client If you open the link to Stem server in your browser: https://stem.fomalhaut.me/ You will see some statistics and the web client. Enter your channel ID into the form, and you can send messages to your robot in real time, right from your phone, without even starting Minecraft. The web client is limited with UTF-8 encoding, though. (Using OpenOS you can send literally anything, as long as the message fits in 64kb of data.) Security Questions The channels by default do not have any special security measures applied. They do not have any authentication mechanisms, the do not have any encryption. Anyone who knows the ID of a channel can send a message to it and can listen for responses. But. The length of ID is 256 bytes. And that can be any bytes - from 0 to 255. That means, that you have 256^256 possible combinations for your ID. And that is a giant number. If you need to secure your channel - just use something long and incomprehensible as your ID. As an additional measure you can use end-to-end encryption, or anything else - this is up to you. Default STEM server uses HTTPS, and does not store any information - message in, message out. Self-hosted STEM solution For those of you who are strong in spirit and computer knowledge - there is a self-hosted option. You can build Stem server from sources and run it on your machine. This is also pretty easy. Additional instructions can be found on GitLab. Useful links GitLab repository: https://gitlab.com/UnicornFreedom/stem Protocol description: https://gitlab.com/UnicornFreedom/stem/wikis/protocol Default server: https://stem.fomalhaut.me/ HPM package: https://hel.fomalhaut.me/#packages/stem If I forgot something - feel free to ask here, or in IRC (my nickname is Totoro there). Also the project contains at least one "Easter egg" feature, that can offer some interesting options if you know HTML/CSS/JS. The Stem protocol is open - you can modify it, you can create your own clients in any programming language, etc.
  2. 5 points
    its_meow

    OpenScreens

    OpenScreens for Minecraft Forge 1.12 to 1.12.2 OpenScreens adds more display options for OpenComputers. Curse Link: https://minecraft.curseforge.com/projects/openscreens Holo Screens Holo screens are floating displays with adjustable size and color. Hologram projector model and texture by ZefTheFox Right clicking a holo screen with a dye will change the background color. Right clicking the sides with an empty hand while crouching adjusts the size of the display. Flatscreens Flatscreens are simple displays that are... flat! There's two types, one on the front of the block and one on the back to allow more freedom. I have questions/need support! Where can I get help? You can always ask in my Discord server. If your issue is related to OpenComputers, you can read the OpenComputers Wiki. Report bugs here. My website: https://itsmeow.dev/ Discord Server: https://discord.gg/zrjXjP5 Curse Link: https://minecraft.curseforge.com/projects/openscreens
  3. 4 points
    Log

    GPS on microcontrollers

    Program and library for building GPS network. https://github.com/DOOBW/OC-GPS Download: wget https://raw.githubusercontent.com/DOOBW/OC-GPS/master/usr/bin/gps.lua /bin/gps.lua wget https://raw.githubusercontent.com/DOOBW/OC-GPS/master/usr/lib/gps.lua /lib/gps.lua The functionality is the same as in the ComputerCraft. Additional command "flash" allows to upload firmware to EEPROM. When the coordinates are precisely determined, when flashing the position of the microcontroller can be omitted - at the first start it will determine its position from neighboring satellites and save on EEPROM. GPS network startup example.
  4. 4 points
    asie

    Introducing "Lunatic"

    No spoiler in the title. Just watch the video.
  5. 3 points
    Due to quarantine, I got a bunch of time in my hands, I remember that since I first used this mod, back in MC 1.7 we had this phrase on Geolyzer description "It is theoretically possible to eliminate this noise by scanning repeatedly and finding an average. (Unconfirmed, needs further testing.)" Now, many years later, i do know quite some about statistics and got plenty of time So, lets begin We begin our dive in Statistics with an hypothesis, Does this number measured relate to an ore or stone, putting it in hardness terms, does the true number of hardness equal to 3(ores) or 1.5(stone), now we estabilish our null hypothesis. The null hypothesis is which one of them I want to minimize the most(it will make more sense in a bit), I prefer to avoid losing ores, therefore my null hypothesis is that the true hardness of the number measured=3 unless proven with enough evidence the contrary(again, more sense later) In statistic we have two kind of erros given in the table below, we want to minimize error type 1 even if type 2 grows, not so much as for example, mark every where as ore, 0 type 1 error and 100% of type 2. Or be it random where both errors are 50%, so we have to have a small type 1 error without gigantic type 2 error ,let's try. I will from now on ommit "error" in type1 error. Let's first analyze on what I believe is the most traditional way, checking if a number is bigger than a threshold , I made a code to help me with that(DataCollector), given a line of 32 blocks, it will go through each one of them, measure 1000 times, and separate in intervals of 0,25. The result is given as every number smaller than the first column It's quite hard to see it all, comparing it with a stone would be disastrous, but we can clearly see a pattern of every 4th increasing in one more row, so make it goes from 0 to 4, to 8 to... to 56, when possible I tried to use an exact distance, for example 40=sqrt(12^2+32^2) when not possible a very close number 56=sqrt(32^2+32^2+32^2), compare stones and ores side by side and we get this: based on this we can see the strengths and weakness of a single or multiple threshold, in my code I tried to give a general approach, so if you want to detect any other pair it's possible. In my code, I used 2 variables, one to know the value when they meet, the distance where they meet, given by (Hhard-Lhard)*8, the second one is Havg, (Hhard+Lhard)/2, it gives the number when they meet. If the distance is smaller than "meet", the value will be bigger or lower than Havg but I will be sure after this check If we use a single threshold of >2.25 we would be fine up to 12, after our errors would be: 16: type1=10.9% ; type2=11.4% | 20: type1=21.7% type2=19.2% | 24:type1=24.7% type2=23.9% | 28: type1=29.8% type2=26.7% | 32:type1=29.6% type2=32.7% As we can see, not good, not terrible if we want to be sure that its a stone or an ore, we must know what is the distance, find this new threshold, it could be done for each one of them but I dont see a particular distribution, but every 4 distance we have a good approximation of a uniform distribution( where every value is as likely to happen), but between them it wont affect that much the chance of being wrong, type1 and type2 errors are equal to: 16: 24% | 20: 42% | 24: 50.4% | 28: 58.1% | 32: 61.8% | 36: 65.8% | 40: 70.5% | 44:73.9% | 48: 75.4% | 56: 78.5% it seems bad to do it that way, we said earlier that our objective is to minimize type1 error, but we can use multiple measurements to decrease the error, we were already going to do that anyway for our second kind of analysis, I chose to do 6 but you can pick another number, I tried to make it easy to change in the code, butt keep in mind that every measurement takes a lot of time and energy, using the geolyzer is time consuming, for each time you add 55 seconds to scan, default(6) is about 5min 30s. The new errors after six times are, (error)^6: 16: 0.1% | 20: 0.5% | 24: 1.6% | 28: 3.8% | 32: 5.6% | 36: 8,1% | 40: 12.2% | 44: 16% | 48: 18% | 56: 23.4% This is already much better, lower error compared to previus test, but this is still very high, we always have 32 distance, the height, with each command and with this test we would have a high chance missing anything, the robot would have to go around or increase the number of tests that adds up for a lot of time and energy, for such a poor result Now we begin using statistical theory, for that we need to know how the variance behaves given a distance, using Variance.lua code changing x and y and Variance1.lua to Z axis. This code gives Standard Deviation this represents how much from the mean it can be. plotting it in a graph we get that the standard deviation is given by approximately 0.35*distance. https://www.khanacademy.org/math/statistics-probability/sampling-distributions-library#what-is-a-sampling-distribution as this free class explains, the distribution of samples is a normal distribution, doesn't matter the original distribution. to visualize it, using DataCollector.lua code add ore nSamples to your code, default is 1, therefore it shows the original distribution now I am doing it with 6 samples the threshold for the average to given the Z value on the Ztable below is given by -Z*StandardDeviation(0.035*distance)/sqrt(nSamples(6)) + oreHardness(3)=OreT, Z is my type 1 error, my type2 error is given by StoneHardness*sqrt(nSamples)/(Z{positive now}*SD)=OreT. This is all a mess I know, lets give it some numbers, let's get a Z value equivalent of 5% wich is about 1.64 or 1.65, I will go with 1.64, distance of 56, we get -1.64*1.96/2.44+3=1,68, to find our type2 error we have Z=1.5*2.44/(1.96*1.68)=1.116 which is equal to 13.1% 16: type1=5% type2=0.6% | 20: type2=1.9% | 24: 3.6% | 28: 5.3% | 32: 7.2% | 36: 8.8% | 40: 10% | 44: 11% | 48: 12% | 52: 13% | 56: 13,5% We can see that this is the best analysis until now overall, mainly on bigger distances, also even though its hard to understand, its super easy to implement it on code, but this analisys and the last one can be thought as independent events if we do both analysis we significantly lower the chance of any error for 56 distance we have type1=1.1% type2= 3.5%, wich is super low, but for my code I chose to do it until 40 of distance or 32^2+32^2+16^2=40^2, for me 1.1% is huge yet and 16*32*32 is enough volume but you can tune it to whatever you like I want to bring to attention that the code of both analysis was done with the ability of taking any pair in mind, be it dirt and stone or stone and ore, or ore and diamond block, it must have a decent enough interval tho. also it checks for anything lower than stone or bigger than ore, must do another analysis to remove the ones you want from it. https://github.com/gabiiel/GeolyzerOreFinder PS: I am not a professional coder or anything like that, I just wanted to burn some quarantine time, any questions or improvements or features, I am willing to help. I hope everyone could understand. Also I am leaving up to you guys how to get to the ores, this is a very low end program that can run on any machine, the ores are stored in a string there is a function to help write and read from it DataCollector.lua variance.lua variance1.lua
  6. 3 points
    Ever needed real-world time in OpenComputers? I did today, so I did something about it. realtime realtime is a set of libraries and protocols designed to let you synchronise your computers with the real world, and includes: The realtime library, for taking and keeping time. The realtime-sync daemon, for synchronising your realtime library with the real world The realtime-relay daemon, for synchronising your realtime across the local network. All of these can be downloaded via oppm, or from the Minitel GitHub repository. Additionally, all of these come with manual pages describing their functionality and usage, all of which can be found here.
  7. 2 points
    GroundShake

    FlatDB - An SQL implementation

    FlatDB is an implementation of SQL (or SQL-like) commands for manipulating databases on the hard drive itself. This post covers: Available commands and overview. How to use the API. Limitations. Performance. Future plans. 1. Available commands and overview. The following commands are available within the API: SELECT DELETE UPDATE INSERT WHERE AND OR Tables are human-readable and a single-row table will typically look like this: #$ID|param1|param2 1|value1|value2 Tables are created as files, with their columns (including headers) separated by the "|" character, and their rows separated by "\n". If you want to use any of those characters in the values you want to store in the table, please remember to replace them with another character or string, or they might break the formatting. Here are some syntax and command examples: SELECT * FROM example -- the wildcard (*) will pull all the results from the table. SELECT name|surname FROM example WHERE name = john OR surname = smith -- parameters for selection MUST be separated by "|". SELECT surname|name|age FROM example WHERE age >= 24 -- parameters are returned in the order they were requested. -- With WHERE, AND and OR you can use "=", "!=", ">=", "<=", "<", and ">" DELETE FROM example -- WARNING: calling DELETE without any OR, AND or WHERE statemens will delete the entire table. DELETE FROM example WHERE $ID = 4 -- this will delete only the row with the ID of 4. Note the '$' character. It is used to signify an auto-enumerated field. UPDATE example SET name = jack|surname = jackson WHERE age < 40 -- as with SELECT, the values for SET are separated by "|". INSERT INTO example VALUES (john|smith|32) -- the values need to be wrapped witin brackets "()" and separated by "|". -- if your table has an auto-enumerated field, you don't need to supply that one. However, the rest must be given. 2. How to use the API. First, you need to download it: pastebin get hCyKeJYT flatdb.lua Then, you'll need to call the API: local flatdb = require "flatdb" Since you don't have a database, you have to create one: flatdb.newDatabase("example") -- example being the name of our new database Now, you need to 'connect' to the database, or in other words, tell the API which database you're using: flatdb.connect("example") -- returns true or throws an error if the database doesn't exist. Next, you need to create a new table: flatdb.newTable("table", "$ID|name|surname|age") -- table being the name of the table, and name, surname, and age being the headers we want to insert. -- The "$" before ID signifies an auto-enumerated field. Now, because you're connected to a database, you can start inserting values: flatdb.query("INSERT INTO table VALUES (john|smith|32)") -- there is a neccesary space between VALUES and the open bracket. -- the values we're parsing must be separated by "|". -- currently, it is not possible to pass only the values you want. If you don't have, for example, a surname, -- you can pass "unknown" or something that can be changed later on. Let's say your name is John Doe, not John Smith. And perhaps you're 25, not 32. Maybe you want to change that: flatdb.query("UPDATE table SET age = 25|surname = doe WHERE name = john AND surname = smith") Let's get some data from the table: local result = flatdb.query("SELECT $ID FROM table") -- a statement like this grabs the IDs of every row in the table. -- NOTE: if you're testing from the shell, don't use the 'local' keyword. You might have noticed that a result is returned. Every query returns true upon completion, except SELECT. The SELECT query returns an io.lines iterator, so you will need to loop through it (in our case, we only have one row, so it will loop exactly once): for row in result do print(row) end The io.lines iterator points to a file that contains your output. Depending on what you selected, this file may contain entire rows of the table. How do you get rid of those pesky separators? Let's say we ran this command: local result = flatdb.query("SELECT * FROM table") When we loop through it, we have to split the values into an array to manipulate each column individually. The API provides a splitString function. for row in result do columns = flatdb.splitString(row, "|") -- the splitString function requires a string and a dilemeter (in our case "|"). print(columns[2]) -- because we have a table that's $ID|name|surname|age, this will print only the names end When you're done with a database, you can disconnect by using: flatdb.disconnect() 3. Limitations. The syntax has to be followed somewhat exactly. Spaces in things like "name = john" don't matter, but the space between "VALUES (john|doe)" does matter. When in doubt, double-check the syntax. Everything is done iteratively. The result of SELECT forces you to process the data you returned row by row. Why? Because of the memory limitations of OpenComputers. If a table gets big, there's no way to store it in memory. The first version of FlatDB stored everything in memory as tables (arrays), but that only worked up to a point. This version (a re-write of everything except the logic) is able to work on a computer with 256k memory (Tier 1.5). If you want to break the code, you will be able to. Error checking is implemented, but I can only imagine what possible inputs I've overlooked, and I'm looking forward to fixing that. And it goes without saying (though I'm saying it) - you need the proper amount of space to store this file and the databases / tables you want to work with. Also, I will state again that you can not use "|" nor "\n" in the values you're inputting. If you need that kind of thing, replace them with something else. 4. Performance To test the performance of the library, I set up a computer of the lowest tier that's supported. (Everything is Tier 1, except for memory, which is a single stick of Tier 1.5) I then created a script that will fill a table with random number values between 1 and 100. These are the results of tests: Insert 100 - 21s Read 100 - 1s Read 100 (one discriminatory statement) - 8.5s Read 100 (two discriminatory statements) - 16s Update 100 (one discriminatory statement) - 16s Again, this is on the lowest tier PC. I'm happy with the performance, but I'll improve it where possible. 5. Future plans. Future plans by priority are: Bug fixing Adding error checking Adding new features (I'm looking at you, TOP, MIN and MAX). If you want to submit a bug, please include what the bug is, how to replicate it, and (if possible) the table you're working with. If nothing else, this was a fun exercise.
  8. 2 points
    I just finished the first version of bundle - a rc application which virtually merges multiple filesystems into a bigger one. You can use it whenever a RAID full of tier 3 HDD isn't enough for your needs. On the picture above, for example, you can see 10 RAIDs with 30 tier 3 HDDs which yield a virtual HDD that can store over 200MB of data. You can also use filesystems of different size and create files bigger than any of the used filesystems since bundle is capable of storing a file on multiple HDDs. If you encounter any bug, please report it on my github repository. Also check out the wiki page. How to use it First of all you can download it from pastebin (id: TmeSNidd) or my github repository and install the file in the directory for rc script (/etc/rc.d/bundle.lua). Before using it you should configure the constants at the top of the script in accordance with their descriptions. Otherwise Bundle might work incorrectly. Then you need to add some filesystems by executing rc bundle add [address] in the shell. Please replace [address] by the address of the desired filesystem. Doing so wipes the added filesystem. However, Bundle never incorporates filesystems automatically. Next you should allow bundle to run in background by executing rc bundle enable Just reboot the computer and it should be listed by df Note that the label of the first added filesystem and the filesystem provided by Bundle are always equal since that's the way how bundle stores it. You can also view the added filesystems by executing rc bundle list You can also remove added filesystems by rc bundle remove [forcefully] Currently, this just removes the last added filesystem, however. If the removal causes the lose of data this fails except you set [forcefully]. Usage notes Don't install the OS on a Bundle filesystem since Bundle requires some functions of OpenOS. Bundle uses a virtual copy of the file structure. On the one hand this makes "hardware" operations faster, on the other hand it might lead to errors when running out of memory. Bundle works with Lua 5.2 as well as Lua 5.3. Known bugs Seek operations that set the current position to a value that is bigger than the size of the file cause the file the become bigger than its actual physical size. This is also the case on filesystem components of Open Computers but with bundle it might cause internal errors. That is it for now, have fun using Bundle.
  9. 2 points
    Adorable-Catgirl

    OpenSolidState

    OpenSolidState for Minecraft 1.12.2 ____________________________________________________ Source Code and builds can be found on Github. Note: Requires Forgelin. General Purpose (E)EPROMs? Have you ever wanted fast storage? How about wanting to boot PsychOS 2 on a uC? Well, now you can! There are two main variants: The card and the drive. The Card! The Drive! Tiers: Tier 1 - Manually erased EPROM, erased with the assembler. 64KiB Tier 2 - Electronically erased! Still 64KiB Tier 3 - Bigger EEPROM! 128KiB! But how do I craft them? Just use JEI, trust me. What else is included? A utility floppy and ROMFS boot EEPROM are included with the mod! Feel free to ask more questions! i need to make docs
  10. 2 points
    Hey! I'm asie, and while I'm not an official certified OpenComputers developer, I contribute to the project from time to time. However, for a long time, I've had some types of patches in the pipeline that couldn't quite reach the upstream - fixes and changes like: a screen renderer rewrite, with major performance boosts; updates to JNLua and LuaJ, fixing bugs and significantly improving performance; Lua 5.4.0 support. For the purpose of testing these changes as a way to see if they are ready for mass adoption, I've created a fork of OpenComputers called OC-Staging. It is available right here to download. The more people give their feedback (even if it's as simple as "I've ran it on my server, no problems found!"), the sooner we can bring those changes and improvements to upstream - and also, free resources to working on more exciting changes! To give feedback, please post in the feedback thread or report bugs on the issue tracker. You can also find me on the #oc IRC on EsperNet.
  11. 2 points
    Overview Hello there. Some of you may remember KLang. I decided that I should you know, actually work on it. Therefore, I present Triton/TritonLang. Triton is the continuation of KLang, a C++-styled programming language that compiles to Lua. I have no ETA on when it will be done as of the moment, but it is work in progress and I would possibly like to get feedback on my current project status. Hello, world! [Pseudocode] #include <io> int main() { io::info("Hello, world!"); return 0; } Advantages to Lua Headers/easily include libraries Statically and dynamically compiled libraries for programs C++-style syntax and easier OOP Helpful Links WIP Documentation GitHub Repository
  12. 2 points
    Update 3.0.0: I've added secondary screens to make your control room cooler.
  13. 1 point
    A while ago i made a JVM in Lua with the first goal of running Java on OC, just because i like Java and we all know it's a good programming language. So here's the JVM running a program that fills GPU: Oops, made a typo. Ok at first this might not seem impressive at all, but now you can interact with components using Java! That's an awesome thing for Java-ers like me! Race to first Java OS in OC? Anyone? Here's the (simple) code i used above import lukyt.oc.Component; public class ComponentTest { public static void main(String[] args) { String gpu = Component.getPrimary("gpu"); Component.invoke(gpu, "setBackground", new Object[] {0x2D2D2D}); Component.invoke(gpu, "fill", new Object[] {1, 1, 160, 50, " "}); System.out.println("Filled screen with RGB 0x2D2D2D"); } } Here's GitHub page (to download and use on your favourite OC computer): https://github.com/zenith391/lukyt
  14. 1 point
    XyFreak

    Big Reactors Grid Control

    Hi everyone. A while back I promised more releases, so here you go: Big Reactors Grid Control is a multi reactor/turbine controller for Big Reactors and Extreme Reactors. Mission goal: Be the best big reactors controller there is. Nothing more, nothing less. First things first - here's the website: https://tenyx.de/brgc/ NOTE: Due to a bug with OpenOS 1.7.4, BRGC will not work with that version. Please update to 1.7.5. Main features Active and passive reactor support Support for multiple reactors and turbines at the same time (n:m) Control active and passive reactors with the same controller Automatic configuration of everything (EVERYTHING!) Setup instructions wget the installer from here: http://xypm.tenyx.de/standalone/brgc_installer.lua Run it Done Big Reactors Grid Control comes with three rc.d files: /etc/rc.d/brgc_reactor.lua /etc/rc.d/brgc_turbine.lua /etc/rc.d/brgc_grid.lua If you want the controller to run at boot time, you can just use OpenOS' rc.d schema. There's a GUI as well as a command line utility for advanced users. To start the gui, simply run "brgc_gui" and watch the magic happen. The gui scales the screen resolution to match the screens ratio and should scale with basically all screen setups. I recommend 3x2 or 4x3 screens. As of now the command line utility allows you to do (almost) everything you can do with the GUI and also allows you to change the controllers configuration at runtime (if you so desire). Check out "brgcctrl help" for further information. How to set up the grid In a basic setup you just interconnect everything: All active reactors can output steam to all turbines. All passive reactors and turbines output energy to the same grid. You CAN have passive reactors and turbines output energy to different energy grids. While this poses absolutely NO problem for passive reactors, you will have to set some turbines to "independent"-mode (more on that below). If you want your reactors and turbines to properly cooperate, you'll also need to connect at least one energy storage block to your energy grid. Currently supported storage "blocks" are: EnderIO Capacitors (requires the mod "Computronics") Draconic Evolution Energy Storage multiblocks. RFTools Energy Cells Thermal Expansion Energy Cells Mekanism Induction Matrices You can connect them using OpenComputers Adapters. Discovering new components As mentioned before the controller tries to autoconfigure everything: Passive Reactors When a new passive reactor is connected to the controller, the controller will first try to measure its maximum energy output. The reactor will have its output increased step by step and the average (interpolated) maximum will be used for that value (CALIBRATING). After calibration has been completed, the controller calculates the most efficient energy output of the reactor. Active Reactors When a new active reactor is connected to the controller, the controller will first try to measure its maximum steam output (CALIBRATING). For this to work correctly the reactor must be able to output at least SOME steam (read: you need a consumer) and you will need to provide sufficient ammounts of water. The controller will detect reactors with a potential steam output greater than 50 B/t and limit its energy accordingly. Turbines When a new turbine is connected to the controller, the controller will first try to measure its maximum energy output (CALIBRATING). For this to work, make sure your turbine is built correctly. This means your turbine can be run at maximum supported steam (25mb/t per blade) without exceeding 1950 RPM. Should your turbine exceed 1950 RPM at any stage, the controller will shut down the turbine and flag it as failed. Note: Your turbine is NOT required to be able to process 2000 mB/t. Smaller turbines work perfectly fine. Screenshots After this wall of text, here're some screenshots (pre 4.2). Setup: Main view: Passive reactor details: Active reactor details: Turbine details: Let's go in order: When you start up the GUI you will be presented with the main view. Here a combined overview of passive reactors, active reactors and turbines will be presented. You can click (or touch) on any of these items to open up a detailed view of the component. Here you can enable/disable the component or change its behaviour. What behaviour? This is where it gets interesting. Passive Reactors You will notice that passive reactors have two modes and an "auto" mode. PWM This is the behaviour everyone knows: The reactor gets turned on when its internal energy storage drops below 10% and gets turned off when the energy storage exceeds 90% of it's maximum capacity. In PWM mode the reactor will generate energy at its most efficient rod level. Overall this mode allows the reactor to generate energy as efficiently as possible as long as your actual energy consumption is below or equal to its optimal energy output. But sometimes you need just a bit more energy and you don't want to upgrade your reactor or build a new one. "Classic" controllers will fail to produce sufficient ammounts of energy here. This leads me to the second behaviour: Load In "Load"-mode the reactor will always aim to produce energy at the same rate as it's consumed. Maybe some people already suspect what that mode is all about: It's a PD-like regulator. While "Load"-mode is not as efficient as PWM-mode in situations where the energy consumption is below the optimal energy output, it will guarantee you're never running into energy shortages - provided you're not exceeding the reactors maximal capacity. Auto "Auto"-mode aims to eliminate the disadvantages of both modes by combining them: If the energy consumption can be satisfied with PWM-mode, PWM will be used. If the energy consumption is above optimal levels, "Load"-mode will be used instead. As a result, "auto"-mode generates energy as efficient as possible while always saturating your energy demands. Active Reactors As of now, active reactors only operate in "load" mode. Steam is consumed and produced way too fast and the reactors internal steam storage does not allow for anything else. Turbines Turbines controlled similar to reactors in "load" mode: The controller will always try to balance the turbines internal energy storage out to 50% by using a PD-like regulator. Turbines can be operated in "ganged"-mode or in "independent"-mode, with "ganged"-mode being the default. The only difference between these two modes is that turbines in "ganged"-mode can be shut down by the controller, while "independent" turbines will always be active, even if they overproduce energy at the lowest RPM allowed. This is handy if one (or more) of your turbines produces energy for a seperate (dedicated) energy grid but has to be controlled by the same controller. If such a turbine is not in "independent"-mode it may be shut down which will lead to energy failure in that grid. That's it for now. If you have any questions, want to report bugs, etc., feel free to drop a message here. Also: Do you want an indepth tutorial on how to use the command line utility? Need a description on what the GUI is actually showing? Have fun XyFreak
  15. 1 point
    How to Write an OpenComputers Operating System This is the kind of guide I wish I had had 9 months ago when I started developing operating systems for OpenComputers. It will walk you through writing a very basic OpenComputers operating system. EDIT: The guide I followed (the only one I found) is here: WARNINGS: -- This post assumes basic knowledge of programming, such as: what a string is, what a table or list is, what a function is, what a variable is, etc. I am NOT attempting to teach you Lua-- see warning #3 -- This operating system is not intended to have many features (nor is it fast!), but more so to teach new programmers. I will try to keep my code well-organized and well-commented, but no guarantees! -- If you're new to Lua, go read the PIL (https://lua.org/pil/1.html), and keep the Lua reference manual (https://lua.org/manual/5.3/manual.html) open in case you need to reference it. (I also recommend having the OpenComputers wiki [https://ocdoc.cil.li] open.) -- Note that the component, unicode, and computer APIs, plus checkArg, are unique to OpenComputers, and that io and package (plus require, loadfile, and dofile) must be defined by the user. -- This OS is structured in a way that is meant to be easy-to-follow, though you can lay your own out however you like. All source code is available at https://github.com/ocawesome101/basic-oc-os under no license in particular. 1. Init.lua init.lua is the file that most BIOSes expect to load. Most operating systems, this one included, simply use init.lua to load their kernel. This is an example of an init.lua file: -- The path to our kernel. Note that it is advisable to use the 'local' keyword in front of your variables unless you want them to be accessible from everywhere. local KERNEL_PATH = "/mini/kern.lua" -- Get the computer's boot address local address = computer.getBootAddress() -- Open the kernel file for reading local handle, err = component.invoke(address, "open", KERNEL_PATH) if not handle then -- The kernel is probably not present! error(err) end -- Read all the data from the kernel file local kernelData = "" repeat local chunk = component.invoke(address, "read", handle, math.huge) kernelData = kernelData .. (chunk or "") -- (chunk or "") protects against errors until not chunk -- End Of File -- Close the kernel file handle component.invoke(address, "close", handle) -- Try to turn the data we read into a function we can call local ok, err = load( kernelData, -- the data (or "chunk") "=" .. KERNEL_PATH, -- what name to use for the loaded chunk, prefixed with an "=" "bt", -- the mode with which to load the chunk. "bt" should be generally fine _G ) if not ok then -- There was probably a syntax error or some such thing error(err) end ok() -- Execute the kernel -- an idle loop in case the kernel exits. Could be replaced with computer.shutdown() while true do computer.pullSignal() end The comments should explain fairly well what is happening. init.lua should be placed in the root of your drive. 2. The Kernel The kernel is the heart of your operating system. In more advanced operating systems, the kernel usually contains some basic hardware management, a scheduler (relatively complex beasts involving coroutines and signal timeouts), and possibly drivers, leaving the rest of system initialization to the init process. For the sake of this tutorial, we will jump straight from a basic kernel to the shell. In my case, the kernel is at /mini/kern.lua, though yours can be almost anywhere. For compatibility's sake, it is usually a good idea to start by defining _OSVERSION like so: _G._OSVERSION = "mini 0.1.0" Next, you should find installed GPU and screen components- at least one of each. local gpu = component.list("gpu")() local screen = component.list("screen")() There are two ways to interact with components: component.invoke and through a proxy. For extended usage, a proxy is generally the better choice, but for one or two operations component.invoke is fine. An example of component.invoke usage: component.invoke( gpu, -- The component address, a string "bind", -- The method you want to invoke. Must be valid, and must be a string. screen -- Any additional arguments are interpreted as parameters ) It is probably a good idea to create proxies for the GPU and boot filesystem, since we're going to be using these things a lot. local gpuProxy = component.proxy(gpu) _G.fs = component.proxy(computer.getBootAddress()) -- computer.getBootAddress() is defined by most BIOSes Optionally, you can set up basic onscreen boot logging. This is especially useful for debugging, and it can give some insight into what your OS is doing when it boots. I set up my logging like this. Note that my code is somewhat over-commented for the sake of this tutorial. local line = 1 -- What line are we on? local width, height = gpuProxy.maxResolution() -- get the maximum resolution of the GPU and screen. These values are the minimum of the two. gpuProxy.setResolution(width, height) -- ensure that the screen resolution is properly set gpuProxy.fill( -- Fill a box on-screen with a single character 1, -- The top-left X coordinate 1, -- The top-left Y coordinate width, -- How wide the box should be height, -- How tall the box should be " " -- The character the box should be made of ) local function log(message) -- checkArg is a very useful function, used for argument checking. checkArg( 1, -- the argument number message, -- the argument itself "string" -- one or more types that are allowed for the argument, in the form of separate strings. ) -- Set the line at gpuProxy.set( -- Set a line (or part of a line) onscreen to a string 1, -- The X coordinate of the string line, -- The Y coordinate of the string message -- The string ) if line == height then -- We can't go down or we'll be off the screen, so scroll down a line gpuProxy.copy( -- Copy one screen area to another 1, -- The top-left X coordinate 1, -- The top-left Y coordinate width, -- The width height, -- The height 0, -- The relative X to copy to -1 -- The relative Y to copy to ) gpuProxy.fill(1, height, width, 1, " ") else line = line + 1 -- Move one line down end end -- Crash the system in a slightly prettier fashion. Not necessary, but nice to have. local function crash(reason) checkArg(1, reason, "string", "nil") -- This is an example of checkArg's ability to check multiple types -- Here, reason is already local; there is no need to specify it so reason = reason or "No reason given" log("==== crash " .. os.date() .. " ====") -- Log the crash header, ex. "==== crash 24/04/20 18:52:34 ====" log("crash reason: " .. reason) -- Log the crash reason. ".." is Lua's string concatenation operator. local traceback = debug.traceback() -- Tracebacks are usually useful for debugging traceback = traceback:gsub("\t", " ") -- Replace the tab character (not printable) with spaces (printable) for line in traceback:gmatch("[^\n]+") --[[ :gmatch("[^\n]+") splits the string on the \n (newline) character using Lua's basic regular expressions ]] do log(line) end log("==== end crash message ====") while true do -- Freeze the system computer.pullSignal() end end For sanity's sake (and ease-of-use) you should define loadfile(), dofile(), and require(). If you set up module caching in require, you can do some neat things that otherwise would be difficult, such as library persistence across programs. loadfile() is probably the most complex of the three: function _G.loadfile(file, mode, env) checkArg(1, file, "string") checkArg(2, mode, "string", "nil") checkArg(3, env, "table", "nil") -- Make sure mode and env are set mode = mode or "bt" env = env or _G -- env can be used for sandboxing. Quite useful. local handle, err = fs.open(file, "r") if not handle then return nil, err end local data = "" repeat local fileChunk = fs.read(handle, math.huge) data = data .. (fileChunk or "") until not fileChunk fs.close(handle) -- Always close your file handles, kids return load(data, "=" .. file, mode, env) end Then dofile: function _G.dofile(file) checkArg(1, file, "string") local ok, err = loadfile(file) if not ok then return nil, err end return ok() end Basic library caching can be setup very quickly with: local loaded = { ["gpu"] = gpuProxy } -- Libraries that have already been loaded Next, you should implement some sort of require() function. Ideally we'd do this with a fully fledged package library, but that's much more complex. First, you'll need paths of some kind to search. I did mine this way: local libPaths = { -- The path(s) to search for libraries "/mini/lib/?.lua", "/ext/lib/?.lua" } The standard Lua package.path is "/usr/share/lua/5.3/?.lua;/usr/share/lua/5.3/?/init.lua;/usr/lib/lua/5.3/?.lua;/usr/lib/lua/5.3/?/init.lua;./?.lua;./?/init.lua" but the above is considerably easier to parse. To disable package caching, useful for development, you can comment out the lines suffixed with "--". function _G.require(lib) checkArg(1, lib, "string") if loaded[lib] then -- return loaded[lib] -- else -- -- It wasn't already loaded, so search all the paths for i=1, #libPaths, 1 do component.proxy(component.list("sandbox")()).log(libPaths[i]:gsub("%?", lib)) if fs.exists( libPaths[i] -- The current path :gsub( -- Replace a character or characters in a string with another string "%?", -- The string to replace. "%" is necessary because string.gsub, string.gmatch, and string.match interpret "?", along with a few other patterns, as a form of regex (DuckDuckGo regular expressions if you don't know what regex is). lib -- The string with which to replace "?" ) ) then local ok, err = dofile(string.gsub(libPaths[i], "%?", lib)) -- string.gsub("stringToGSUB", ...) is the same as ("stringToGSUB"):gsub(...) if not ok then error(err) end loaded[lib] = ok -- return ok end end end -- end Once this is all done, I load my shell with a simple while true do local ok, err = dofile("/mini/shell.lua") -- Run the shell if not ok then crash(err) end end Note that mine is encased in a while loop so that if the shell exits it will restart. We aren't done yet though, as we still need to program the shell. 3. The shell For simplicity's sake, my shell is just a basic Lua interpreter. It doesn't seem to function properly in ocvm, unfortunately (pcall results are strange, I'll have to test in-game) but here it is, in all its glory: _G.term = require("term") _G.gpu = require("gpu") -- This is where the loaded = { ["gpu"] = gpu } line comes in term.clear() function _G.print(...) local args = {...} for k, v in pairs(args) do term.write(tostring(v) .. " ") end term.write("\n") end local currentDirectory = "/" -- self explanatory local function drawPrompt() gpu.setForeground(0x00FF00) -- Colors are stored as 24-bit hexadecimal values. (Look up "hexadecimal color"). 0x00FF00 is bright green. term.write("\n" .. currentDirectory .. " > ") gpu.setForeground(0xFFFFFF) end local function printError(err) gpu.setForeground(0xFF0000) term.write(err .. "\n") gpu.setForeground(0xFFFFFF) end local function execute(command) local ok, err = load(command, "=lua") if not ok then ok, err = load("=" .. command, "=lua") if not ok then return nil, err end end local result = {pcall(ok)} -- pcall, or protected call, captures errors. Very useful function. if not result[1] and result[2] then return printError(result[2]) end for i=#result, 1, -1 do print(result[i]) end end while true do drawPrompt() local command = term.read() if command ~= "\n" then execute(command) end end What is this shell doing? First, it defines a few utility functions (print(), drawPrompt, printError, and execute), and then it runs the shell's main loop. But wait! What about the top line? Where is the term API? It's in /mini/lib/term. I implemented term.getCursorPosition, term.setCursorPosition, term.scroll, term.clear, term.write, and term.read, but you can implement more fairly easily. Internally, there are two functions (showCursor and hideCursor) that I call after and before every operation, respectively. For example, when you call term.setCursorPosition(2, 2), the term API executes this code: function term.setCursorPosition(newX, newY) checkArg(1, newX, "number") checkArg(2, newY, "number") hideCursor() cursorX, cursorY = newX, newY showCursor() end cursorX and cursorY, as well as width and height, are used internally for purposes you can probably guess based on their names. If you need it, here's my term.read function (text input is always particularly tricky to get right): -- Fairly basic text imput function function term.read() local read = "" local enter = 13 local backspace = 8 local startX, startY = term.getCursorPosition() local function redraw() term.setCursorPosition(startX, startY) term.write(read) --.. " ") -- the extra space ensures that chars are properly deleted end while true do redraw() local signal, _, charID, keycode = computer.pullSignal() -- signal is the signal ID, charID is the ASCII code of the pressed character, and keycode is the physical keyboard code. Note that these are keypress-specific!! if signal == "key_down" then -- A key has been pressed if charID > 31 and charID < 127 then -- If the character is printable, i.e. 0-9, a-z, A-Z, `~!@#$%^&*()_+-=[]{}\|;':",./<>? read = read .. string.char(charID) elseif charID == backspace then -- The character is backspace read = read:sub(1, -2) -- Remove a character from the end of our read string elseif charID == enter then -- my god Kate's syntax detection is crap read = read .. "\n" redraw() return read end end end end That should be all! Feel free to comment if you need help (be sure to provide error messages and the relevant bits of your code) and I'll do my best to respond. My results with this code (I can enter Lua statements and they will be run): Next Steps: -- Expand on this OS with a more advanced shell, io and package libraries, and the like -- Write your own OS with a task scheduler using coroutines -- Be sure you give events to all processes! My first scheduler very much did not do that.
  16. 1 point
    Molinko

    filesystem.list() function help

    local function list_files(dir) local files = {} for path, err in filesystem.list(dir) do assert(path, err) if not filesystem.isDirectory(path) then table.insert(files, path) end end return files end -- # use local files = list_files '/home' -- # example result -- { -- 'test.lua', -- 'poop.cfg' -- }
  17. 1 point
    Thank you. Honestly, neither did I. Until I decided to make a Point of Sale system and realized that I needed a database. If I'm gonna do it once, I might as well make a library.
  18. 1 point
    Log

    unrecoverable error prank

    That is mighty easy. computer.pullSignal = nil
  19. 1 point
    This is a draft. Examples of software will be coded later. Concepts Socket: A file on the system which links two programs' communications. OC: Abbreviation for "OpenComputers" OS: Abbreviation for "Operating System" OpenOS: The stock OS for OC computers. Socket: a medium for communication between two or more programs Rationale To standardize any possible IPC implementations Basic Concepts Background programs (or daemons) can be started with a simple wrapper, such as this example code: thread.create(function() shell.execute(ENV, "/bin/daemon.lua") end) Programs can communicate with sockets through the signals defined in this document These signals can be created with "computer.pushSignal(name: string, [...])" They can be received with "event.pull([timeout: number], [name:string], ...)" or "event.listen(event: string, callback: function)", or on a low-level basis with "computer.pullSignal([timeout: number])" Signals oipc_sock_comms(socketID: string, <... (message)>) -- OIPC Socket Communications -- message must be of type nil, boolean, number, string, table (tables and other messages MUST NOT contain threads and functions due to the limitations of computer.pushSignal()) Notes Please note that OIPC will only work with OSes which pass signals to all subprocesses instead of simply consuming the signal on "computer.pullSignal", "event.pull", or similar functions to wait for/listen for signals.
  20. 1 point
    There is a new Stargate mod AUNIS that is looking very good,. and has added in Open Computers support. I was wondering if there would be a way to port this program to work with the new mod? Curse forge: https://www.curseforge.com/minecraft/mc-mods/aunis Git hub: https://github.com/MrJake222/AUNIS/wiki
  21. 1 point
    Fingercomp

    IRC library

    There was no IRC library for OpenComputers, so I've made one. Here's a demo bot that uses it: local com = require("component") local event = require("event") local thread = require("thread") local gpu = com.gpu local irc = require("irc") local events = irc.events local env = setmetatable({ irc = irc, events = events, }, {__index = _G}) local client = irc.builder() :connection { host = "irc.esper.net:6667", throttling = { maxDelay = 2, maxThroughput = 5, }, } :auth { nickname = "oc-finger-irc", username = "fingercomp", realname = "OpenComputers IRC client library", } :bot { channels = {"#oc-finger-irc"}, tracking = { users = true, modes = true, account = true, userInfo = true, }, } :execution { threaded = true, reconnect = true, catchErrors = true, } :subscribe(events.irc.command, events.priority.high, function(self, client, evt) gpu.setForeground(0x00ff00) print("→ " .. evt.rawLine) gpu.setForeground(0xffffff) end) :subscribe(events.irc.write, events.priority.normal, function(self, client, evt) gpu.setForeground(0x00dbff) print("← " .. evt.line:gsub("[\r\n]*$", "")) gpu.setForeground(0xffffff) end) :subscribe(events.irc.message, irc.events.priority.normal, function(self, client, evt) if evt.source.nickname == "fingercomp" then if evt.message == "::quit" then evt:reply("Quitting.") evt.client:stop(("%s told me to quit."):format(evt.source.nickname)) elseif evt.message == "::spam" then evt:reply("1") evt:reply("2") evt:reply("3") evt:reply("4") evt:reply("5") elseif evt.message == "::longmsg" then local msg = {} for i = 1, 256 do if i == 128 then table.insert(msg, tostring(i) .. " ") else table.insert(msg, tostring(i)) end end evt:reply(table.concat(msg)) elseif evt.message == "::error" then (nil).test() elseif evt.message:sub(1, #"::exec ") == "::exec " then local code = evt.message:sub(#"::exec " + 1) local chunk, reason = load("return " .. code, "=irc", "t", env) if not chunk then chunk, reason = load(code, "=irc", "t", env) end if not chunk then evt:reply(("\x0304Error:\x0f %s"):format(reason)) else local result = table.pack(xpcall(chunk, debug.traceback)) local success = table.remove(result, 1) result.n = result.n - 1 for i = 1, result.n, 1 do if type(result) ~= "string" and type(result) ~= "number" and type(result) ~= "boolean" and type(result) ~= "nil" then result[i] = tostring(result[i]) else result[i] = ("%q"):format(result[i]):gsub("\\\n", "\n") end end if not success then evt:reply(("\x0304Error:\x0f %s"):format(result[1]:match("^[^\n]*"))) io.stderr:write(("%s\r\n"):format(result[1])) elseif result.n > 0 then evt:reply(table.concat(result, " ", i, result.n)) else evt:reply("\x0309Success") end end end end end) :subscribe(events.irc.ctcpRequest, irc.events.priority.normal, function(self, client, evt) if evt.ctcpCommand == "TIME" then evt:reply(os.date("%F %T")) end end) :subscribe(events.client.error, irc.events.priority.top, function(self, client, evt) print("Caught: " .. evt.traceback) evt:cancel() end) :build() local t = thread.create(function() repeat local evt = event.pull("interrupted") until evt end) env.client = client client:run() thread.waitForAny({t, client.thread}) client:stop("Quitting.") os.exit() I don't want to brag about it too much, but I think the code is pretty. Features Threaded execution. A nice API. IRCv3.2 capability negotiation. Throttling to prevent the bot from triggering anti-flood mechanisms. Tracks channel members, modes, nick changes, account names, etc. Automatically reconnects if it's disconnected from the IRC server. Splits long messages over multiple lines. The event bus can use coroutines as message handlers. Links The GitLab repository: https://gitlab.com/cc-ru/irc-oc Documentation: https://gitlab.com/cc-ru/irc-oc/-/wikis/home Demo programs: https://gitlab.com/cc-ru/irc-oc/snippets
  22. 1 point
    BIG UPDATE! I've worked out some updates and a new visual editor for the gui system. To use the gui just download http://pastebin.com/Dfgc6z0T to a computer as /lib/gui.lua and try your best. If you don't want to fight with the placing of elements on the screen, then you want to use the visual editor. It's alpha state, but i hope it will make no errors. The editor will create a full lua code as frame work for your own program in resolution 80x25 like for a tier 2 screen. But you need a tier 3 screen to use the editor it self. The program you can run then on a tier 2 or tier 3 screen. Please try it and let me know, what you think. It's a bit flickry when updating the screen, but i hope i get this fixed. You can download the editor at https://pastebin.com/jdaM8FKG If you like it, let me know and tell me, what i could change, or what you want me to put into the gui or the editor. Have fun
  23. 1 point
    Bumping because it's basically been re-written; we're on 2.0 now, and it has some big improvements: Better re-connect logic Multiple connections pcap capture support for the vTunnel bridge with a wireshark plugin for dissecting Minitel packets Additionally, this post will contain a list of known public relays: lain.church, port 4096 luna.nosafe.space, port 4096 (thanks @Adorable-Catgirl )
  24. 1 point
    vTunnel can be used to add bridging over the internet to any existing OpenOS software that uses linked cards. Despite originally being written for Minitel, vTunnel implements a fully-functional linked card emulator and a server that will run under most unix-likes (OpenBSD is currently somewhat flaky, Linux is recommended). You can peruse the page on Github, for documentation and protocol information. Install it with oppm: oppm install vtunnel Additionally, you can read the documentation in-game with man vtunnel
  25. 1 point
    Subtixx

    VSCode OC Lua

    I made a visual studio code extension for opencomputers available here: https://marketplace.visualstudio.com/items?itemName=subtixx.opencomputerslua and here: https://github.com/Subtixx/vscode-oclua Images:
  26. 1 point
    ben_mkiv

    GPS on microcontrollers

    good job on that, started something similar once but got distracted... thanks for sharing
  27. 1 point
  28. 1 point
    Wow, isn't it annoying to write EEPROMs? Don't you hate how messy they are? Well, I have the utility for you! LuaComp! LuaComp A general purpose Lua preprocessor and minifier. Building To build, either execute luapreproc or luacomp on src/init.lua luapreproc Execute luapreproc init.lua ../luacomp.lua luacomp Execute luacomp init.lua -xO ../luacomp.lua NOTE: Do not use a minifier, it breaks argparse! How-To Merging Lua source files -- myfile.lua local my_lib = {} function my_lib.hello_world() print("Hello, world!") end -- main.lua --#include "my_file.lua" my_lib.hello_world() Getting enviroment variables print("This was compiled in the shell "..$(SHELL)) Macros @[[function my_macro(a, b)]] print("Hello, @[{a}]. Your lucky number is @[{b}].") @[[end]] @[[my_macro("world", 7)]] @[[my_macro("user", 42)]] @[[my_macro("Earth", 0)]] @[[my_macro("Satna", 666)]] @[[my_macro(os.getenv("USER"), os.getenv("UID")]]
  29. 1 point
    Izaya

    portinfo - Network port database

    OC-ports OC-ports provides a database and library for using said database to cross-reference between protocol names and network port numbers. The database also contains the entity that registered the port(s) and, if applicable, a link to more information. API The portinfo API provides one function: portinfo.search(*query*, [*database*]) table: result The search() function takes your query - either a string or a port number - and searches the database, defaulting to the OC ports database, for your query, returning the first result as a table in the format: name port registered by more information This is more than enough to use for simple port lookups and generating tables. Reserving ports To reserve a port in the database, please submit an issue on the GitHub repository. Download portinfo can be installed via oppm from the Minitel repository, using the command oppm install portinfo Additionally, to install manually, place portinfo.lua into /usr/lib/, and both oc.db and minitel.db into /usr/lib/ports/.
  30. 1 point
    Zen1th

    OETF #17 - Open HyperText Protocol

    You can use the port that is not 80. since i said "SHOULD" and not "MUST". But i'll try to change this for better clarity
  31. 1 point
    In OpenComputers we currently have a simple highly abstracted networking model. We do have ports, thankfully, but besides that the model is highly abstracted and thusly underpowered. The first suggestion, is remove the abstraction on network communication in the first place. Allow this to be configured in the mod preferences file, but have it enabled by default. By default, there is no “hardware addresses”. A cable is just that, a cable. The only API by the mod is “broadcast and receive”. In the OS provided by the game by default could still have the same API as now. The different is it’d behave like broadcast, with packets being what are broadcasted. The new network card API (excluding any OS-level abstraction would look like this: - card:up() - card:down() - card:listen() - card:transmit(raw) Already, we now have a lot of extra things. It encourages crafting an encryption card (or whatever it’s called) because users can now snoop and preform MITM attacks on these packets, since there is no game mechanic (provides by the mod itself) preventing posing as somebody else. That also means you can simulate multiple networks cards in software while crafting only one. Second, something that kinda complements the idea of the first suggestion. Cable bandwidth limits. Just like normal cables, there is a limit to the amount of data we can cram into a single cable. Since the last suggestion removed the magic of hardware addresses, we actually need to listen to packets on the cable. We can only process so many packets so often. Now, us developers have an actual NEED to work on more complex softwares. We need to design things like intelligent multiplexing algorithms and routing softwares to efficiently receive, decode, process, bundle, re-encode, and transmit packets. There will also now be tiered network cards, that change things like the maximum number of packets a second the card can receive and transmit. It could also limit what kinds of cables the system can connect to. For example, you might need a tier four to connect to fibreglass. Keeping on the same note, Radio Frequencies. Just like cables, we can only send so much data through the air at once. One way we allow for more people talking wirelessly, besides just having everybody wait their turn in a long que to talk, is Frequency Multiplexing (FM). This also adds a new unique challenge, but powerful tool, to busy areas. You can allow a lot of people to talk at once using multiple frequencies, but you need to develop systems to send data to users on the right frequency to have them actually receive it. Radio Frequencies would have different reasons to use it. Higher frequencies can transmit farther, but they use more power and they can be affected by things like weather (If I understand correctly some RF wavelengths can experience interference due to the size of the droplets). Lower frequencies would use less energy, but have lower range, but less susceptible to interference from things like weather (however, if memory serves right, lower frequencies are more noisy; translates in-game to possibly more failed packets and corruption). In the game, tiered wireless cards have been added. The higher tiers have the capability for wider bandwidth (meaning the range of RFs the card can use), multiple antennas (allowing use of multiple frequencies at once), and higher bandwidth (packets/second it can receive and transmit). To craft these, one good way could be like how you setup server racks. You can open a GUI where there are slots. You need better processor for higher throughput (packets/second) and higher memory for higher throughout volume capacity. All my suggestion make the game more difficult, sure. That’s why I use it over ComputerCraft. I like having my computers be complex and expensive, they should be! They’re freaking computers. This adds the ability to design a lot of new things, and new challenges. However, they won’t really effect new players. On your small one or Teo computer network running the default OS, everything will work perfectly fine. Only large-scale complex systems have these issues.
  32. 1 point
    Palagius

    AE2 Level / Auto-crafting

    It is possible this was implemented elsewhere and I failed to notice it, but I did this as an exercise as exploring OpenComputers. My son and I play The 1.7.10 Pack for our sandbox fun (in survival mode though), and I wanted to see if I could easily use OpenComputers to replace the typical-and-complex nest of level emitters and crafting cards to maintain minimum amounts of certain items in the AE2 ME network. This is not terribly sophisticated, and is just "fire-and-forget" with respects to requesting the crafting operations from the ME Network. As I continue to dabble I may add in checking on the status of the requested jobs and bound the looping to when all requested jobs per loop-pass have been completed. Edited to include versions (Minecraft 1.7.10) and remove a couple of potentially confusing commented-out lines: OpenComputers 1.6.2.12 AE2 rv3 beta6 Lots of other stuff outside the scope of this program Here is what I wrote: local component = require("component") local meController = component.proxy(component.me_controller.address) local gpu = component.gpu -- Each element of the array is "item", "damage", "number wanted", "max craft size" -- Damage value should be zero for base items items = { { "minecraft:iron_ingot", 0, 512, 32 }, { "minecraft:gold_ingot", 0, 256, 32 }, { "IC2:itemIngot", 0, 512, 32 }, -- Copper { "IC2:itemIngot", 1, 256, 32 }, -- Tin { "IC2:itemIngot", 2, 512, 32 }, -- Bronze { "IC2:itemIngot", 3, 256, 64 }, -- Refined Iron { "appliedenergistics2:item.ItemMultiMaterial", 8, 128, 32 }, -- Fluix Dust { "appliedenergistics2:item.ItemMultiMaterial", 10, 128, 32 }, -- Pure Certus { "appliedenergistics2:item.ItemMultiMaterial", 11, 128, 32 }, -- Pure Nether { "appliedenergistics2:item.ItemMultiMaterial", 12, 128, 32 }, -- Pure Fluix { "appliedenergistics2:item.ItemMultiMaterial", 22, 128, 32 }, -- Logic Processor { "appliedenergistics2:item.ItemMultiMaterial", 23, 128, 32 }, -- Calculation Processor { "appliedenergistics2:item.ItemMultiMaterial", 24, 128, 32 }, -- Engineering Processor { "appliedenergistics2:item.ItemMultiMaterial", 52, 32, 32 }, -- Blank Pattern { "appliedenergistics2:item.ItemMultiPart", 16, 128, 32 }, -- Glass Cable - Fluix { "appliedenergistics2:item.ItemMultiPart", 21, 64, 32 }, -- ME Covered Cable - Orange { "appliedenergistics2:item.ItemMultiPart", 22, 64, 32 }, -- ME Covered Cable - Magenta { "appliedenergistics2:item.ItemMultiPart", 24, 64, 32 }, -- ME Covered Cable - Yellow { "appliedenergistics2:item.ItemMultiPart", 25, 64, 32 }, -- ME Covered Cable - Lime { "appliedenergistics2:item.ItemMultiPart", 29, 64, 32 }, -- ME Covered Cable - Cyan { "appliedenergistics2:item.ItemMultiPart", 30, 64, 32 }, -- ME Covered Cable - Purple { "appliedenergistics2:item.ItemMultiPart", 31, 64, 32 }, -- ME Covered Cable - Blue { "appliedenergistics2:item.ItemMultiPart", 34, 64, 32 }, -- ME Covered Cable - Red { "appliedenergistics2:item.ItemMultiPart", 36, 64, 32 }, -- ME Covered Cable - Fluix { "appliedenergistics2:item.ItemMultiPart", 140, 64, 32 }, -- Quartz Fiber { "appliedenergistics2:tile.BlockQuartzGlass", 0, 64, 32 }, -- Quartz Glass { "minecraft:glass", 0, 512, 256 }, { "minecraft:sand", 0, 512, 256 } } loopDelay = 60 -- Seconds between runs while true do for curIdx = 1, #items do curName = items[curIdx][1] curDamage = items[curIdx][2] curMinValue = items[curIdx][3] curMaxRequest = items[curIdx][4] -- io.write("Checking for " .. curMinValue .. " of " .. curName .. "\n") storedItem = meController.getItemsInNetwork({ name = curName, damage = curDamage }) io.write("Network contains ") gpu.setForeground(0xCC24C0) -- Purple-ish io.write(storedItem[1].size) gpu.setForeground(0xFFFFFF) -- White io.write(" items with label ") gpu.setForeground(0x00FF00) -- Green io.write(storedItem[1].label .. "\n") gpu.setForeground(0xFFFFFF) -- White if storedItem[1].size < curMinValue then delta = curMinValue - storedItem[1].size craftAmount = delta if delta > curMaxRequest then craftAmount = curMaxRequest end io.write(" Need to craft ") gpu.setForeground(0xFF0000) -- Red io.write(delta) gpu.setForeground(0xFFFFFF) -- White io.write(", requesting ") gpu.setForeground(0xCC24C0) -- Purple-ish io.write(craftAmount .. "... ") gpu.setForeground(0xFFFFFF) -- White craftables = meController.getCraftables({ name = curName, damage = curDamage }) if craftables.n >= 1 then cItem = craftables[1] retval = cItem.request(craftAmount) gpu.setForeground(0x00FF00) -- Green io.write("OK\n") gpu.setForeground(0xFFFFFF) -- White else gpu.setForeground(0xFF0000) -- Red io.write(" Unable to locate craftable for " .. storedItem[1].name .. "\n") gpu.setForeground(0xFFFFFF) -- White end end end io.write("Sleeping for " .. loopDelay .. " seconds...\n\n") os.sleep(loopDelay) end I have also attached a cropped screenshot of it running and the output. Naturally one will want to turn knobs on the crafting amounts and frequency. I find the 60 minute cycle to be more than enough for the crafting backlog to be cleared.
  33. 1 point
    Adorable-Catgirl

    OC Programs - Share programs

    do you want to make an ass out or yourself? this is how you make an ass out of yourself. Also, what? Like, what do you mean you want people to teach you but you don't want to look at videos? If videos are a problem, then google is your friend. Lua ain't too hard to learn. also holy duck it's hard to decipher what the hell you're saying
  34. 1 point
    Open Extensible Firmware Interface v2.1 FOR LUA ARCHITECTURE, OEFI PRESENTS LITTLE TO NO ADVANTAGES! Lua BIOSes that implements OEFI must allow using conventional booting. Note that OEFI has been made to be more architecture-independent and will support ANY architecture able to read files and CPIO (basically any architecture with basic access to component and bitwise operations). Concepts Application: Executable code booting using OEFI in the EFI1 or EFI2 format. Conventional Booting: OpenComputers default booting method. Often called "BIOS" Operating System (OS) : Complex Application with user interaction and/or providing an environment for programs. Concept only used in this document for Conventional Booting OC: Shortcut for "Open Computers" Rationale Due to the limitation of current OC booting method which basically searches for an init.lua file, the most big problem is that this only work for Lua architecture, and what should other architectures use, init.asm? init.test? init.o? What happens if we want one drive to contains multiple inits for multiple architectures? Well that's where Open Extensible Firmware Interface comes handy. Using . The limitations OEFI fix in Conventional Booting in OC are: In Conventional Booting, there is only one init script per filesystem, while in OEFI there can be multiple applications per filesystem. Conventional Booting doesn't have any native support for multiple applications. An OS that want to boot another one need to manually check for init.lua files in all filesystems, OEFI has oefi.getApplications() method for it, this is even worse for Applications booting on unmanaged drives Conventional Booting isn't made for any other architecture than Lua. And with it, like addressed below, it's impossible to have multiple applications for multiple architectures, while OEFI allows in theory to have one same drive to boot on all architectures it support, without tweaks needed from the user! OEFI is basically a much more extensible version of OETF #1, « Standardized booting of nonstandard architectures » and Conventional booting. 2.1 Changelog Changed EFI2 format into a properties file for easier parsing Using CPIO instdead of URF for same reason: easier parsing Added OEFI Extensions, oefi.loadInternalFile(path) and oefi.setApplications(appTable) Fixed having put AwesomeCatgirl instdead of AdorableCatgirl as username for CAP conntribution Application Table Format The application table must contains tables as entries. The tables must contains the drive address with as « drive » entry and the path (from drive) as « path » entry Example: { { drive = "af58dbe2-ff8c-433a-a871-c08723e01f25", path = ".efi/sampleos.efi" }, { drive = "af58dbe2-ff8c-433a-a871-c08723e01f25", path = ".efi/osOnSameDrive.efi2" }, { drive = "015f9d4c-cdfb-4686-91cb-bc8cf997f4ec", path = ".efi/another_os.efi" } } For architectures not supporting hash maps / dictionnaries, "drive" is index 0 and "path" is index 1 For architectures not supporting arrays inside arrays (2D arrays), the arrays should be appended in such a way it look like that: drive, path, drive, path, drive, path, ... . This is the default standard used by C for multi-dimensional arrays. If the language supports multi-dimensional arrays then the arrays of the language must be used. Finding Applications OEFI Applications can be found on any sort of drives, from disk drives to floppy, with raids, only if they contains a ".efi" directory. The OEFI should search files in ".efi" directory: If the file ends with .efi, then check if it contains CPIO signature, if no, boot in compatibility mode (OEFI1, which is not described anymore on this document). However if the same file contains that signature, then boot as normal. .efi2 will ALWAYS be in standard EFI2 format, unlike .efi which can be EFI or EFI2. .efi can be EFI1 or EFI2 to keep compatibility with old OEFI Applications, and to allow 8.3 filesystems to still support OEFI (would be problematic otherwise) API Methods Methods are same as in Version 1, of course API version is now 2 (logic), and some new methods are being added, so here is the new list of methods: oefi.loadfile(path) - Loads file from boot drive oefi.loadInternalFile(path) - Loads file from current archive - new in OEFI 2.1 oefi.getBootAddress() - replaces computer.getBootAddress() oefi.getApplications() - Return an application table as described above oefi.setApplications(appTable) - Set the application table (as described above) to appTable. - new in OEFI 2.1 oefi.getAPIVersion() - Return API version number. Returns float, double or any decimal 2.1 for this version oefi.getImplementationName() - Returns implementation name oefi.getImplementationVersion() - Returns implementation version number oefi.returnToOEFI() - Recalls the OEFI program, the expected behavior is that the implementation will try to re-execute itself. oefi.execOEFIApp(drive, path) - Boot another OEFI app by using the implementation's routine oefi.getExtensions() - OEFI EXTensions is for non-standard features from implementation. This should always be used for implementation methods. The way this work is described below - new in OEFI 2.1 For architectures supporting tables (and global), API must be available in Global Else, API must be available as a pointer/struct/class/anything like that available as argument to the code OEFI Extensions work in the following way: If the architecture supports entries with keys, then a entry should be created containing the function (or its pointer), and the key should be equals to ImplementationName_MethodName_MethodVersion, ImplementationName should be same as in oefi.getImplementationName(), MethodVersion should be the revision number of a method, starts at 1. And MethodName is the name of the method. Example: SuperOEFI_DrawHandSpinner_2, which could be called (in Lua) via oefi.getExtensions().SuperOEFI_DrawHandSpinner_2() If tables are not supported, then the array (returned by oefi.getExtensions()) should contain all the methods as other arrays. So oefi_ext will be a 2D array. Each array should contain the name (see above) at the first index (0 or 1, depends on architecture), and a pointer to the function (or the function itself, if possible) at second index. If 2D array too aren't supported, then like Application Table, the array should act like if they are appended to each other. Please also note that if possible, computer.getBootAddress() and computer.setBootAddress(addr) should be REMOVED! This is due to that Applications supporting OEFI doesn't need any compatibility methods as thoses conventional booting methods are only kept when booting a OS that only support conventional booting. Implementation can create their own methods, however it should ALWAYS BE INSIDE oefi.getExtensions(). (see above) EFI2 EFI2 is a new format for Applications, it replaces EFI(1) in , it is a CPIO archive. All files in that archive must be placed at root and are listed here: app.cfg app.exe app.exe is only the Application, it contains the code designed for target architecture, and will be launched by the OEFI . app.cfg is a configuration file using "key=value" scheme. The file should look like this: name=Application Name version=1.0 oefiVersion=2.1 arch=Lua archMinVer=5.2 archMaxVer=5.3 Space after key or before name is parsed as it and aren't ignored, be careful! "name" is equals to the name of the Application. Will always be a text "version" is equals to the version of the Application, if you don't want to fill it, just make it stay to 1.0. Will always be a decimal "arch" is a string with the name of supported architecture, "archMinVer" and "archMaxVer" are self-explanatory and will always be a decimal. Note that for archMinVer and archMaxVer, -1 can be used if a version doesn't make sense to the architecture to have a version. (example: a 6502 architecture) "oefiVersion" is equals to the OEFI version the Application has been designed to run with, if the "oefiVersion" field have a version incompatible with the current API version or if it's higher than the current one (ex. it's equals to 3 but we're on API v2.1, or it's equals to 1 but we're on API v2). This will also always be a decimal With all thoses fields in mind, the EFI2 was designed to be durable, with only changes being to app.lon and URF version. Configuration Data Everything is explained in that image: Component Address Packing To shrink down components to 16 bytes, since components address (and UUIDv4 in general) are just hexadecimal numbers converted to string, we can re-convert the string to a byte array and vice-versa. To do it, the lines (-) must be ignored, and each group of 2 characters must be interpreted as a hexadecimal string, this should be easy with architecture supporting string to number with optional base (in our case base is equals to 16) For example it turns: 68ca0f59-ac2c-49f8-ba6a-3c4c7e5f069b into: {0x68, 0xCA, 0x0F, 0x59, 0xAC, 0x2C, 0x49, 0xF8, 0xBA, 0x6A, 0x3C, 0x4C, 0x7E, 0x5F, 0x06, 0x9B} Here is a code sample submitted by AdorableCatgirl to encode and decode the addresses: function binToHex(id) local f, r = string.format, string.rep return f(f("%s-%s%s", r("%.2x", 4), r("%.2x%.2x-", 3), r("%.2x", 6)), id:byte(1, 16)) end function hexToBin(addr) addr = addr:gsub("%-", "") local result = "" for i=1, #addr, 2 do baddr = result .. string.char(tonumber(addr:sub(i, i+1), 16)) end return baddr end -- example: hexToBin("68ca0f59-ac2c-49f8-ba6a-3c4c7e5f069b") == {0x68, 0xCA, 0x0F, 0x59, 0xAC, 0x2C, 0x49, 0xF8, 0xBA, 0x6A, 0x3C, 0x4C, 0x7E, 0x5F, 0x06, 0x9B} -- "68ca0f59-ac2c-49f8-ba6a-3c4c7e5f069b" == binToHex(the array below) Back to EEPROM data, implementation name and custom configuration are very easy to understand what they're about.
  35. 1 point
    Have you ever wanted to encrypt something but couldn't afford a T2 data card? Well, look no further than icekey-lua and Igloo! Low Level: IceKey IceKey is the low level library. It's no RSA, but it should work for most purposes in OC. If you want to learn more about ICE, click here. Useful if you want to do more with the block cipher, rather than just encrypting files or whatnot. It can be found here. High Level: Igloo Igloo is the high level library, great for encrypting/decrypting files. Automatically uses a CBC and padding. It can be found here. PRs welcome!
  36. 1 point
    Well, first of all, if you only need the message to contain one string, then you are better off by just sending the string as the message, so no need to make a table with that string, serialize the table transforming it into a string which is then send via the modem, once received, transformed back into a table which is then indexed to get the string you want to send... But anyways, I would assume the error with the serialization comes from trying to serialize a nil value. You're using a timeout with your event.pull, that means, event.pull returns nil if no modem_message was received within that 239 seconds. So either you simply remove the number specifying the timeout, or you add an if-statement checking whether you actually received a message and skip the serialization part when the message is nil. -- without the timeout, if this is possible, but it looks like you want your robot to execute some stuff every 239 seconds function loopWait() loopOff = false db.clear(1) me.store({name = "minecraft:record_wait"}, db.address, 1) selectEmpty() me.requestItems(db.address, 1, 1) ic.equip() robot.useUp() repeat _, _, _, _, _, serialized_message = event.pull("modem_message") received_table = require("serialization").unserialize(serialized_message) if recieved_table.loopSwitch == "off" then loopOff = true end robot.useUp() selectFull() ic.equip() robot.useUp() until loopOff == true robot.useUp() selectFull() me.sendItems() end -------------------------------- -- with an if statement verifying there actually was a message received function loopWait() loopOff = false db.clear(1) me.store({name = "minecraft:record_wait"}, db.address, 1) selectEmpty() me.requestItems(db.address, 1, 1) ic.equip() robot.useUp() repeat _, _, _, _, _, serialized_message = event.pull(239, "modem_message") if serialized_message then received_table = require("serialization").unserialize(serialized_message) if recieved_table.loopSwitch == "off" then loopOff = true end end robot.useUp() selectFull() ic.equip() robot.useUp() until loopOff == true robot.useUp() selectFull() me.sendItems() end But the easiest and best way would be to send your string directly as the message -- the computer sending the message modem.send(address, port, "off") -- receiving computer function loopWait() loopOff = false db.clear(1) me.store({name = "minecraft:record_wait"}, db.address, 1) selectEmpty() me.requestItems(db.address, 1, 1) ic.equip() robot.useUp() repeat _, _, _, _, _, message = event.pull(239, "modem_message") if message == "off" then loopOff = true end robot.useUp() selectFull() ic.equip() robot.useUp() until loopOff == true robot.useUp() selectFull() me.sendItems() end
  37. 1 point
    its_meow

    OpenScreens

    Update: Minor bugfix that fixes a crash between the holoscreens and RailCraft - OpenScreens v1.0.1
  38. 1 point
    Michiyo

    StattenOS - Base control system

    no primary 'modem' available. It's looking for a component that provides "modem" Likely a network card, or a linked card.
  39. 1 point
    1.7.2 had some serious bugs - not sure why you're not using latest builds.use our latest release build on curse ,or even better, try our latest dev builds https://minecraft.curseforge.com/projects/opencomputers/files https://ci.cil.li/
  40. 1 point
    Zen1th

    Fuchas: Security at its best

    Fuchas 0.4.0 is almost done The new features are: MineOS installer: AVAILABLE Multi-user: AVAILABLE Dualboot (arleady used for 0.3.0): AVAILABLE CPIO-based installer (very very stable installation and allow updates): AVAILABLE Security! (permissions): AVAILABLE Default unicode support: AVAILABLE Virtual components: AVAILABLE (updated 06/30/2019)
  41. 1 point
    Hey, in these if statements, you need to use relational operators. Since you want to see if you're variable is equal to a certain string, you need the '==' (two equal signs). So you're code would look like this -- local require commands start local component= require (“component”) local sides = require(“sides”) local rs = component.redstone local event = require(“event”) -- local os = require(“os”) remove this, the os lib does not need to be required, I think -- local require commands end -- Main function start local function main() local username, message = event.pull(“chat_message”) -- you head a period (.) between both variables -- problematic loop start if username == “Hakz_Studios” and message == “ Alice Refuel” then component.speech_box.say(“Refueling”) component.chat_box.say(“Refueling”) repeat local username,message = event.pull(“chat_message”) rs.setoutput(sides.bottom, 15) -- you need to give the redstone output a value, otherwise it wont turn on -- also, by putting it into a loop, the redstone output will be set a ton of times -- it helps putting the statement before the repeat until loop until username == “Hakz_Studios” and message == “Stop Refueling” -- restarting function function main() -- idk what is this line about, but i dont think it belongs here elseif username == “Hakz_Studios” and message == “Stop Refuel Systems” os.execute(“Shutdown”) -- it will look for a program called 'Shutdown' with a capital S else function main() -- also, dont know what you want to do here, do you want to start the function again (to have the code repeated endlessly) --problematic loop end end -- main function end end Some small info: you don't have to put brackets around your condition in the if-statements, you can, but it's not necessary. Also, here is a program that repeats the main loop over and over again, as I think that is what you want to do in your original code, if I'm wrong tho and misinterpreting you're code, just ignore my suggestion -- require libs local component = require("component") local rs = component.redstone local sides = require("sides") local event = require("event") -- main function local function main() local username, message = event.pull("chat_message") if username == "Hakz_Studios" and message == "Alice Refuel" then component.speech_box.say("Refueling") component.chat_box.say("Refueling") -- this time I set the redstone output once, and then wait for the message 'Stop refueling' then deactivate the redstoneoutput again rs.setOutput(sides.bottom, 15) repeat username, message = event.pull("chat_message") -- you dont have to use 'local' in front of username and message here, since you already created these variables at the top of the main function -- it will override these values but it actually doesnt matter since from this part you will skip to the end and these initial values for both variables -- wont be needed anymore until username == "Hakz_Studios" and message == "Stop Refueling" rs.setOutput(sides.bottom, 0) -- I assume you want to deactivate the redstone after you're done refueling elseif username == "Hakz_Studios" and message == "Stop Refuel System" then os.execute("Shutdown") -- again, this will start the program "Shutdown" with a capital "S" end -- as you can see, we skip the last else statement, as it will call the main function recursively, resulting in a overflow error pretty fast -- you could get away with returning a call to the main function, but this wouldnt be good practice eiter, I guess end -- we add a last while loop, which will repeat endlessly calling the main function while true do main() end I hope this helps. Also you did great for your first shot at programming!
  42. 1 point
    uncpio is a rather simple binary CPIO extractor (File begins with 0x71C7 or 0xC771, made with cpio -oHbin). To acquire uncpio, run pastebin get YbrVjRwa /bin/uncpio.lua To use, make the directory you'll be extracting your CPIO archive to, cd into it, then run uncpio path/to/your/file.cpio And it will extract to the current directory. Currently only works in OpenOS, as far as I know.
  43. 1 point
    Power5000

    VSCode OpenComputer API

    This is a Snippets extension for VSCode that allows you to quickly reference modules used in OpenComputer it is available via github and the VSCode marketplace. be advised it is still a VERY early release and is bound to have typos. please let me know if you find any errors or issues. https://marketplace.visualstudio.com/items?itemName=Power5000.opencomputersnippets https://github.com/power-5000/OpenComputerSnippets
  44. 1 point
    Michiyo

    OpenSecurity 1.7.10/1.10.2

    Hello all, I'm here to announce the release of OpenSecurity! Build Status: Downloads: https://minecraft.curseforge.com/projects/OpenSecurity Change Log: http://ci.pc-logix.com/job/OpenSecurity/changes Source: https://github.com/PC-Logix/OpenSecurity OpenSecurity adds Items and Blocks that are useful for the security of your worlds or bases. Documentation has been moved to GitHub: https://github.com/PC-Logix/OpenSecurity/wiki
  45. 1 point
    KestrelOS GUI-based, Windows-alike, highly customizable, and safe Operating System for common pourposes What's the major GUI-based OS currently available? The amazing system created by Igor, called MineOS (I'm sure everyone by now knows about it). Igor's system is based on OpenOS, that looks like MacOS and is by itself the most amazing system released yet, with all sorts of programs and even 3D libraries which is mind blowing. So why create yet another GUI-based system? There are several reasons why I decided to take on this journey. First of all, the majority of OS's out there, including MineOS is based upon OpenOS, which makes it a bit streamline and boring, but also unsafe. KestrelOS is made entirely from scratch with it's own libraries, services and style. I wanted to create something new, that would give less freedom than OpenOS (which is KestrelOS's main disadvantage), over a much more secure way to process applications. I also wanted to make KestrelOS as simple as possible, so anyone that is familiar to Windows will recognize most of it's content. How exactly KestrelOS works? KestrelOS implements safety policy, where only so called "managers" have absolute control over the system's event management. The "heart" of the system is a manager called "taskman" (Task Manager). Every other manager is registered to taskman and is a read-only table with functions that cannot be altered once the system has booted up. This restrains a lot of freedom for the user, but also prevents malicious software of changing core functions of the system in order to spy or corrupt data. There is few core managers that will "steer" every process in the system, taskman being the most important one as it is the only library in the entire system that has access to a now unavailable command: computer.pullSignal This forces every application to register itself into taskman in order to be able to hook itself under the heartbeat. What is this weird "heartbeat" you're talking about? Taskman has a loop, in which it listens for any signal. I called it the heartbeat, because it waits only 0.25 of a second to update any tasks hooked under specific processes even if nothing happens. This allows multitasking, or for example updating the clock on the bottom-right of the screen What are the so-called "managers" doing? Those so-called managers are here to serve programs with several system services. For example, there's a manager called "driverman", which loads system drivers, which are usually a single library that communicates with a specified type of component. There's a driver for graphics, which is communicating with the GPU, but uses Igor's amazing double-buffering technique (although I made my own version of it from scratch, but it is very primitive right now) to draw into the screen. Drivers are basically bridges between gpu's, datacards etc. that make sure such a given component is available and return optimized methods to use those components better. Of course, every driver has it's own version, name, description, and can be retrieved manually from driverman using the driver id or name, in case you'd like to implement your own driver and use it. What other features it has? Well, most of the system features are actually the managers which act as the main "pillars" of the system. Here's few of main managers that I remember as of now (as I'm not on my home PC right now, I'm writing from my work PC): driverman - manages drivers fileman - manages mounts for different filesystems and resolves path using mounts taskman - heartbeat of the system, manages processes and tasks assigned to those processes regman - manages system's registry guiman - uses kgraphics driver from driverman to draw complex GUI elements on the screen ... (there's a few more that I can't remember now or that are under development) ... Any concerns/disadvantages? Well, like stated before, it actually restrains quite some core functions to prevent malicious application of accessing those in order to prevent system spying or corruption. This removes quite a lot of freedom, but once you log in and unlock everything, you should be able to edit that manually in the system files if you so desire. Any pictures? Well I'm on my work PC not at home so I can't do any pictures, what I can say is that most of the baseline managers are implement and that I'm working on the GUI now, so don't say hurray yet as I'm working on it. Sorry Release date? Undefined.
  46. 1 point
    Features: FlatScreen Panel frameless screen which can be configured to be "rotated/tilted" on the x/y axis and can render transparent (they work as normal Screens, Touchinput will be improved in the final release) CardDock external housing for OpenComputer Cards which can be bound to any machine in the Network Cases additional Tier3 computer cases from ZefTheFox Download on curseForge for Minecraft 1.12.2 https://minecraft.curseforge.com/projects/ocdevices
  47. 1 point
    This is a suggestion on how and why to rework OC's sysyield timeouts. The required fixes basically give ability to implement preemptive multitasking for free. 1. Current implementation of sysyield timeouts is insufficient Currently, it is not a real protection against executor thread hogging. It is only a safeguard, and a very efficient one. Consider the following code: local function dos() while true do end end while true do pcall(coroutine.resume, coroutine.create(dos)) computer.pullSignal(0) end Flash it onto a EEPROM, and throw that into a bare T1 case with just a CPU, a smallest RAM stick, and some power to keep it going. Turn on that computer, and you have a hogged a single executor thread until someone shuts it down. Boot some more computers off the same EEPROM, and you can easily hog all executor threads on a server. On default config, running just 4 of such hogs makes other computers practically unusable, every sysyield causes a 5 second delay. Tweaking the timeout won't really help, since then programs will have to pull(0) much more often, and in the presence of such hogs every yield will cause a delay. Just killing the whole machine when it starts hogging executors won't help in some cases, specifically if computer is turned on by WoL, redstone signal or another computer. Even though it's highly unlikely, such hogging can happen accidentally. Specifically, if a system is built so that it restarts on unknown errors, sysyield timeout will not stop an accidental infinite loop in it. 2. How it is currently implemented I don't think I have a complete understanding yet, but that's how I see it: The coroutine library is wrapped: coroutine.yield() adds an extra nil as the first value, to differentiate normal yields from sysyields coroutine.resume() repeatedly does following: Call sethook() on the coroutine to terminate it on a sysyield timeout Call the real coroutine.resume() If the first returned value is nil (i.e. normal yield), return the rest Otherwise (i.e. sysyield), yield all values and continue the loop Therefore, when sysyield happens (i.e. on computer.pullSignal), the whole stack of running coroutines is unwound, and the outermost one yields the computer. On the next tick, or whenever a signal comes, the computer is resumed, and the same stack of coroutines is rebuilt, and the innermost one continues its execution. The hook that is attached to each coroutine checks if computer has been running for too long, and throws an error if so, which terminates the currently running coroutine. It also extends the deadline by half a second exactly once, so that the parent coroutine has a chance to recover. So long as it does a sysyield in those half a second, or yields/returns and lets its parents do that, the deadline is reset and the computer can continue operating. If it does not, the remaining parent coroutines do not get a chance to recover, and the computer is halted with an error. And until the innermost coroutine times out, nothing can stop it unless it yields control. For example, if you type while true do end in the LUA repl, it will start that code in a coroutine and print an error message when it times out. If that same loop is explicitly started inside a coroutine, the error is caught and another infinite loop is started, the REPL will not get a chance to do anything, and the whole computer will crash. 3. The suggested implementation The basic problem is, the hook set by Lua code with debug.sethook() cannot yield a coroutine. It can only throw an error, terminating the coroutine, therefore the timeout has to be long enough to let the program do whatever it needs to without doing sysyields all the time. This is problematic, since all the computers share the same few executor threads, and the timeout also has to be short enough to allow other computers to run normally. However, the debug hooks actually can yield, under certain very restrictive conditions: https://www.lua.org/manual/5.3/manual.html#lua_Hook The catch is, it can only happen from the native code (C for normal Lua, probably Java for LuaJ), and no values can be returned. I've written a simple test library in C to allow setting yieldable Lua hooks from Lua code: https://github.com/evg-zhabotinsky/yieldhook I tried to implement it myself at first, but then realized that I'm reimplementing debug.sethook... So I just copied it, cut out the unneeded bits and added a loader. If possible, it's probably cleaner to modify the original Lua library (ldblib.c for C version, not sure about LuaJ). The final interface of the modified debug.sethook() is that if hook mask contains an 'y', event is either 'line' or 'count' and the hook function returns truth, the paused coroutine is yielded with no values, i.e. coroutine.resume() returns just true. The normal return from coroutine with no arguments can be differentiated from a hook yield by checking if coroutine is now dead, and the normal yields can be wrapped to prepend an extra true value. tl;dr: see the test program in my repo, it demonstrates a simple preemptive multitasking implementation. Its wrapper for coroutine.resume returns: true plus the values on normal yield or return false plus the error message on error nothing on a hook yield (that's what different from the standard behavior) It should be pretty easy to modify the OC's existing wrapper and hook functions to sysyield instead of throwing an error on timeout. That timeout can then be made much shorter, since coroutines are no longer terminated. Preferably, it should be adjusted dynamically by machine.lua, so that cycles are distributed fairly (incl. according to CPU and memory tiers) with no leftovers and each computer runs exactly once every tick. Preferably, something like computer.getSliceTime() and computer.getRemainingTime() should return how much time the computer has been assigned during the tick and how much of it is left. The units of those functions can be declared "abstract cycle amounts" for the sake of "realism", in which case the slice time will be CPU frequency (quite unstable, just like the tooltip suggests xD) and the remaining time will be cycle count until the next bus synchronization or whatever. Having done that, there basically will be preemptive multitasking between all the computers, and none of them will have to wait long for their turn to run. For compatibility, the current "die if hung for 5s" behavior can be implemented in OpenOS, and allowed to be disabled for the sake of "power users". To allow for user-controlled preemptive multitasking on a single computer, I propose adding computer.setTimeout(time, coroutine), with time being the same units as computer.remainingTime() and coroutine being the timeout handler coroutine. The debug hook will work all the same, except it will yield prematurely if the soft deadline happens to be earlier. The wrapped coroutine.resume() will see that a timeout has happened, but hard timeout hasn't expired yet, and instead of yielding any further will disable soft timeout and resume the specified coroutine. The coroutine.status() has to be wrapped too to mark the "yielded by hook" coroutine as "normal", as if it called resume() on the handler coroutine. While the handler coroutine is running, soft timeouts are ignored. When it yields, the paused coroutine is resumed and soft timeout is enablet, if it was set again by the handler. However, if there is a pending soft timeout, the handler coroutine is immediately resumed again. The setTimeout behavior suggested above matches closely how a timer interrupt would be handled in a real CPU, exactly what machine.lua should contain. The rest of multitasking implementation and protection is on the OS. Apart of implementing a scheduler, synchronization mechanisms have to be implemented. Count hook can trigger in the middle of any non-trivial expression, so normal assignments cannot be used for unconditionally reliable synchronization. However, a coroutine cannot be resumed unless it's suspended, and everything on a computer runs in a single Lua state, so any coroutine body is a natural critical region, which can easily be leveraged to implement any kind of synchronization. 4. Who is going to implement all that? Given some time, I can implement the Lua side of things. The native side, though... I'm afraid to break something there, and even though I've done the same modifications for the official Lua implementation, I don't know yet how to do the same for JNLua and LuaJ and in the context of OpenComputers specifically. Plus, I'm not keen on rebuilding OpenComputers from source. If someone confirms that there's nothing to learn or break and that it should just work, I'll probably do that too. Once the core functionality is implemented, I'm thinking more like implementing a more Unix-like OS, aiming for POSIX compatibility, and the ability to implement proper preemptive multitasking is a must for that. The ultimate goal is to be able to compile and run most normal C programs without modifications. I'm already working on a primitive C to Lua compiler, because I gave up porting a simplistic MP3 decoder to Lua by hand. (I want to have online radio in my bunker!) Aaanyway, comments and suggestions are welcome. I was more interested in the technical part, so I haven't really though much about API function names or how exactly to divide time among computers of different tiers, so there's that. (Also, is there a way to figure out tiers of arbitrary component from inside the computer?) I didn't think at all about how OpenOS would provide preemptive multitasking to its programs, too, and I have absolutely no idea if it would crash and burn when anything starts running "in parallel".
  48. 1 point
    asie

    Introducing "Lunatic"

    The optimization patches in OpenComputers's repository are not yet merged into mainline, but you can install lunatic86 regardless! (Just with worse performance.) $ oppm install lunatic86 $ lunatic86 -h
  49. 1 point
    Minitel is a simple, efficient networking protocol implementing layers 3, 4 and 5 of the OSI model. It supports automatic configuration and routing over large and small networks. This topic contains links to all known Minitel protocols. Core protocols (OSI layers 3 through 5): protocol-3.md - describes the format of Minitel packets and basic behavior of each node. protocol-4.md - describes how ordered sequences of packets should be handled. protocol-5.md - describes how Minitel's bidirectional streams work Application layer protocols: FRequest - a simple file retrieval protocol MMail - simple mail delivery protocol If you wish to have a protocol added to this list, post it here.
  50. 1 point
    BloodyRum

    How to program EEPROM?

    Thank you. Now it looks like something a ten year old can do. (Not joking nor being Sarcastic) But it should be easily done with something like 1. Make special X Block and put EEPROM Into it 2. Enter something like "edit (EEPROM Add)" 3. Enter code then remove EEPROM With Arduino the coding is "simple" much like OpenComputers. Snippet of Arduino code int hour11 = 1; int hour21 = 2; int hour22 = 3; int hour23 = 4; int hour24 = 5; int minute11 = 6; int minute12 = 7; int minute13 = 8; int minute21 = 9; int minute22 = 10; int minute23 = 11; int minute24 = 12; int hour1 = 0; int hour2 = 0; int minute1 = 0; int minute2 = 0; int addmin = 0; int addhour = 13; void setup() { pinMode(hour11, OUTPUT); pinMode(hour21, OUTPUT); pinMode(hour22, OUTPUT); pinMode(hour23, OUTPUT); pinMode(hour24, OUTPUT); pinMode(minute11, OUTPUT); pinMode(minute12, OUTPUT); pinMode(minute13, OUTPUT); pinMode(minute21, OUTPUT); pinMode(minute22, OUTPUT); pinMode(minute23, OUTPUT); pinMode(minute24, OUTPUT); pinMode(addmin, INPUT); pinMode(addhour, INPUT); } void loop() { delay(60000); minute2 = minute2 + 1; if (minute2 = 10){ minute1 = minute1 + 1; minute2 = 0; } if (minute1 = 6){ hour2 = hour2 + 1; minute1 = 0; } if (hour2 = 10){ hour1 = hour1 + 1; hour2 = 0; } if (hour2 = 2){ if (hour1 = 1){ hour1 = 0; hour2 = 0; } } (Sorry Admins if this is too long) (Think of pinmode as Redstone IO) You can see its similar to OpenComputers, but instead of if (hour2 = 2){ if (hour1 = 1){ hour1 = 0; hour2 = 0; } } You would have if hour2 == 2 if hour1 == 1 hour1 = 0 hour2 = 0 end end Also the main reason why I wanted to do this to program a Microcontroller is to have a big reactor control program. (Again sorry admins if this is too long. Delete it or let me know to shorten this.)
  • Newsletter

    Want to keep up to date with all our latest news and information?
    Sign Up
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.