Git Product home page Git Product logo

mt-yatm's Introduction

YATM Logo YATM

YATM - Yet Another Tech Mod.

While YATM was originally made as a minecraft mod, I never did enjoy working in Java, so I ported the (incomplete) mod over to minetest and lived happily ever after.

Check each mod for it's own README on what it does.

Requirements

  • Minetest 5.4.x (optionally with LuaJIT for some mods (needed for bit and ffi modules))

Dependencies

Optional

  • mesecons
  • mobkit
  • default

Tests

You may notice a tests/ directory in some of the mod directories, this uses the 'Luna' test module that I originally wrote for a love2d game. Luna was then ported to minetest (along with the Class modules).

It's a rather simple unit test framework that runs during startup, for now tests run on startup, and usually complete within milliseconds, but this will be toggable later once everything has stabilized.

Installation

Grab the latest release or master, master tends to be playable.

Add yatm_core and yatm_oku to your trusted_mods list in minetest's settings.

Or you can just not add them, the mods will disable certain sections and post warnings in the logs.

Some sections will have slower fallback implementations while some features are just completely impossible.

Why does yatm_core and yatm_oku require an insecure_environment?

yatm_core needs bit and ffi, same with yatm_oku.

yatm_core needs it for it's binary buffers which is a faster alternative to its string buffers. These buffers are used to load binary encoded files used by some of the other mods.

The bit module is needed for bit operations in various parts of the code especially in oku which needs to perform bit manipulation.

A lua implementation is provided for the bit module and will allow the binary buffer to exist, however it will be slower than a more native version.

I can promise the worse that will happen is minetest crashes due to a reading mistake.

Game and Modpack creators

YATM has an optional dependency called yatm_prelude, which is purposely not present in this codebase.

It is intended to be used to preconfigure YATM for a game or modpack, simply create a yatm_prelude mod in the game or modpack's mods directory and add the configuration settings in the init.lua.

As of this writing YATM doesn't really have any settings that can be preconfigured to affects its behaviour

yatm_prelude Configuration

This section will be populated when there are actual options to configure.

mt-yatm's People

Contributors

icedragon200 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

mt-yatm's Issues

Thermal Boiler

An alternative boiler that operates off thermal energy

Fluid-Fuel Heater

An alternative to the solid fuel heater that consumes fluids instead to produce heat

Add Deployer

It should be able to place nodes in front of itself, triggered by mesecon and data

It should possible trigger the right-click action of the node it's facing as well.

the use case is to have it place empty crates unto a docking station

DATA network persistence

With so much complexity and state, the network needs to persist the in-flight events in case of a server shutdown to avoid losing something like control events (for memory)

Arithmetic and Logic nodes support constants

At the moment, configuring these abominations requires priming them beforehand with a switch/button or something that emits a data signal

Now the main issue is how difficult it is to actually configure ANY of them, since they have so many ports and requirements just to perform their action.

Related #16, #19

Mod loading problems

(I'm not a native english speaker so I'm sorry if I made any grammar mistakes or typos.)

Minetest version 5.7.0-dev
(followed the minetest documentation for compiling and installed LuaJIT library for LuaJIT support)

OS info: Debian GNU/Linux 11 (bullseye)

Hello, I came across a post you made in minetest forums about this mod and it got my attention, so I decided to try it out.
However, I tried to load the mod but I failed to successfully initialize the mod.

The way that I tried was enable this mod, foundation and nokore_mods under minetest_game. But when I tried to play a world, minetest gave me this error:

ModError: Failed to load and run script from /home/think/minetest/minetest-master/bin/../mods/nokore-mods/nokore_tnt/init.lua:
...etest-master/bin/../mods/nokore-mods/nokore_tnt/init.lua:6: attempt to index global 'foundation' (a nil value)
stack traceback:
	...etest-master/bin/../mods/nokore-mods/nokore_tnt/init.lua:6: in main chunk
Check debug.txt for details.

