Implemented basic water well and water bucket

This commit is contained in:
zontreck 2024-06-11 00:41:37 -07:00
parent f928139088
commit 3dbc618418
17 changed files with 862 additions and 0 deletions

View file

@ -0,0 +1,210 @@
#include "Common.lsl"
key g_kID=NULL_KEY;
string g_sIngredientType = "none";
integer g_iQuantity = 0;
key g_kFollow = NULL_KEY;
integer g_iProdLink=3;
integer g_iDies=FALSE;
vector g_vScale;
setText() {
llSetText(g_sIngredientType + ": " + (string)g_iQuantity, <1,1,1>, 1);
}
setProductTexture(key kID) {
#ifdef PRODUCT_PRIM
if(g_iProdLink!=-99) {
#ifdef PRODUCT_FACE
llSetLinkTexture(PRODUCT_PRIM, kID, PRODUCT_FACE);
#else
llSetLinkTexture(PRODUCT_PRIM, kID, ALL_SIDES);
#endif
}
#endif
}
stopFollowing(float fOffset) {
if(g_kFollow == NULL_KEY)return;
g_kFollow = NULL_KEY;
llSetTimerEvent(0);
llSetPos(llGetPos() - <0,0,fOffset>);
}
follow(key kID) {
g_kFollow = kID;
llSetTimerEvent(1);
}
vector g_vParticleColor = ZERO_VECTOR;
particles(key kTarget) {
if(kTarget == NULL_KEY) llParticleSystem([]);
else {
llParticleSystem(
[
// texture parameters:
PSYS_SRC_TEXTURE , "",
PSYS_PART_START_SCALE , <0.67,0.58,0.00>, PSYS_PART_END_SCALE , <0.09,0.09,0.00>,
PSYS_PART_START_COLOR , g_vParticleColor, PSYS_PART_END_COLOR , <0.16,0.71,0.83>,
PSYS_PART_START_ALPHA , (float)1.00, PSYS_PART_END_ALPHA , (float)1.00,
// production parameters:
PSYS_SRC_BURST_PART_COUNT , 16,
PSYS_SRC_BURST_RATE , (float)0.10,
PSYS_PART_MAX_AGE , (float)6.54,
PSYS_SRC_MAX_AGE , (float)0.18,
// placement parameters:
PSYS_SRC_PATTERN , 2,
PSYS_SRC_BURST_SPEED_MIN , (float)1.00, PSYS_SRC_BURST_SPEED_MAX , (float)1.00,
PSYS_SRC_BURST_RADIUS , (float)0.00,
// placement parameters (for angles only):
PSYS_SRC_ANGLE_BEGIN , (float)0.00,
PSYS_SRC_ANGLE_END , (float)0.00,
PSYS_SRC_OMEGA , <0.00,0.00,0.00>,
// after-effects & influences:
PSYS_SRC_ACCEL , <0.00,0.00,0.00>,
PSYS_SRC_TARGET_KEY , kTarget,
PSYS_PART_FLAGS , ( 0 // texture & influence options:
// | PSYS_PART_INTERP_COLOR_MASK
| PSYS_PART_INTERP_SCALE_MASK
// | PSYS_PART_BOUNCE_MASK
// | PSYS_PART_WIND_MASK
// | PSYS_PART_FOLLOW_SRC_MASK
| PSYS_PART_FOLLOW_VELOCITY_MASK
| PSYS_PART_TARGET_POS_MASK
// | PSYS_PART_TARGET_LINEAR_MASK
| PSYS_PART_EMISSIVE_MASK
)] );
}
}
default
{
state_entry() {
llLinksetDataReset();
llSetText("Empty", <1,1,1>, 1);
llSay(0, "Freshly initialized");
PROTECT();
XteaKey(PSK);
global_ingredients = getIngredientChannel(NULL_KEY);
llListen(global_ingredients, "", "", "");
particles(NULL_KEY);
setProductTexture(TEXTURE_TRANSPARENT);
llSay(0, "Ready to package");
}
touch_start(integer num_detected)
{
llParticleSystem([]);
if(g_kFollow == NULL_KEY) {
follow(llDetectedKey(0));
}else {
stopFollowing(g_vScale.z-0.2);
}
}
timer () {
g_vScale = llGetAgentSize(g_kFollow);
if(g_vScale == ZERO_VECTOR) {
stopFollowing(g_vScale.z-0.2);
}else {
list lData = llGetObjectDetails(g_kFollow, [OBJECT_POS, OBJECT_ROT]);
vector vPos = llList2Vector(lData,0);
rotation rPos = llList2Rot(lData,1);
llSetRegionPos(vPos + <1.1, -1, 1> * rPos);
}
}
on_rez(integer n) {
llSetText("Empty", <1,1,1>, 1);
llListen(getIngredientChannel(llGetKey()), "", "", "");
setProductTexture(TEXTURE_TRANSPARENT);
// Check if ingredient type was already set. This is not a storage container.
if(g_sIngredientType != "none") {
llWhisper(0, "I spilled in your inventory, consider using a sealed storage container.");
if(g_iDies) llDie();
#ifdef DIES
llDie();
#endif
g_sIngredientType = "none";
g_iQuantity = 0;
g_vParticleColor = ZERO_VECTOR;
setProductTexture(NULL_KEY);
}else {
// Inform any nearby object that is waiting that we've been rezzed
llWhisper(global_ingredients, xtea_encrypt_string(llList2Json(JSON_OBJECT, ["cmd", "alive", "type", INGREDIENT_HOLDER_TYPE])));
}
}
listen(integer c,string n,key i,string m) {
// Decode message
string params = xtea_decrypt_string(m);
// Get operation
if(c == global_ingredients) {
if(g_kID == NULL_KEY) return;
else {
if(llJsonGetValue(params, ["cmd"]) == "query") {
llRegionSayTo(i,c,xtea_encrypt_string(llList2Json(JSON_OBJECT, ["cmd", "reply", "ingredient", g_sIngredientType, "id", g_kID])));
}
}
}else {
if(llJsonGetValue(params, ["cmd"]) == "init") {
g_kID = llGenerateKey();
llSetText("Initializing...", <0.5,0,0>, 1);
} else if(llJsonGetValue(params, ["cmd"]) == "deposit") {
if(g_sIngredientType == "none" || g_sIngredientType == llJsonGetValue(params, ["type"])) {
g_sIngredientType = llJsonGetValue(params, ["type"]);
string sStatus = "fail";
if(g_iQuantity == 0) {
g_iQuantity += (integer)llJsonGetValue(params, ["amount"]);
sStatus = "ok";
setProductTexture(llJsonGetValue(params, ["texture"]));
g_vParticleColor = (vector)llJsonGetValue(params, ["particle"]);
g_iDies = (integer)llJsonGetValue(params, ["dies"]);
particles(llGetKey());
llMessageLinked(LINK_SET, 0, "", "");
}
setText();
llRegionSayTo(i, getIngredientChannel(NULL_KEY), xtea_encrypt_string(llList2Json(JSON_OBJECT, ["cmd", "deposit_reply", "status", sStatus])));
particles(NULL_KEY);
}
} else if(llJsonGetValue(params, ["cmd"]) == "use" && llJsonGetValue(params, ["id"]) == g_kID) {
particles(i);
if(g_iQuantity==0) {
llRegionSayTo(i,global_ingredients,llList2Json(JSON_OBJECT, ["cmd", "use_reply", "id", NULL_KEY, "amount", 0]));
return;
}
g_iQuantity--;
llRegionSayTo(i,global_ingredients,llList2Json(JSON_OBJECT, ["cmd", "use_reply", "id", g_kID, "amount", 1, "ingredient", g_sIngredientType]));
setText();
if(g_iQuantity<=0) {
g_iQuantity=0;
setProductTexture(TEXTURE_TRANSPARENT);
g_sIngredientType = "none";
#ifdef DIES
llDie();
#endif
if(g_iDies) llDie();
}
}
}
}
}

