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


Popular Content

Showing content with the highest reputation since 09/24/19 in all areas

  1. 5 points

    Cyan BIOS

    The world as I knew it had a problem. A plenty of bootloaders had already existed, and they'd all shared the same flaw: it wasn't me who made them. I've decided to put an end to that. Cyan is a multi-bootloader and a replacement for the plain Lua BIOS. The features it encompasses include: a whitelist to prevent random strangers from tampering with the computer a Lua interpreter to test your sudden ideas support for hot-plugging filesystems if you've forgot to insert a floppy the ability to format or label a filesystem, while we're at it loading the boot payload from the internet when you can't afford an HDD and a gorgeous, minimalistic design Pictures: To install on OpenOS, run the following: wget -fq https://raw.githubusercontent.com/BrightYC/Cyan/master/installer.lua && installer.lua Or, if you're a MineOS user, look for the program (bearing the same name) at your local AppMarket. Here's how the whitelist works. You add trusted users to the list when the installer asks you. Then the bootloader will ignore any signals from other people. That's it. Oh, and you can also choose a less restrictive option: the Cyan BIOS can wait for input from a trusted user. Before that an authorized person can't access the bootloader. Lastly, a couple of words about the Lua interpreter. It doesn't wrap the output, and the input command must be less than the screen width. The last restriction can be circumvented by copy-pasting the command. In addition to that, the bootloader defines the following functions: os.sleep([timeout: number]) proxy(componentName: string): table or nil — returns a component proxy by its name (cf. component.proxy, which takes an address) read(lastInput: string or nil): string or nil — a primitive io.read() print(...) The source code for the curious: https://github.com/BrightYC/Cyan P. S. Big thanks to @Fingercomp for his lecture about string escapes and writing this text.
  2. 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
  3. 3 points
    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.
  4. 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.
  5. 2 points

    Minecraft server on OC

    Last demo video: No, it does not currently run modded minecraft (albeit it runs plugins made for this server), but one experiment i want to do for later is recreating a bit of OC mod in Lua, to make it run in this server, so that you can run Minecraft server in Minecraft server in Minecraft server in Minecraft server in ... until it crashes your PC lol.
  6. 2 points
    Anything not impossible is possible, and this feature doesn't even require much perseverance to implement. Right now we're using owner to store the nickname of one player. We are going to replace it with a table, and therefore the name owner is no longer satisfactory. Let's rename it as trustedPeople and populate it with some test names. local trustedPeople = {"player1", "player2", "player3"} A table is the universal record type in Lua, that is, the type that stores multiple values. But we still need to choose the correct data structure. The table trustedPeople is a sequence. This means its elements are stored sequentially, without gaps, and can be accessed using integer indeces (trustedPeople[1], trustedPeople[2], etc.). Such a data structure is useful if we need an ordered collection of items to iterate over, for example. However, this is not the case here. What we need is essentially a set, which stores unique elements and can tell us in an efficient way if a certain value exists. In Lua, sets are usually implemented as follows: local trustedPeople = { ["player1"] = true, ["player2"] = true, ["player3"] = true, } The stuff in square brackets is called the key, and what follows after the equals sign is the value. If you have the key, you can quickly determine the associated value, which defaults to nil for nonexistent keys. The most important word is quickly. As for the previous data structure, to find if a table contains a trusted person, we would have to iterate over the sequence of authorized players for every element of the table. local ownerNearby = false for _, entry in ipairs(scan) do for _, trusted in ipairs(trustedPlayers) do if entry.name == trusted then ownerNearby = true goto out end end end ::out:: It's very inefficient and complicated. Now, compare it with the code that we would write if we use a set for trustedPlayers: local ownerNearby = false for _, entry in ipairs(scan) do if trustedPlayers[entry.name] then ownerNearby = true break end end However, I like how easy it is to modify the sequence in the code. {"one", "two", "three"} is much more concise than {["one"] = true, ["two"] = true, ["three"] = true}. I'll make it so that we could specify the list of allowed people, and it would be converted to a set by the program. local trustedPeople = {"player1", "player2", "player3"} for index, nickname in ipairs(trustedPeople) do trustedPeople[nickname] = true trustedPeople[index] = nil end Let's incorporate all of that in the original program. local component = require("component") local alarm = component.os_alarm local door = component.os_door local entity = component.os_entdetector local trustedPeople = {"player1", "player2", "player3"} for index, nickname in ipairs(trustedPeople) do trustedPeople[nickname] = true trustedPeople[index] = nil end local previousState = "nobody" while true do local scan = entity.scanPlayers(64) if scan and #scan > 0 then local shouldOpen = false for _, entry in ipairs(scan) do if trustedPeople[entry.name] then shouldOpen = true break end end if shouldOpen and previousState ~= "allowed" then door.open() alarm.deactivate() print("Welcome home!") previousState = "allowed" elseif not shouldOpen and previousState ~= "intruder" then door.close() alarm.activate() print("Hello, whoever you are.") previousState = "intruder" end else door.close() alarm.deactivate() previousState = "nobody" end os.sleep(2) end I've also changed a couple of names so that they would reflect their purpose.
  7. 2 points
    I am sorry, but unless I'm misreading your code, it can't possibly throw an "attempt to index a nil value" error, with any people in proximity or without. And the question is contradictory, stating both that the program crashes and that it freezes (the latter is correct, however). Actually, I'm unsure what the actual question is. Therefore, I'll do the only thing I can here: that is, explain what your code does wrong and how to fix it. Before I can proceed to fix the actual issues in the program's logic, I have to get rid of some minor problems. The first such problem is that the code is indented poorly. Of course, Lua doesn't care how you format your code, but it isn't why you do that. Indentation helps you, the program's author, to keep track of what it does, to visually separate chunks of code. And other people benefit from that too, for properly formatted code is much more readable. Without further ado... local component = require("component") local colors = require "colors" gpu = require("component").gpu alarm = require("component").os_alarm door = require("component").os_door entity = require("component").os_entdetector local w, h = gpu.getResolution() local delay -- sleep time local player -- list of players while true do os.sleep(2) if entity.scanPlayers(64) == true then scan = entity.scanPlayers(64) name = scan[1].name if name ~= "sav" then door.close() alarm.activate() print("Hello " .. scan[1].name) os.sleep(2) alarm.deactivate() elseif name == "sav" then door.open() alarm.deactivate() print("Welcome Home Sav") os.sleep(2) end os.sleep(4) end end ...And the second thing to take care of is the global variables. Unless you need them such (which rarely happens and this is no exception), make them local. Finally, you've already required component, so there is no reason to do so again; and, while fixing that, let's also remove the unused variables: gpu, colors, delay and player. You can re-add them later yourself if you need. local component = require("component") local alarm = component.os_alarm local door = component.os_door local entity = component.os_entdetector local owner = "sav" -- insert your nickname here while true do os.sleep(2) if entity.scanPlayers(64) == true then local scan = entity.scanPlayers(64) local name = scan[1].name if name ~= "sav" then door.close() alarm.activate() print("Hello " .. scan[1].name) os.sleep(2) alarm.deactivate() elseif name == "sav" then door.open() alarm.deactivate() print("Welcome Home Sav") os.sleep(2) end os.sleep(4) end end Great, so now we can start dissecting the code. What does it do? First, we require the component library, get proxies of the components we need, and proceed into the main loop. There we first sleep for 2 seconds... Why do we sleep for 2 seconds, again? I'm not sure; let's keep it there for now. Then we perform a scan, calling entity.scanPlayers(64), which returns a table, and compare if it is equal to true. Wait. There is no way a table can be equal to true, not unless you mess with metamethods, which we don't. Very suspicious. If we interpret the code literally, we skip the whole if, and end up at the start of the loop again. It's not interesting, so let's pretend that somehow the if's condition is satisfied to understand what the author's intent was. And then we perform another scan... hang a minute, another one? Haven't we already done that? Why should we be in dire need of repeating ourselves? Anyway, I think I realized what the code was supposed to do: scan the surroundings and check if there's anyone around. After all, running an alarm without anybody to listen to the marvelous sounds of it is just a waste of energy, isn't it? Let's put it into words in Lua. ... while true do local scan = entity.scanPlayers(64) if scan and #scan > 0 then ... else door.close() alarm.deactivate() end os.sleep(2) end We do the scan as soon as we're in the loop. If the scan result is present (neither a false nor a nil), which means the entity detector had no errors, and the length (#) of that table (#scan) is greater than 0 (#scan > 0), then we'll do something about it. The previous sentence is basically how you'd read the code in English. Note that if scan happens to be empty, we close the door and disable the alarm. And we shouldn't forget to sleep, for the sake of energy conservation. All right, so let's do something about the scan. scan the variable is a table of tables. In other words, scan is a table that stores other tables. Each "other table", in turn, contains information about one player nearby. We have already checked that at least one player is present, but there may be more people gathered around, totally not planning a siege, and we don't yet know whether you are there. You blindly assume you would be the first player in the returned list. Unfortunately, the entity detector couldn't care less about that, and your entry could easily be the second or the last one. Or not present at all, if you happened to carelessly abandon your fortress. Our mini-goal is to walk through all the entries of the table (this is called iterating a table) until your entry is found. If after iterating through all items we have yet to found yours, you're not around. So we close the door and activate the alarm. Otherwise, we do the opposite. This is how you do it: local ownerNearby = false for _, entry in ipairs(scan) do if entry.name == owner then ownerNearby = true break end end if ownerNearby then door.open() alarm.deactivate() print("Welcome home!") else door.close() alarm.activate() print("Hello, whoever you are.") end Something isn't right... The program will keep spamming "Welcome home!" if you're in vicinity, which isn't quite courteous. Let's make it greet you only if you weren't around before that, and do likewise for greeting intruders. To do that, we need to remember the previous state of your program: whether there was nobody, an intruder, or you. local component = require("component") local alarm = component.os_alarm local door = component.os_door local entity = component.os_entdetector local owner = "sav" -- insert your nickname here local previousState = "nobody" while true do local scan = entity.scanPlayers(64) if scan and #scan > 0 then local ownerNearby = false for _, entry in ipairs(scan) do if entry.name == owner then ownerNearby = true break end end if ownerNearby and previousState ~= "owner" then door.open() alarm.deactivate() print("Welcome home!") previousState = "owner" elseif not ownerNearby and previousState ~= "intruder" then door.close() alarm.activate() print("Hello, whoever you are.") previousState = "intruder" end else door.close() alarm.deactivate() previousState = "nobody" end os.sleep(2) end Well, this is the whole program. I didn't test it, so any bugs are yours to find and exterminate.
  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
    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
  10. 2 points
    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.
  11. 2 points
    bad at vijya


    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
  12. 2 points
    A while back, I've quietly released an unofficial, experimental OpenComputers fork called OC-Staging, available here. The key features as of writing include: Optimized GPU rendering code, providing up to 2x better performance (in terms of frame rendering time), LuaJ and JNLua bugfixes and updates, Native Lua performance improvements, Lua 5.4 support! (currently on lua-5.4.0-beta) This is the feedback thread for this fork, as input is sought before merging the changes back into OpenComputers due to their potentially invasive nature (for bug reports, please use the issue tracker).
  13. 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.
  14. 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
  15. 2 points

    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.
  16. 1 point
    First post here, hi. For the past few months, I’ve been working on an operating system for OpenComputers. It’s a monolithic, UNIX-like operating system. Note that Monolith will not currently work in OCEmu due to the lack of support for`computer.getDeviceInfo`. First, the advantages over OpenOS: - Monolith supports dynamically adding and removing screens, GPUs, and keyboards - it’ll automatically spawn a shell on an available combo and will try to match by tier. - Monolith’s userspace is properly sandboxed - there’s no way to completely crash the kernel from userland. - Monolith includes a fairly complete set of documentation, in the form of manual pages, for many system and user-level APIs. They are also available for online viewing here. - Monolith’s terminal is entirely VT100 - the `term` API is a wrapper around this and included only for compatibility. - The scheduler will automatically collect garbage if memory gets low, and includes a facility that avoids dropping signals. Your system may freeze for half a second or so, but all input will be registered and you’re less likely to OOM. - Monolith ships with the Minitel, and soon GERTi, network stacks out-of-the-box. - Monolith’s package manager, while admittedly somewhat basic, is faster than OPPM. - The provided `readline` implementation is ridiculously featured and the best I’ve written - and it’s even its own API. `io.stdin:read` is by default simply a wrapper around `readline`. - The recommended and default editor, `vled`, has support for optional syntax highlighting through a command-line flag. So far, only Lua is supported. Now, the disadvantages. - Shell redirects are not implemented. - Monolith requires a minimum of 256 kilobytes of RAM, or a single tier 1.5 stick, due to the userspace sandboxing. - Monolith does not *quiiiiiiite* have full OpenOS compatibility, though most programs should theoretically run out of the box - see `wget`, `pastebin`, `components`, and `lshw`, which are pretty much direct copies of the OpenOS implementations. The `event`, `internet`, and `buffer` libraries are also taken from OpenOS. - `vled` is slower (due to use of VT100) and slightly less featured than OpenOS’s `edit`. It’s also a little more obtuse thanks to the fact that it draws heavily from `vim`. - There are a few small and rather strange bugs in my `readline` implementation. They shouldn’t affect normal use too much, though, as they aren’t terribly noticeable except on tier 1 screens. The source code is available here if you want to try it out!
  17. 1 point
    There's software for importing/exporting components included with the Minitel RPC library (on oppm as mtrpc) tl;dr oppm install mtrpc exportcomponent <component address> [component address...] importcomponent <host> <component type> <component address> Doesn't work properly with components that return functions, like the internet card, but it works nicely with stuff like redstone cards and storage devices.
  18. 1 point

    Minecraft server on OC

    Not a Minecraft server about OC, but a Minecraft server running on OC. More specifically an 1.15.2 Minecraft server. (btw sorry for low video quality, but 2 Minecraft instances with one modded is CPU-intensive, so..) Installing Just look at the github: https://github.com/zenith391/OCMCS
  19. 1 point

    Minecraft server on OC

    Wait what? How? You did what? But can it run modded minecraft? How deep is the rabbit hole?
  20. 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.
  21. 1 point

    Wireless and Relays

    There is some issue with the tier 1 card. I usually use tier 2 anyways, therefore I didn't notice. Tried with a tier 1 card and I was able to replicate your findings. So for now, I would simply use a tier 2 card in the robot and computer and everything will work just fine without a relay. I'll probably have a look in the tier 1 card's source code later and file a bug report on github (unless you want to do that)
  22. 1 point

    SGCX - SGCraft Stargate Controller

    SGCX - SGCraft Stargate Controller Stargate controller based on GML library. Showcase: Installation steps: First download the package manager that will be used to download the application and all required dependencies: wget https://pastebin.com/raw/iAH5xC3b arpm_downloader.lua arpm_downloader Use the package manager do download SGCX: arpm install sgcx Run SGCX with an additional argument - init. This will allow you to pick a stargate interface address from list. It is required only during the first startup - address will be saved in a configuration file. sgcx init Optionally you can install the irisAuth package (remote iris management) using the previously mentioned package manager. Features: Displaying Stargate status Storing gate addresses Grouping and searching addresses Disconnecting wormhole after specified time Automatic iris control (see installation steps, step 4) Displaying distance to the selected destination Address calculator: convert addresses within one dimension into chunk (and estimated block) coordinates and vice versa Animated dialing sequence with chevron drawings Future plans: Dialing history Iris authorization usage history Requirements: Tier 3 screen and GPU At least 1 MB RAM Network card Keyboard (GitLab repository)
  23. 1 point
    zag kalidor


    have a look into the /bin/echo.lua, maybe something like this ?
  24. 1 point
    The inconsistency comes from you pulling events twice and storing them to separate variables. That can mess up the different senders in your network. So what you need to do is pull an event once, check the sender's address and then perform some tasks based on the addresses. local event = require "event" while true do local _, _, addr, port, _, message = event.pull("modem_message") if addr == "one address" then -- # do some stuff elseif addr == "the other address" then -- # do some other stuff -- # you can add as many addresses in elseif statements as you want end end Or you use a a table to map functions to addresses. local event = require "event" local addresses = { ["address1"] = function (msg) -- # do stuff end, ["address2"] = function (msg) -- # do other stuff end -- # you can add as many addresses and functions as you want } while true do local _, _, addr, port, _, message = event.pull("modem_message") if addresses[addr] then addresses[addr](message) end end
  25. 1 point
    I don't know securitycraft or opensecurity but you can put a redstone card into the computer and get a redstone signal on incoming wormholes.
  26. 1 point
    Okay thanks for the reports. I reverted the last update so it should be back to normal.
  27. 1 point
  28. 1 point
    Seems like this small script is gone, removed by codepen robots, and i cant find it in my archives. This script was cutted version of .vox converter. You can use it instead, but will need extra work on output. Your comment is my award! Thank you for using it and telling me this.
  29. 1 point

    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' -- }
  30. 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.
  31. 1 point

    unrecoverable error prank

    That is mighty easy. computer.pullSignal = nil
  32. 1 point
    I've modified this to be able to remove either a specific filesystem or the last added filesystem by either passing an address or '.' (for the last added) as the first parameter to the remove command. The second parameter is the forcefully option. so 'rc bundle remove ad432df3 true' (yes, short addresses are allowed).
  33. 1 point
    I had this problem quite a long time ago, and I think I fixed it by also updating the settings client-side to match those on the server.
  34. 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
  35. 1 point

    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
  36. 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
  37. 1 point
    MineOS is half the operating system and half the graphical environment for OpenOS, which comes in OpenComputers mod by default. Oringinally it was developed in Russian, but it supports several languages. MineOS has following features: Multitasking Windowed interface with double buffered graphics context Animations, wallpapers, screensavers and color schemes Language packs and software localization User authorization by password and biometrics Support for file sharing over the local network via modems Support for client connection to real FTP servers Error reporting system with the possibility to send information to developers App Market with enormous amount of wonderful applications and possibility to publish your own programs for every MineOS user An internal IDE with syntax highlighting and debugger Open source system API and detailed illustrated documentations Custom EEPROM firmware with the possibility to select/format the boot volume and Internet recovery Almost complete compatibility with OpenOS software How to install? First, you need to install OpenOS from floppy disk to your HDD. After that you'll be able to run MineOS installer via single command: pastebin run 0nm5b1ju System requirements: Internet Card OpenOS installed on Tier 3 HDD Tier 3 GPU 2x Tier 3 RAM Tier 3 CPU (not really matters, just speed up) Troubleshooting: Are there any problems, suggestions? I'll be glad to see you on the operating system repository: https://github.com/IgorTimofeev/MineOS
  38. 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 )
  39. 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
  40. 1 point

    ocCraft v0.1.2

    ocCraft is a little videogame originated trough a very little OpenComputers game jam. It is currently not much more as the engine but should be easy to modify as long as you have a little practice with lua. Modding You can install/create your own texture packs (also with different resolution) as well as mods with new blocks, entities and biomes (world gen)*. *(technically you can change nearly anything at runtime because the most data are stored in a local table named global which will given to any script at loading.) GitHub: https://github.com/MisterNoNameLP/ocCraft Pastebin (installation script): https://pastebin.com/7h1xNZgt Gameplay: I hope you like the project and have a little bit fun :>
  41. 1 point

    GPS on microcontrollers

    good job on that, started something similar once but got distracted... thanks for sharing
  42. 1 point

    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.
  43. 1 point
  44. 1 point

    Robot-miner with geolyzer

    I present you a program for a robot that allows you to mine ore without going down into the caves. Robot, using a geolyzer, can find and mine ore. All features are not yet implemented, so I ask you to test and inform me about a bugs. Requirements: Computer case (tier II or III) Inventory Upgrade (more the better) Inventory Controller Upgrade Hard Disk Drive EEPROM with Lua BIOS Geolyzer RAM (tier I or higher) CPU (any) Hover Upgrade (tier I) Diamond pickaxe or equivalent tool Optional: Crafting Upgrade Wireless Network Card or Linked Card Solar Generator Upgrade Battery Upgrade Experience Upgrade Chunkloader Upgrade Generator Upgrade Enderchest from EnderStorage mod Installing: Download and save the file as init.lua wget https://raw.githubusercontent.com/DOOBW/geominer/master/miner.lua init.lua Put this file in to root directory of the hard disc. Add the disk when crafting a robot. Place the robot on a solid blocks platform. Give the robot a pickaxe Place a container and the charger near the robot. Press the power button and enjoy a process.
  45. 1 point

    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/.
  46. 1 point

    Introducing "Lunatic"

    No spoiler in the title. Just watch the video.
  47. 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
  48. 1 point

    Draconic Energy Core Monitor

    Program I wrote to monitor my Draconic Evolution Energy Core: -- Original by Merung (October, 2018) local component = require("component") local term = require("term") local gpu = component.gpu -- Setup components if not component.isAvailable("draconic_rf_storage") then print("Draconic Energy Core not connected. Please connect computer to Energy Core with an Adapter") os.exit() end storage = component.draconic_rf_storage if not component.isAvailable("screen") then print("How do you expect to view this?") os.exit() end -- Set Resolution res_x = 120 res_y = 25 gpu.setResolution(res_x, res_y) -- Set Max Value and increment for bottom bars io_max_rate = 600000 io_increment = io_max_rate / 100 -- Functions function exit_msg(msg) term.clear() print(msg) os.exit() end function get_tier_level(maxrf) local tier_level = 0 if maxrf == 45500000 then tier_level = 1 elseif maxrf == 273000000 then tier_level = 2 elseif maxrf == 1640000000 then tier_level = 3 elseif maxrf == 9880000000 then tier_level = 4 elseif maxrf == 59300000000 then tier_level = 5 elseif maxrf == 356000000000 then tier_level = 6 elseif maxrf == 2140000000000 then tier_level = 7 else tier_level = 8 end return tier_level end function convert_value(rf) if rf == 0 then return "0 RF" end local i, units = 1, { "RF", "K RF", "M RF", "G RF", "T RF", "P RF", "E RF", "Y RF" } while rf >= 1000 do rf = rf / 1000 i = i + 1 end local unit = units[ i ] or "?" local fstr if unit == "RF" then fstr = "%.0f %s" else fstr = "%.2f %s" end return string.format( fstr, rf, unit ) end function get_percent_color(energy) local energycolor if energy <= 5 then energycolor = RED elseif energy <= 25 then energycolor = ORANGE elseif energy <= 50 then energycolor = YELLOW elseif energy <= 75 then energycolor = GREEN elseif energy <= 99 then energycolor = BLUE else energycolor = BLACK end return energycolor end function draw_legend(io) gpu.setForeground(fg_default) for loc = 0, 100, 10 do term.setCursor(offset + loc, visual_y_start + 11) term.write(loc) term.setCursor(offset + loc, visual_y_start + 12) term.write("|") end draw_direction(io) end function draw_direction(io) local is_neg local pos_num if io == 0 then return elseif io > 0 then is_neg = 0 pos_num = io elseif io < 0 then is_neg = 1 pos_num = io * -1 end -- Determine how many "=" local num_col = pos_num / io_increment if num_col > 100 then num_col = 100 end if num_col < 1 then num_col = 1 end -- Create the bars local base_bar = "" local base_bar1 = "" local base_bar2 = "" local base_bar3 = "" local num_spaces = 100 - num_col local space_offset = num_spaces / 2 for int_space = 0, space_offset, 1 do base_bar = base_bar .. " " end if is_neg == 1 then base_bar1 = base_bar .. "/" base_bar2 = base_bar .. "<=" base_bar3 = base_bar .. "\\" else base_bar1 = base_bar base_bar2 = base_bar base_bar3 = base_bar end for int_eq = 0, num_col, 1 do base_bar1 = base_bar1 .. "=" base_bar2 = base_bar2 .. "=" base_bar3 = base_bar3 .. "=" end if is_neg == 0 then base_bar1 = base_bar1 .. "\\" base_bar2 = base_bar2 .. "=>" base_bar3 = base_bar3 .. "/" end -- Draw the actual bars if is_neg == 1 then gpu.setForeground(RED) term.setCursor(offset, visual_y_start + 15) term.write(base_bar1) term.setCursor(offset - 1, visual_y_start + 16) term.write(base_bar2) term.setCursor(offset, visual_y_start + 17) term.write(base_bar3) gpu.setForeground(fg_default) else gpu.setForeground(GREEN) term.setCursor(offset, visual_y_start + 15) term.write(base_bar1) term.setCursor(offset, visual_y_start + 16) term.write(base_bar2) term.setCursor(offset, visual_y_start + 17) term.write(base_bar3) gpu.setForeground(fg_default) end end function draw_visuals(percent) term.setCursor(offset, visual_y_start + 13) for check = 0, 100, 1 do if check <= percent then gpu.setForeground(get_percent_color(check)) term.write("|") gpu.setForeground(fg_default) else gpu.setForeground(fg_default) term.write(".") end end end -- Define Colors RED = 0xFF0000 BLUE = 0x0000FF GREEN = 0x00FF00 BLACK = 0x000000 WHITE = 0xFFFFFF PURPLE = 0x800080 YELLOW = 0xFFFF00 ORANGE = 0xFFA500 DARKRED = 0x880000 -- Main Code loopdelay = 1 event_loop = true while event_loop do if not component.isAvailable( "draconic_rf_storage" ) then exit_msg("Energy Core disconnected. Exiting.") end local storedenergyinit = storage.getEnergyStored() local maxenergyinit = storage.getMaxEnergyStored() local iorate = storage.getTransferPerTick() local tier = get_tier_level(maxenergyinit) local percentenergy = storedenergyinit / maxenergyinit * 100 local convstored = convert_value( storedenergyinit ) local convmax = convert_value( maxenergyinit ) offset = 10 visual_y_start = 5 fg_default = WHITE fg_color_max = PURPLE local fg_color_stored = get_percent_color(percentenergy) local fg_color_percent = fg_color_stored local fg_color_io if iorate <= 0 then fg_color_io = RED else fg_color_io = GREEN end if percentenergy <= 99 then gpu.setBackground(BLACK) else gpu.setBackground(DARKRED) end term.clear() gpu.setForeground(fg_color_max) term.setCursor(48, visual_y_start) term.write("Energy Storage Tier: " .. tier) gpu.setForeground(fg_default) term.setCursor(30, visual_y_start + 1) term.write("Current Stored Energy / Max Energy: ") gpu.setForeground(fg_color_stored) term.write(convstored) gpu.setForeground(fg_default) term.write (" / ") gpu.setForeground(fg_color_max) term.write(convmax) gpu.setForeground(fg_default) term.setCursor(44,visual_y_start + 2) term.write("Percent Full: ") gpu.setForeground(fg_color_percent) term.write(string.format("%.12f %s", percentenergy, " %")) gpu.setForeground(fg_default) term.setCursor(48,visual_y_start + 3) term.write("RF/Tick Change: ") gpu.setForeground(fg_color_io) term.write(iorate) draw_visuals(percentenergy) draw_legend(iorate) os.sleep(loopdelay) end
  49. 1 point

    Clock - displays ingame time

    I make is with pseudographics pastebin get wA3Nz2YC clock.lua
  50. 1 point

    The Debugging Guide

    Content Introduction Reproducing an Error Error Messages Debug Output Appendix List of Error Messages Using a Debugger Ad alert: cbrowse Introduction Writing code is one thing, making it work is a completely different story. More often than not something is not working as intended and sometimes your program just crashes the instant you run it. This can be fun and inspiring but most often it is just frustrating. This guide is meant to introduce you to several useful debugging techniques with the primary focus being OpenComputers and Lua. I could use your help to improve this guide. If you spot an error or miss some content: Please tell me! Reproducing an Error Even with maxed out debugging skills you are going to have a hard time fixing a bug if you can't see it. So step one in debugging is finding a way to reproduce the bug. This is something that does not necessarily require programming. You can even do that as a user! It is very good manners to add a step by step instruction to your bug report: Write down every step of what you did to reach the bug. Test this instruction yourself and try to find ways to make it as short as possible. Maybe the work you did before opening *this* file did not have anything to do with your bug. Also try some variations to find out if this bug needs a specific setup or if it happens in a more general use case. If the program had no trouble on a T3 screen but crashes on a T1 screen there might be something involving the resolution or color depth. Does it work with a T2 screen? This makes it very easy to see the bug in action. Even if it is just 1 in 10 times. It helps. Beware of the Heisenbug which only appears when you are not watching it! ;-) Error Messages Debug Output Appendix List of error messages Syntax Error: detected when loading code syntax error near 'x' 'x' expected near 'y' 'a' expected (to close 'b' at line c) near 'c' Most of the time it's just a missing 'end' or bracket. That's easy to see if you use indentation. Sometimes it is a bit harder to find, but b()=2 clearly is not correct. <eof> means the end of file Runtime Error: detected when the code is executed Runtime errors aren't as easy. They can hide in rarely used code and there is a variety of them: bad argument #1 to 'func' ('type' expected, got 'wrongType') You called a function but one of the parameters you've given has the wrong type. You should check the functions documentation and compare to how you use it in your program. attempt to index local/global/field 'name' (a 'type' value) attempt to index a 'type' value You tried to access a table field but there actually was no table you could access. (but nil, a number, a function etc.) Check the return value/variable you are using and work backwards to find out where a check has failed, the value has been overwritten or not written. table index is NaN/nil You tried to access a table using an invalid index. Everything is allowed to be an index except nil and NaN. attempt to call local/global/field 'name' (a 'type' value) attempt to call a 'type' value The return value/variable you tried to call as a function hasn't been a function or a value with a __call metamethod. Using a Debugger In other environments it is possible to use an external program to help debugging, a 'debugger'. This would display and modify the values of variables and would allow to stop the program at previously defined breakpoints. After stopping it is possible to step through the program line by line to check what it is doing. Just to be clear: This is possible in normal Lua but OpenComputers already occupies the same feature to limit execution time. Ad Alert: cbrowse You can easily add advanced debug in/output by installing my program cbrowse. The debug interface works by calling this: local a, b, c = 1, "A", {test = true} require"cbrowse".view(a, b, c) Tables can be manipulated. If you want to change the value of a variable you have to temporarily use a table and manually export the result back to the local variable. local a = 1 local _t = {a = a} require"cbrowse".view(_t) a = _t.a But there is one drawback: None of the events happening while cbrowse runs reach your event.pull in your program. Event listeners work though.
  • 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.