But foundation was enabled under it, so I thought "It might need the nokore game itself", so I installed the nokore_game and tried to load the mod again under nokore_game (and yes I enabled the dependencies as well).

But when I tried to load the mod, minetest gave me a different error:

ModError: Failed to load and run script from /home/think/minetest/minetest-master/bin/../games/nokore-game/mods/nokore_prelude/init.lua:
..../mods/foundation/foundation_node_sounds/node_sounds.lua:15: a name is required for node sound registries
stack traceback:
	[C]: in function 'assert'
	..../mods/foundation/foundation_node_sounds/node_sounds.lua:15: in function 'initialize'
	...master/bin/../mods/foundation/foundation_class/class.lua:107: in function 'new'
	...er/bin/../games/nokore-game/mods/nokore_prelude/init.lua:8: in main chunk
Check debug.txt for details.

I looked into source code, but I couldn't find anything wrong. I couldn't understand what name is requied.
I hope somebody can assist further for fixing this issue.
Have a great day/night.

Change DATA formspec port configuration page

Currently it's very, very clunky text everywhere and the recent formspec update blew the formatting away.

In short it's due for an overhaul (and just in time to sync with foundation and nokore too).

Instead ports can be paged by their color, and instead of displaying just the text, it can display the connected bus (using the item renderer thing in the formspec), this makes it not only more appeasing but also very easy to identify which side is being configured.

Overhead Rail System

Has nothing to do with the minecart or yatm_rails.

This would be a entirely new system, it would be formed from some simple components:

Nodes

  • Overhead Rail (Straight) - A straight line rail
  • Overhead Rail Stop - Allows a rail device to 'stop' at the location
  • Overhead Rail (Bend 90) - Allows rail corners
  • Overhead Rail (Tee) - Allows rail movement in 3 directions
  • Overhead Rail Riser - Raises or lowers attached rail devices (i.e. allows changes on Y-axis)
  • Docking Chest Station - A simple node that can host a single docking chest, the chest itself can be picked up and carried around with it's inventory intact. The station should implement the item interface, energy interface and fluid interfaces, the type of behaviour is determined by the attached docking object.

Entity

  • Docking Chest - a chest that can be carried by the Overhead Rail Arm and placed unto a new docking chest station
  • Docking Cell - a special chest that can be carried by the Overhead Rail Arm and placed unto a new docking chest station, it can contain energy OR fluids.
  • Overhead Rail Arm - an autonomous arm that can perform a handful of operations, such as picking up or placing special nodes
  • Overhead Rail Hook - allows players to ride the rail system like a minecart, but instead being lifted into the air

DATA Memory node

Finally have an idea of what to do with the Memory node.