41
LSL/raw/discord.lsl Normal file
View file

@ -0,0 +1,41 @@
#include "Common.lsl"
SendUserMessage(string sMessage, integer iError) {
integer iUseTitle=1;
if(llStringLength(sMessage) > 255) iUseTitle=0;
string sJson = llList2Json(JSON_OBJECT, [
"content", JSON_NULL,
"attachments", llList2Json(JSON_ARRAY, []),
"username", "Farm Servers",
"avatar_url", "https://media.discordapp.net/attachments/836451385733021706/1238977979141591081/second-life-icon-25-3810850605.png?ex=66413fa9&is=663fee29&hm=f92e5dceb842992fcc56cfde3dce306da91412eb12f3ca8ebfab4ed2c163115a&=&format=webp&quality=lossless&width=500&height=500",
"embeds", llList2Json(JSON_ARRAY, [
llList2Json(JSON_OBJECT, [
"footer", llList2Json(JSON_OBJECT, [
"text", "Aria's Creations Discord Relay v" + VERSION
]),
"timestamp", llGetTimestamp()
])
])
]);
if(iUseTitle)
sJson = llJsonSetValue(sJson, ["embeds", 0, "title"], sMessage);
else sJson = llJsonSetValue(sJson, ["embeds", 0, "description"], sMessage);
llHTTPRequest(g_sNotifyURL, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/json"], sJson);
llSay(0, "Message Sent!");
}
default
{
state_entry()
{
}
}

89
LSL/raw/item_server.lsl Normal file
View file

@ -0,0 +1,89 @@
#include "Common.lsl"
string API_SERVER;
integer g_iActive = 1;
integer g_iRegistered=0;
default {
state_entry() {
llSay(0, "Server '" + llGetObjectDesc() + "' is starting up...");
llMessageLinked(LINK_SET, 2, "", "");
llMessageLinked(LINK_SET, -1, "", "");
XteaKey(PSK);
}
link_message(integer s,integer n,string m,key i) {
if(n == 0x004f) {
API_SERVER = DecipherService(m, "api");
if(g_iRegistered)return;
// Register the server object ID
llHTTPRequest(API_SERVER + "/zni/Put_Server_ID.php?NAME=" + llEscapeURL(llGetObjectDesc()) + "&PSK=" + llEscapeURL(SERVER_PSK), [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/json"], llList2Json(JSON_OBJECT, ["id", llGetKey()]));
llMessageLinked(LINK_SET, 1, "", "");
}
}
http_response(key k, integer s, list m, string b) {
if(s == 200) {
llMessageLinked(LINK_SET, 0, "", "");
llSay(0, "Server '" + llGetObjectDesc() +"' is now ready");
g_iRegistered=TRUE;
llSetTimerEvent(1);
}
}
touch_start(integer t) {
if(llDetectedKey(0) == llGetOwner()) {
g_iActive = 1-g_iActive;
if(g_iActive) {
llSay(0, "Server '" + llGetObjectDesc() + "' reactivating...");
llResetScript();
} else {
llMessageLinked(LINK_SET, 2, "", "");
llSay(0, "Server '" + llGetObjectDesc() + "' has been taken offline for maintenance. Any pending requests will still be processed, but any new ones will be blocked");
llHTTPRequest(API_SERVER + "/zni/Del_Server_ID.php?NAME=" + llEscapeURL(llGetObjectDesc()) + "&PSK=" + llEscapeURL(SERVER_PSK), [], "");
}
}
}
timer() {
llGetNextEmail("", "");
}
on_rez(integer t) {
llResetScript();
}
email(string time, string address, string subject, string body, integer num_remain) {
if(subject == "RequestProductDelivery") {
//llSay(0, "EMAIL : " + body);
llMessageLinked(LINK_SET, 1, "", "");
list lPar = llParseString2List(body, [";;"], []);
string sPayload = xtea_decrypt_string(llList2String(lPar,1));
// Check what object is being requested and by who
string sRequest = llJsonGetValue(sPayload, ["item"]);
string sID = llJsonGetValue(sPayload, ["id"]);
// Forbid giving scripts
if(llGetInventoryType(sRequest) == INVENTORY_SCRIPT) return;
// Deliver if we have the item
if(llGetInventoryType(sRequest) != INVENTORY_NONE) {
llGiveInventory(sID, sRequest);
llWhisper(999, sPayload);
}
else
{
// Log this as an error in delivery
llWhisper(998, sPayload);
}
llSleep(0.25);
llMessageLinked(LINK_SET, 0, "", "");
}
}
}

View file

@ -0,0 +1,67 @@
#include "Common.lsl"
integer global_ingredients;
list g_lDiscovered = [];
key g_kAv;
integer g_iChannel;
integer g_iListen;
default
{
state_entry()
{
XteaKey(PSK);
global_ingredients = getIngredientChannel(NULL_KEY);
llListen(global_ingredients, "", "", "");
llOwnerSay("Listening on " + (string)global_ingredients);
}
touch_start(integer t) {
if(g_kAv != "") {
return;
}
g_lDiscovered = [];
llSay(0, "Looking for nearby ingredients...");
llWhisper(global_ingredients, xtea_encrypt_string(llList2Json(JSON_OBJECT, ["cmd", "query"])));
llSetTimerEvent(3);
g_kAv = llDetectedKey(0);
}
timer() {
list lOpts = StrideOfList(g_lDiscovered, 3, 1, -1);
g_iChannel = llRound(llFrand(0xFFFF));
g_iListen = llListen(g_iChannel, "", "", "");
llDialog(g_kAv, "What item do you want to delete?", lOpts, g_iChannel);
llSetTimerEvent(0);
}
listen(integer c,string n,key i,string m) {
if(c == global_ingredients) {
string params = xtea_decrypt_string(m);
if(llJsonGetValue(params,["cmd"]) == "reply"){
g_lDiscovered += [llJsonGetValue(params,["id"]), llJsonGetValue(params, ["ingredient"]), i];
llWhisper(0, "Discovered: " + llJsonGetValue(params, ["ingredient"]));
}
} else if(c == g_iChannel) {
integer iIndex = llListFindList(g_lDiscovered, [m]);
if(iIndex == -1) {
llResetScript();
} else {
string sID = llList2String(g_lDiscovered, iIndex-1);
string sObj = llList2String(g_lDiscovered, iIndex+1);
integer iChan = getIngredientChannel(sObj);
llRegionSayTo(sObj, iChan, xtea_encrypt_string(llList2Json(JSON_OBJECT, ["cmd", "use", "id", sID])));
llResetScript();
}
}
}
}

13
LSL/raw/tree.lsl Normal file
View file

@ -0,0 +1,13 @@
#include "Common.lsl"
integer g_iStartedGrowing;
integer g_iWater;
default
{
state_entry()
{
g_iStartedGrowing = (integer)llLinksetDataRead("progress");
g_iWater = (integer)llLinksetDataRead("water");
}
}

215
LSL/raw/water_well.lsl Normal file
View file

@ -0,0 +1,215 @@
#include "Common.lsl"
integer g_iLastFillTime;
integer g_iTotalWater;
integer g_iWellChannel;
integer g_iWellListener;
string WATER_TEXTURE = "333d2eb0-f8c3-2c2e-3371-43df880ad2bf";
vector WATER_PARTICLE = <0.20,0.36,0.79>;
string API_SERVER="nset";
key g_kAv=NULL_KEY;
float g_fEmpty = -1.142;
float g_fFull = -0.202;
integer g_iRequestTime = 0;
string WATER_WELL_NAME = "WoodStoneWaterWell";
string VERSION = "1.0.0";
integer g_iWaterPrim;
integer g_iRoofPrim;
integer g_iDestroyed = 0;
float getScaledValue(integer percentage) {
// Ensure the percentage is within the range 0-100
if (percentage < 0) percentage = 0;
if (percentage > 100) percentage = 100;
// Calculate the scaled value
float scaledValue = g_fEmpty + ((g_fFull - g_fEmpty) * (percentage / 100.0));
return scaledValue;
}
setText() {
llSetText("Water Well\nFill Level: " +(string)g_iTotalWater + "%", <1,1,1>, 1);
}
updateLevel() {
llSetLinkPrimitiveParams(2, [PRIM_POS_LOCAL, <0,0,getScaledValue(g_iTotalWater)>]);
}
SCAN() {
integer i;
integer end = llGetNumberOfPrims();
for(i=LINK_ROOT;i<=end;i++){
string sName = llGetLinkName(i);
if(sName == "water") g_iWaterPrim = i;
if(sName == "roof") g_iRoofPrim = i;
}
if(!g_iWaterPrim || !g_iRoofPrim) {
llSay(0, "Something is wrong, either the water of roof was not detected");
}
}
default
{
state_entry()
{
llLinksetDataReset();
XteaKey(PSK);
PROTECT();
llSay(0, "Scanning for needed linked prims...");
SCAN();
llSay(0, "Scan completed");
llSay(0, "Ready to be packaged");
global_ingredients = getIngredientChannel(NULL_KEY);
llListen(global_ingredients, "", "", "");
g_iTotalWater = 100;
updateLevel();
setText();
}
listen(integer c,string n,key i,string m) {
string sJson = xtea_decrypt_string(m);
if(llJsonGetValue(sJson, ["cmd"]) == "alive" && llJsonGetValue(sJson, ["type"]) == "Bucket") {
if(g_kAv != NULL_KEY) {
g_iTotalWater--;
g_iLastFillTime = llGetUnixTime();
llSetTimerEvent(1);
g_kAv = NULL_KEY;
integer iChannel = getIngredientChannel(i);
llSleep(2);
llRegionSayTo(i, iChannel, xtea_encrypt_string(llList2Json(JSON_OBJECT, ["cmd", "init"])));
llSleep(1);
llRegionSayTo(i, iChannel, xtea_encrypt_string(llList2Json(JSON_OBJECT, ["cmd", "deposit", "type", "Water", "amount", 4, "texture", WATER_TEXTURE, "particle", WATER_PARTICLE, "dies", 1])));
setText();
updateLevel();
}
}
}
on_rez(integer t) {
// Start the timer
g_iLastFillTime = llGetUnixTime();
llSetTimerEvent(1);
if(g_iWellChannel != 0) {
llListenRemove(g_iWellListener);
}
g_iWellChannel = (integer)("0x" + llGetSubString(llGetKey(), 0, 5));
g_iWellListener = llListen(g_iWellChannel, "", "", "");
setText();
}
link_message(integer s,integer n,string m,key i) {
if(n == 0x004f) {
API_SERVER = DecipherService(m, "api") + "/zni";
}
}
changed(integer c) {
if(c & CHANGED_OWNER) {
// pre-fill water
g_iTotalWater = 100;
} else if(c & CHANGED_REGION_START) {
// Check for a product update
llHTTPRequest(API_SERVER + "/Modify_Product_V2.php", [HTTP_MIMETYPE, "application/json", HTTP_METHOD, "POST"], llList2Json(JSON_OBJECT, ["psk", SERVER_PSK, "op", "get", "name", WATER_WELL_NAME]));
}
}
timer() {
if(llGetUnixTime() > (g_iLastFillTime + 30)) {
g_iLastFillTime = llGetUnixTime();
g_iTotalWater ++;
updateLevel();
if(g_iTotalWater >= 100) {
g_iTotalWater = 100;
llSetTimerEvent(0);
llLinksetDataWrite("water", (string)g_iTotalWater);
}
setText();
}
}
touch_start(integer t) {
if(g_iDestroyed) {
llSay(0, "The well appears to have sustained a lot of damage. You'll need to construct a new one.");
return;
}
if(g_iTotalWater == 0) {
llSay(0, "The well is currently empty. Come back later");
return;
}
if(API_SERVER == "nset") {
llWhisper(0, "Still waiting for API Server...");
llMessageLinked(LINK_SET, -1, "", "");
return;
}
if(g_kAv == NULL_KEY) {
g_kAv = llDetectedKey(0);
g_iRequestTime = llGetUnixTime();
//llRezObject("Water Bucket [AC]", llGetPos() + <2,0,0>, ZERO_VECTOR, ZERO_ROTATION, g_iWellChannel);
llHTTPRequest(API_SERVER + "/Get_Server_ID.php?NAME=Farming", [], "");
llWhisper(0, "Requesting a bucket...");
llSetText("BUSY", <1,0,0>,1);
} else {
if(llGetAgentSize(g_kAv) == ZERO_VECTOR) {
llWhisper(0, "I was previously in use, the person seems to have left the region. Try again now");
g_kAv = NULL_KEY;
setText();
}else {
llWhisper(0, "I am currently in use, please be patient");
if(llGetUnixTime() > g_iRequestTime + 120) {
llWhisper(0, "2 minutes have passed, clearing busy status");
g_kAv = NULL_KEY;
g_iRequestTime = 0;
setText();
}
}
}
}
http_response(key kID, integer iStatus, list lMeta, string sBody) {
list lParams = llParseString2List(sBody, [";", ";;"], []);
string sScript = llList2String(lParams,0);
//llSay(0, sBody);
if(sScript == "GetServerID") {
string sJson = llList2String(lParams,1);
g_sServerID = llJsonGetValue(sJson, ["id"]);
requestProductForDelivery("Water Bucket [AC]", g_kAv);
}else if(sScript == "Modify_ProductV2") {
// Gives the version information
string sJson = llList2String(lParams,1);
if(llJsonGetValue(sJson, ["status"]) == "ok") {
// We now have the effective version, check it
if(llJsonGetValue(sJson, ["version"]) != VERSION) {
// Do what needs doing
llSetLinkTexture(g_iRoofPrim, TEXTURE_TRANSPARENT, ALL_SIDES);
llSetLinkTexture(g_iWaterPrim, TEXTURE_TRANSPARENT, ALL_SIDES);
g_iDestroyed=1;
}
}
}
}
}