• Content Count

  • Joined

  • Last visited

Community Reputation

31 Excellent

About mikesmullin

  • Rank
    Junior Member

Recent Profile Visitors

972 profile views
  1. More detail on Replicas ## EntityScript Replica Components Replicas only affect the component values of an EntityScript. Adding components to entities is straight-forward, for example: ``` local e = CreateEntity(); e:AddComponent("named"); assert(e.components.named == require("components/named")); ``` By default all components are designed to operate locally. For example, if the following line were evaluated only by the client, it would not change the value for the same component on the same entity on any other simulator on the network: ``` e.components.named:SetName("SecretBilly"); ``` For every component that requires network synchronization, a components/*_replica.lua is created. The name is also registered via AddReplicableComponent(). While the original component and replica component may share the same interface, the replica's job is to sync its data so all machines in the network receive the same values, using netvars and RPC. For example, if the server evaluates the following code, all clients with a copy of the same entity will receive the same changes to their component values, as well: ``` // component names listed in REPLICATABLE_COMPONENTS list // automatically have their replica components added to // the entity during the AddComponent() step above. assert(e.replica.named == require("components/named_replica")); e.replica.named:SetName("EverybodyKnowsBilly"); ``` The named component is a real example, so read its source for more detailed examples.
  2. ## Client / Server Simulation Relationship Mods should use these always to be clear about which side you want code to run on; by default all Lua code runs on BOTH client and server side, and this can be very wasteful! ### Definitions: - client host: DST > Play > Host Game > Generate/Resume World - remote client: DST > Play > Browse Games > Join - dedicated: Steam > Tools > Dont Starve Together Dedicated Server | | client host | remote client | dedicated | ------------------------------------------------------------------ | TheWorld.ismastersim | true | false | true | | TheNet.GetIsServer() | true | false | true | | TheNet.IsDedicated() | false | false | true | | TheNet.GetIsClient() | false | true | false | `TheWorld.ismastersim` == `TheNet:GetIsServer()` // this is running on a computer hosting the game `not TheWorld.ismastersim` == `TheNet:GetIsClient()` // this is running on a computer joining a game `TheNet:IsDedicated()` // this is a headless dedicated server NOTICE client host means client and server share a single simulator; evaluating one instance of the logic for both client and server. ## Netvars (Network Variables) A collection of classes representing platform-agnostic data types; streamed change events synchronize their values over a networked machine cluster. The intended use case for netvars is to be exclusively `:set()` by the server, while `:value()` is read by the client(s). Although `:set_local()` can be used by any side, its most useful on the client-side for network lag interpolation between `:set()` values and subsequent dirty events. The interface for dirty event listeners is `f(e:Entity):Void`. Netvars must be defined on both sending and receiving sides before changing values will cause a sync or dirty event. fig. 1: `Entity:ListenForEvent()` will trigger | if listening from... | and `:set()` on... | | | client host | remote client | dedicated | |----------------------|-------------|---------------|------------| | client host | true | false | - | | remote client | true | false | true | | dedicated | - | false | true | fig. 2: `NetVar:set()` will always change local `NetVar:value()`, but it will only sync | `:value()` of... | if `:set()` on... | | | client host | remote client | dedicated | |----------------------|-------------|---------------|------------| | client host | true | false | - | | remote client | true | false | true | | dedicated | - | false | true | Its not an error to `:set()`, or `:set_local()` from the client, but realize it only changes it for that one local client instance. If you do it mistakenly, you will find the `:value()` is not the same on the server or other clients. If you bind a new netvar to an Entity GUID that only exists on the client, or an Entity that does not have an `:AddNetwork()` component attached to it, it will NOT sync or trigger, neither locally or remotely. Binding a netvar to an Entity GUID that does not exist on the client side will cause a hard crash on the client. Network protocol is an un-encrypted implementation of RakNet mainly udp/10999 http://raknet.com/raknet/manual/ ``` interface NetVar<T> { /** * Register event handler for network variable of a given name. * * @param guid - Entity GUID. * @param name - Network variable name. Must be unique per entity. * @param dirtyEventName - Can be bound by `Entity:ListenForEvent()`. See set() for details. */ public function constructor(guid:GUID, name:String, ?dirtyEventName:String):Void; /** * Unidirectional setter; * - Sets new value locally * - Triggers dirty event listeners (see fig. 1 above) * - Syncs new value from server to client(s) (see fig. 2 above) * * Will no-op unless one of the following is true: * * - given value is different than last value, or; * - `set_local()` used one or more times since last `set()`. */ public function set(value:T):Void; /** * Local-only setter; * Does NOT notify the cluster or trigger dirty event listeners. * * Recommended for frame-rate-dependant interpolation. * (e.g. client makes guesses locally until corrected by the server) */ public function set_local(value:T):Void; /** * Local-only getter; * Return last value received by network sync, :set(), or :set_local(). */ public function value():T; } /** * 1-bit boolean * * Default: false * * e.g., set_local(true); set(true); can be used on net_bool * to transmit event notifications without having to * toggle true on/off between each event. */ interface net_bool extends NetVar<Bool> {}; /** * 8-bit unsigned integer [0..255] */ interface net_byte extends NetVar<Int> {}; /** * array of 8-bit unsigned integers (max size = 31) * * Arrays are expensive; avoid if you will dirty them often. */ interface net_bytearray extends NetVar<Bytes> {}; /** * unsigned 64-bit integer containing entity network id * represents the entity instance */ interface net_entity extends NetVar<Entity> {}; /** * 32-bit float */ interface net_float extends NetVar<Float> {}; /** * 32-bit unsigned integer * * If value is a number, it is forwarded as the hash. * If value is a string, it is converted to a hash before sending. * * REMINDER: The hash algorithm is deterministic, so expect * clients to agree on output value regardless of platform. */ interface net_hash extends NetVar<Hash> {}; /** * 32-bit signed integer [-2147483647..2147483647] */ interface net_int extends NetVar<Int> {}; /** * 16-bit signed integer [-32767..32767] */ interface net_shortint extends NetVar<Int> {}; /** * Maps to an unsigned 32-bit integer. */ interface net_uint extends NetVar<Int> {}; /** * 16-bit unsigned integer [0..65535] */ interface net_ushortint extends NetVar<Int> {}; /** * 3-bit unsigned integer [0..7] */ interface net_tinybyte extends NetVar<Int> {}; /** * 6-bit unsigned integer [0..63] */ interface net_smallbyte extends NetVar<Int> {}; /** * array of 6-bit unsigned integers (max size = 31) * * Arrays are expensive; avoid if you will dirty them often. */ interface net_smallbytearray extends NetVar<Bytes> {}; /** * variable length string */ interface net_string extends NetVar<String> {}; /** * A convenience wrapper over net_bool. * does the set_local(true) set(true) trick for you. * * Use for one-shot triggers. */ interface net_event extends NetVar<String> {}; /** * Remote trigger. * * Like set() but no value is required. */ public function push(): Void; } ```
  3. interactive meaning the debugger pauses the Lua thread and waits for you to step over, step into, step out of, or click continue before proceeding to evaluate the next line of code after a breakpoint, it allows you to evaluate arbitrary lua code at runtime during a breakpoint, set conditional breakpoints, and watch statements. you can walk the stack and inspect scope at each level. that kind of thing.
  4. I'm working on something similar but just using Visual Studio Code. Here's my setup explained. It includes an interactive debugger, and the beginning of compile-time-checked strong typing, and API documentation. Maybe you want to collaborate? https://www.twitch.tv/videos/166601037
  5. Thanks for the techniques and configuration, Jouste! I'm using the pencil tool at 10px, eraser at 25px. Using the Clipping Mask (alt+click between layers) and the lasso tool for scoop shaded shadows. Using top-right lighting. Sketchpad is 2000x2500px @ 96ppi in color #cd7a50. :3 Can't touch that amazing pen control and speed, tho. Will keep practicing... Thanks for these streams.
  6. Toni uses the photoshop brush tool and the brush preset is just the default circle shape ("Hard Round Pressure Size") in the 10px-55px range at 100% hardness. She confirms this in "RWP #144 - Don't Starve Draw Along (Art Stream) • 9 days ago" on Twitch art stream @ 27:45 She uses it for shading and coloring as well. Sometimes with "Lock Transparent Pixels" enabled. Jouste uses the pencil tool at 10px, and eraser at 25px.