Originally I intended to model it after actual memory indexing, but an issue arises from the read/write accesses.

  • It can only store up to 256 bytes of information (so that 16 on top needs to become an 8 in it's texture).
  • It can only write or read a single byte at a time
  • The offset can be adjusted using the Address Port
  • Reads are triggered via the Read Port, the payload is an offset in the memory to read, it will be added to the current Address offset
  • Data for a read port request is sent to the Data Port(s)
  • Data is written via the Write Port, the payload is the data

Questions

Q. Why only 256 bytes?

A. It's manageable as a single string in the node's metadata, anymore will require special handling and or persistence externally, it also leaves room for computers that have upwards of 64k bytes of memory to still be relevant, and most data nodes only operate on bytes (i.e. all arithmetic nodes can only handle 8-bit math)

DATA Splitter

A high-level counter part to the DATA Decoder, the splitter would allow users to specify a 'structure' of the data and then route individual parts to different ports.

Features

  • Users can specify the structure, in terms of bytes, that is, a user can specify 2,2,4, which would split the incoming pdu into smaller pdu's of size 2, 2 and 4 respectively.
Input: \x02\x03\x04\x05\xA0\xA1\xA2\xA3
Output: 1:\x02\x03, 2:\x04\x05, 3:\xA0\xA1\xA2\xA3
  • Users can specify output ports or each part based on the specified structure, there should be a limit to the number of splits allowed (16 to match with the maximum allowed ports on non-multi cables)

DATA Programmer formspec should support boolean as 2nd return value

Normally these formspec functions expect the second argument to be a new formspec, but in the case of DATA programming, the new formspec is normally just a refreshed version of the very same formspec, as such receive_programmer_fields/5 should handle the second return value like so:

local keep_bubbling, formspec_or_refresh_current = receive_programmer_fields(...)

if type(formspec_or_refresh_current) == "boolean" then
  -- call get_programmer_formspec again and use that formspec
elseif type(formspec_or_refresh_current) == "string" then
  -- use the value as a new formspec
end

Do not reset input field in consoles on formspec refresh

Seeing as the only way to 'refresh' a formspec is to straight up reshow it, the input in the user's field must be persisted across refreshes.

At the moment, I do believe it defaults to a blank string, so it's unclear what the behaviour would be if the entire section was omitted.

It's also unclear if the field sends information on input or only on submit.

Add Codex item

Synopsis

YATM has many, many features, of which rely on complex configuration or setup.

The Codex would provide ingame documentation of items, nodes or entities that a player may encounter.

Usage

Players will right click on target nodes, or entities to pull up information on that node in a formspec.

The right click action should ALWAYS open the formspec, even if the target isn't supported by the codex.

Players can additional drop and item, or node into the codex's formspec to perform a 'scan' which will pull up any associated entries similar to it's right click action.

Configuration

Items (craft items, tools and nodes) should define a codex_entry field on their item definition.

This field is a string that points to a registered codex entry.
Optionally the field can be a table, with several fields for defining more complex entries, or for inline entries.

Codex entries can be registered using yatm.codex.register_entry(name, def) similar to any other registration.

Codex entries are made up of rows, which can display text, images or inventory grids (e.g. for demonstrating a setup).

Rows can be further split into pages.

yatm.codex.register_entry('my_mod:entry_1', {
  pages = {
    {
      "This is the first line",
      "This is the second line",
      {
        image = "this would be an image name",
      },
    },
  },
})

Additional Features

Another feature of the codex would be to provide 'demos', demos would be a special value attached to a node item, when a player right clicks the placed demo node it would deploy a demo scene, that is a series of nodes which demonstrate the usage of the node, item etc...

Demos would be registered separately from entries yatm.codex.register_demo(name, def)

Demo

Demos are defined as a table with functions.

yatm.codex.register_demo('my_mod:cool_demo', {
  init = function (pos)
    -- called when a new demo scene is to be constructed
    -- this function should return any 'state' data it wants to, if any
    return assigns
  end,

  build = function (pos, assigns)
    -- pos is the origin of the demo node that was deployed
    -- in the build function, it should clear an area, and place nodes, no additional configuration should be performed here
  end,
  
  configure = function (pos, assigns)
    -- called once build is finished, this function should be used to apply any additional configuration to the built nodes, such as setting energy levels, inventories or ports.
  end,

  done = function (pos, assigns)
     -- called once everything is finished, use this to notify the player, or play some jingle if you'd like
  end,
})

Worldgen Ideas

The world seems kind of barren, YATM can generate some structures through it's codex system and that gave me the idea to generate more complex or broken machines and structures naturally in the world.

This issue will be reserved for those ideas, when and if I get around to it

Biomes

  • Iron Sand Deserts
    A long standing idea is having a desert filled with iron concentrated sand and Fayalite crystals litter the landscape, the sand can be magnetised to seperate the ferrous (i.e. Iron Dust) from other loose particles (i.e. Sand)
    As a hazard, thunderstorms in a Iron desert are common and very dangerous, damaging entities and equipment alike, making it quite difficult to mine

DATA Router

Similar to the Splitter in #10, this will inspect a payload and then determine where it should go

Maybe this can be made redundant with some clever use of the logic+splitter.

But for performance reasons, this may still be the better option.

To limit the complexity, it can only inspect a single byte, of the player's choosing.

And only up to 6 routing conditions can be added.

Conditions should be order dependent.

Logical operators are provided.

Use cases

-- For funsies, a pseudo ipv4 routing system
-- R is router, S is splitter 
-- The could split a single payload across 6 outputs or 6 blocks
R
|-> I -> R
|-> I -> R 
|-> I -> R 
|-> I -> R 
|-> I -> R 
|-> I -> R
-- the first splitters would be used to drop the first byte and route the rest 
-- the second set of routers would repeat what the initial did, sending to another set of splitters
-- until 4 bytes have been consumed, by then the payloads will arrive at it's destination

OKU

OKU is the in-game computer programming and emulation system

TODO

  • Can assemble 6502 source

  • Can execute 6502 binary

  • Additional in-game tools for debugging programs (more on that when we get to that milestone I guess)

  • Determine if it's worth keeping the RISCV ISA

Button system for vector-type DATA IO

So using coloured buttons for the simple IO has proven very useful, the only problem is vector-based io, that is devices that use multiple ports per IO entry are still stuck in the csv format.

The main reason is these vectors tend to very large, almost too large to cleanly represent using the button system, at least not without some tabs

Security system revision

This is about the third revision of YATM's security features (or lack thereof)

YATM devices/machines require quite a lot of configuration (especially when dealing with DATA related devices).

At the moment, YATM doesn't make a lot of effort to show or even set ownership of machines (drones get a quick 'owner' tag, but that's about it), to make matters worse, these devices or machines can contain valuable information or items that shouldn't be exposed under normal circumstances, or shouldn't even be changeable.

Features

  • Nodes can have a 'security' definition (more on that later)
  • Entities can have a 'security' definition
  • Can register new security features
  • Provide API functions for trigger lock checks at any level
  • Tool for inspecting the security features installed on a node/object

Security features to provide

  • Identity - a quick check that the player accessing the node is the authorized player, this is just a quick name check
  • Access Group - similar to Identity, this allows a group of players to access the node/object, groups are defined globally
  • Mechanical Locks - Requires a physical key to access the node/object, this is a form of inventory check
  • Electrical Locks - This is the existing 'chipped' system which uses the access card as the key

Interop with other modules

  • EMP to disable electrical locks
    • Server owners should be able to trigger this feature on/off, to provide exploits if so required

What is a security definition

A security definition is a table that contains a handful of properties and functions (as with any of the definition formats).

Defining security information on object

security = {
  -- Slots tell the security system what meta reference keys to look at to find the 
  -- information needed for the system, it may just be a prefix 
  -- if a MetaSchema is used to represent it
  slots = {"yatmsec_primary", "yatmsec_secondary"}, -- would default to just "yatmsec" if not specified
  slots = function (pos, node) -- a function could be used instead as well
    return {"yatmsec_primary", "yatmsec_secondary"}
  end,
  
  on_install_feature = function (pos, node, slot, data)
    -- called before a feature is installed
    -- developers can modify the data here
    -- or outright reject the installation by returning false
    -- if not defined, it will default to returning true
    -- this can be used to deny use of some features in an object
    return true
  end,

  on_feature_installed = function (pos, node, slot, data)
    -- a callback function when security feature is installed on the object
    -- slot is the name of the slot that the feature was installed in
    -- data contains any additional information, possibly what type of
    -- security feature was installed, and additional parameters
    -- this callback can be used to provide some user feedback, such as a sound effect or particle effect
  end,
}

Defining security types

-- An example of registering a security type for mechanical locks
-- Mechanical locks would include the default carbon steel lock and keys as the unlocking mechanism
yatm.security.register_security_feature("yatm:mechanical_lock", {
  description = "Mechanical Lock",

  -- This function can report different states
  -- First, it can report that a lock can be bypassed (i.e. it's okay)
  -- Second, it can report that a lock cannot be bypassed (e.g. it's locked, or simply denying access)
  -- Thirdly, it can report a delayed, or 'needs' action state (e.g. the player needs to complete a prompt)
  -- yatm_security will provide all these return options as constants in it's API module for ease
  -- yatm.security.OK, yatm.security.REJECT, yatm.security.NEEDS_ACTION
  check_node_lock = function (self, pos, node, player, slot_id, slot_data, data)
    -- player is the player entity that is triggering the lock check, it could also be a different entity, but it likely will be a player for the most part.
    -- slot_id is the name of the slot on the node
    -- slot_data is the table pulled from the meta, containing all the stored information for the lock
    -- data is any additional data that yatm security would provide, such as a password from the user when a NEEDS_ACTION was sent before
    return yatm.security.OK
  end,

  check_object_lock = function (self, object, player, slot_id, slot_data, data)
    -- same as above, but triggered for objects
    return yatm.security.OK
  end,
})

-- An example of a feature that would prompt the user for a password
local function prompt_for_password(pos, node, player, slot_id, slot_data, data, callback)
  -- see above for what each of the parameters are for
  -- callback should be executed when finished, this will let 
  -- yatm security know it can take the security request off ice and resume checks
  local formspec_name = "yatm:password_lock_form"
  local assigns = {
    callback = callback,
    data = data,
  }

  -- normally you wouldn't define the function here, instead you would define it
  -- outside this scope as a generic resuable function and then set data on the 
  -- assigns as needed.
  local on_receive_fields = 
    function (player, form_name, fields, assigns)
      -- the formspec in question should be configured to quit by itself
      -- otherwise you can close it here if you'd like
      assigns.data.password = fields.password
      callback() -- let yatm security know it can resume checks now
      return true -- this is just the receive_fields propogation flag                                   
    end

  yatm_core.bind_on_player_receive_fields(player, formspec_name,
                                          assigns,
                                          on_receive_fields)  
  minetest.show_formspec(player:get_player_name(), formspec_name)  
end

yatm.security.register_security_feature("yatm:password_lock", {
  description = "Password Lock",

  _check_password = function (self, data, slot_data)
    if data.password then
      if data.password == slot_data.secret then
        -- the player provided the correct password, authorize them
        return yatm.security.OK
      else
        -- the player did not provide the correct password, reject access
        return yatm.security.REJECT, 'password incorrect'
      end
    else
      -- no password was provided, prompt the player for a password
      return yatm.security.NEEDS_ACTION, prompt_for_password
    end
  end,

  check_node_lock = function (self, pos, node, player, slot_id, slot_data, data)
    return self:_check_password(data, slot_data)
  end,

  check_object_lock = function (self, object, player, slot_id, slot_data, data)
    return self:_check_password(data, slot_data)
  end,  
})

API mockup

-- Register new security features with register_security_feature
yatm.security.register_security_feature(name: String, definition: Table) :: void

-- Remove existing features with unregister_security_feature
yatm.security.unregister_security_feature(name: String) :: void

-- Retrieve a feature by it's name
yatm.security.get_security_feature(name: String) :: Table

-- Trigger check_node_lock for a specific feature
yatm.security.security_feature_check_node_lock(feature_name: String, pos: Vector, node: NodeRef, player: PlayerRef, slot_id: String, slot_data: Table, data: Table) :: AccessFlag, Function | nil | String
yatm.security.security_feature_check_object_lock(feature_name: String, object: ObjectRef, player: PlayerRef, slot_id: String, slot_data: Table, data: Table) :: AccessFlag, Function | nil | String

-- The execute_* functions will take a callback function which should perform the normal
-- action.
-- check_* functions will return the result from check_lock on the feature, it's up to the caller to deal with it

-- Check all locks on a specific node
-- Use this when all locks need to be checked at once
yatm.security.execute_check_node_locks(pos: Vector, callback: Function) :: void
yatm.security.check_node_locks(pos: Vector) :: yatm.security.AccessFlag, Function | nil | String

-- Check all locks on given object
-- Use this when all locks need to be checked at once
yatm.security.execute_check_object_locks(object: ObjectRef, callback: Function) :: void
yatm.security.check_object_locks(object: ObjectRef) :: yatm.security.AccessFlag, Function | nil | String

-- Check a specific lock on a specific node
yatm.security.execute_check_node_lock(pos: Vector, slot_id: String, callback: Function) :: void
yatm.security.check_node_lock(pos: Vector, slot_id: String) :: yatm.security.AccessFlag, Function | nil | String

-- Check a specific lock on given object
yatm.security.execute_check_object_lock(object: ObjectRef, slot_id: String, callback: Function) :: void
yatm.security.check_object_lock(object: ObjectRef, slot_id: String) :: yatm.security.AccessFlag, Function | nil | String

-- Check for presence of locks with:
yatm.security.has_node_locks(pos: Vector) :: Boolean
yatm.security.has_node_lock(pos: Vector, slot_id: String) :: Boolean
yatm.security.has_object_locks(object: ObjectRef) :: Boolean
yatm.security.has_object_lock(object: ObjectRef, slot_id: String) :: Boolean

-- Retrieve information on a node's locks with the functions below:
-- This retrieves ALL locks on the specific node, the table is indexed by the slot_id
yatm.security.get_node_locks(pos: Vector) :: Table<String, Table> | nil

-- Retrieves the data for the specific lock
yatm.security.get_node_lock(pos: Vector, slot_id: String) :: Table | nil

yatm.security.get_object_locks(object: ObjectRef) :: Table<String, Table> | nil
yatm.security.get_object_lock(object: ObjectRef, slot_id: String) :: Table | nil

Example of security checks

-- Below is an example of performing security checks on DATA style node
-- The node requires that both it's security slots grant access
minetest.register_node("my_mod:my_node", {
  description = "DATA My Node",

  groups = {
    cracky = 1,
    data_programmable = 1, -- needed for the DATA Programmer item
    yatm_data_device = 1, -- just let YATM know this is a DATA device that needs to be re-loaded
  },

  -- boring YATM data boiler plate
  data_network_device = {
    type = "device",
  },
  data_interface = {  
    ... -- omitted information for brevity

    -- A function that will be added to data programmer
    check_formspec_access = function (self, pos, user, pointed_thing, assigns, callback)
      -- this node will just check all of it's security features before allowing itself to be programmed
      yatm.security.execute_check_node_locks(pos, callback)
    end,
  },

  security = {
    slots = {"yatmsec_primary", "yatmsec_secondary"}
  }
})

-- Below is an example of performing security checks on another DATA style node
-- This node however split's it's slots for different access checks
minetest.register_node("my_mod:my_node", {
  description = "DATA My Node",

  groups = {
    cracky = 1,
    data_programmable = 1, -- needed for the DATA Programmer item
    yatm_data_device = 1, -- just let YATM know this is a DATA device that needs to be re-loaded
  },

  -- boring YATM data boiler plate
  data_network_device = {
    type = "device",
  },
  data_interface = {  
    ... -- omitted information for brevity

    -- A function that will be added to data programmer
    check_formspec_access = function (self, pos, user, pointed_thing, assigns, callback)
      -- this node will only check it's yatmsec_dataprog feature on programming
      yatm.security.execute_check_nod_locks(pos, "yatmsec_dataprog", callback)
    end,
  },

  on_rightclick = function (pos, node, user, itemstack, pointed_thing)
    -- this node will only check it's yatmsec_operation feature on right click
    yatm.security.execute_check_nod_locks(pos, "yatmsec_operation", function ()
      -- display default formspec here, or perform some modification to the node
    end)
  end,

  security = {
    slots = {"yatmsec_dataprog", "yatmsec_operation"}
  }
})

Questions

Q. Would I need to include the security mod to add the definition to the node/entity

A. It should not, the definition will be designed as much as possible to only provide needed information to the system and shouldn't need the mod to exist to be defined, if the mod isn't present, the data will just sit there, quietly.

Q. Would I need the security mod to perform access checks?

A. Yes, since the mod would be needed to handle all the different security types

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.