From dd049be341439b89842789cf336c84dbbda23bda Mon Sep 17 00:00:00 2001 From: Redo Date: Wed, 26 Feb 2025 17:36:12 -0700 Subject: [PATCH] add box features --- classes/server/duplimode/boxselect.cs | 21 +- classes/server/duplimode/fillcolor.cs | 4 +- classes/server/duplimode/plantcopy.cs | 27 +- classes/server/duplimode/stackselect.cs | 11 +- classes/server/selection.cs | 553 +++++++++++++++--------- client.cs | 29 ++ description.txt | 6 +- readme.md | 29 ++ scripts/client/controls.cs | 116 +++++ scripts/client/guis/fillwrench.gui | 507 ++++++++++++++++++++++ scripts/client/handshake.cs | 33 ++ scripts/client/wrench.cs | 164 +++++++ scripts/server/commands.cs | 157 ++++--- scripts/server/functions.cs | 73 +++- scripts/server/handshake.cs | 34 +- scripts/server/images.cs | 22 +- scripts/server/logicFillBus.cs | 29 ++ scripts/server/modes.cs | 6 +- scripts/server/prefs.cs | 8 +- server.cs | 5 +- v20fix.cs | 15 - 21 files changed, 1510 insertions(+), 339 deletions(-) create mode 100644 client.cs create mode 100644 readme.md create mode 100644 scripts/client/controls.cs create mode 100644 scripts/client/guis/fillwrench.gui create mode 100644 scripts/client/handshake.cs create mode 100644 scripts/client/wrench.cs create mode 100644 scripts/server/logicFillBus.cs delete mode 100644 v20fix.cs diff --git a/classes/server/duplimode/boxselect.cs b/classes/server/duplimode/boxselect.cs index bbefad8..c7ab9e9 100644 --- a/classes/server/duplimode/boxselect.cs +++ b/classes/server/duplimode/boxselect.cs @@ -1,3 +1,5 @@ +//bls 4 + // This file should not exist. Fix later... // ------------------------------------------------------------------- @@ -200,6 +202,21 @@ function NDM_BoxSelect::onSelectObject(%this, %client, %obj, %pos, %normal) %client.ndUpdateBottomPrint(); } +function ndRound(%v, %step) { + return mFloor(%v/%step + 0.5)*%step; +} + +function ndCorrectBox(%box) { + %xl = ndRound(getWord(%box, 0), 0.5); + %yl = ndRound(getWord(%box, 1), 0.5); + %zl = ndRound(getWord(%box, 2), 0.2); + %xh = ndRound(getWord(%box, 3), 0.5); + %yh = ndRound(getWord(%box, 4), 0.5); + %zh = ndRound(getWord(%box, 5), 0.2); + %box2 = %xl SPC %yl SPC %zl SPC %xh SPC %yh SPC %zh; + return %box2; +} + function ndGetBoxFromRom(%b) { %db = %b.getDatablock(); %box = %b.getWorldBox(); @@ -207,7 +224,7 @@ function ndGetBoxFromRom(%b) { %bh = getWords(%box, 3, 5); %bl = vectorAdd(%bl, "0 0 " SPC (%db.brickSizeZ * 0.2)); %bh = vectorAdd(%bh, "0 0 " SPC (%db.logicRomZ * 0.2)); - return %bl SPC %bh; + return ndCorrectBox(%bl SPC %bh); } function ndGetBoxFromZone(%b) { @@ -216,7 +233,7 @@ function ndGetBoxFromZone(%b) { %scale = %z.getScale(); %sx = getWord(%scale, 0); %sy = getWord(%scale, 1); %sz = getWord(%scale, 2); %bl = %pos; %bh = vectorAdd(%pos, %sx SPC (-%sy) SPC %sz); - return %bl SPC %bh; + return ndCorrectBox(%bl SPC %bh); } diff --git a/classes/server/duplimode/fillcolor.cs b/classes/server/duplimode/fillcolor.cs index 3361312..0cc2723 100644 --- a/classes/server/duplimode/fillcolor.cs +++ b/classes/server/duplimode/fillcolor.cs @@ -48,7 +48,7 @@ function NDM_FillColor::onPlantBrick(%this, %client) //Admin limit if($Pref::Server::ND::PaintAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Paint Mode is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Paint Mode is admin only. Ask an admin for help."); return; } @@ -63,7 +63,7 @@ function NDM_FillColor::onPlantBrick(%this, %client) //Admin limit if($Pref::Server::ND::PaintFxAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Paint Fx Mode is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Paint Fx Mode is admin only. Ask an admin for help."); return; } diff --git a/classes/server/duplimode/plantcopy.cs b/classes/server/duplimode/plantcopy.cs index 14d5568..95dd52a 100644 --- a/classes/server/duplimode/plantcopy.cs +++ b/classes/server/duplimode/plantcopy.cs @@ -1,3 +1,5 @@ +//bls 4 + // This file should not exist. Fix later... // ------------------------------------------------------------------- @@ -26,6 +28,7 @@ function NDM_PlantCopy::onChangeMode(%this, %client, %nextMode) { %client.ndSelection.deleteData(); } + %client.ndOwnership = false; } //Kill this mode @@ -33,6 +36,7 @@ function NDM_PlantCopy::onKillMode(%this, %client) { //Destroy the selection %client.ndSelection.delete(); + %client.ndOwnership = false; } @@ -112,12 +116,21 @@ function NDM_PlantCopy::onPlantBrick(%this, %client) { if($Pref::Server::ND::FloatAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Force Plant has been disabled because it is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Force Plant has been disabled because it is admin only. Ask an admin for help."); %client.ndForcePlant = false; } } - %this.conditionalPlant(%client, %client.ndForcePlant); + if(%client.ndOwnership) { + if(!%client.isAdmin) { + %client.ndOwnership = false; + ndmessageClient(%client, '', "\c6Ownership plant has been disabled because it is admin only."); + } + } + + %this.conditionalPlant(%client, %client.ndForcePlant, %client.ndOwnership); + + %client.ndOwnership = false; } //Cancel Brick @@ -160,7 +173,9 @@ function NDM_PlantCopy::getBottomPrint(%this, %client) %l0 = "Pivot: \c3" @ (%client.ndPivot ? "Whole Selection" : "Start Brick") @ "\c6 [Prev Seat]"; - if(isObject(%client.ndSelection.targetGroup)) + if(%client.ndOwnership) + %l1 = "Planting as: Original Owner"; + else if(isObject(%client.ndSelection.targetGroup)) %l1 = "Planting as: \c3" @ %client.ndSelection.targetGroup.name; else %l1 = "Size: \c3" @ %x @ "\c6 x \c3" @ %y @ "\c6 x \c3" @ %z @ "\c6 Plates"; @@ -222,7 +237,7 @@ function NDM_PlantCopy::moveBricksTo(%his, %client, %pos, %normal) } //Check time limit and attempt to plant bricks -function NDM_PlantCopy::conditionalPlant(%this, %client, %force) +function NDM_PlantCopy::conditionalPlant(%this, %client, %force, %ownership) { //Check timeout if(!%client.isAdmin && %client.ndLastPlantTime + ($Pref::Server::ND::PlantTimeoutMS / 1000) > $Sim::Time) @@ -252,7 +267,7 @@ function NDM_PlantCopy::conditionalPlant(%this, %client, %force) getTrustLevel(%client, %client.ndSelection.targetGroup) < 1 && (!%client.isAdmin || !$Pref::Server::ND::AdminTrustBypass2)) { - messageClient(%client, '', "\c6You need build trust with \c3" + ndmessageClient(%client, '', "\c6You need build trust with \c3" @ %client.ndSelection.targetGroup.name @ "\c6 to plant bricks in their group."); return; @@ -264,5 +279,5 @@ function NDM_PlantCopy::conditionalPlant(%this, %client, %force) %ang = %client.ndSelection.ghostAngleID; %client.ndSetMode(NDM_PlantCopyProgress); - %client.ndSelection.startPlant(%pos, %ang, %force); + %client.ndSelection.startPlant(%pos, %ang, %force, %ownership); } diff --git a/classes/server/duplimode/stackselect.cs b/classes/server/duplimode/stackselect.cs index df49ace..9085808 100644 --- a/classes/server/duplimode/stackselect.cs +++ b/classes/server/duplimode/stackselect.cs @@ -1,3 +1,5 @@ +//bls 4 + // This file should not exist. Fix later... // ------------------------------------------------------------------- @@ -71,8 +73,13 @@ function NDM_StackSelect::onSelectObject(%this, %client, %obj, %pos, %normal) //Start selection %client.ndSetMode(NDM_StackSelectProgress); - - if(%client.ndMultiSelect) + + if(%client.ndSelection.brickCount==0) + %client.ndInitialMultiSelect = %client.ndMultiSelect; + + if(%client.ndInitialMultiSelect) + %client.ndSelection.startStackSelectionAdditive(%obj, 2, %client.ndLimited); + else if(%client.ndMultiSelect) %client.ndSelection.startStackSelectionAdditive(%obj, %client.ndDirection, %client.ndLimited); else %client.ndSelection.startStackSelection(%obj, %client.ndDirection, %client.ndLimited); diff --git a/classes/server/selection.cs b/classes/server/selection.cs index 9f7ca6d..aa36651 100644 --- a/classes/server/selection.cs +++ b/classes/server/selection.cs @@ -1,3 +1,5 @@ +//bls 3 + // This file is way too big. Fix later... // ------------------------------------------------------------------- @@ -11,6 +13,7 @@ // $NS[%s, "P", %i] - Position // $NS[%s, "R", %i] - Rotation +// $NS[%s, "O", %i] - Owner BL_ID // $NS[%s, "NT", %i] - Brick name // $NS[%s, "HN", %n] - Name exists in selection // $NS[%s, "PR", %i] - Print @@ -123,6 +126,50 @@ function ND_Selection::onRemove(%this) //Stack Selection ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function ndBoxSearchAdjacentBricks(%brick, %boxadd, %limited){ + %box = %brick.getWorldBox(); + %boxsize = vectorSub(getWords(%box, 3, 5), getWords(%box, 0, 2)); + %boxsize = vectorAdd(%boxsize, %boxadd); + //%mask = %limited ? $TypeMasks::FxBrickObjectType : $TypeMasks::FxBrickAlwaysObjectType; + %mask = $TypeMasks::FxBrickAlwaysObjectType; + initContainerBoxSearch(%brick.getPosition(), %boxsize, %mask); +} +function ndGetNextAdjacentBrick(%brick, %limited) { + if($ND_boxSearchDir$="" || $ND_boxSearchBrick!=%brick) { + $ND_boxSearchDir = 1; + $ND_boxSearchBrick = %brick; + ndBoxSearchAdjacentBricks(%brick, "0.2 -0.2 -0.2", %limited); + } + for(%i=0; %i<100; %i++) { + //while(true) { + %brick2 = containerSearchNext(); + //echo(%i SPC %brick2); + if(%brick2) { + //if(%brick2.colorId==%brick.colorId && %brick2!=%brick) { + if( + (!%limited || %brick2.colorId==%brick.colorId) && + %brick2!=%brick + ) { + //echo("hit"); + return %brick2; + } + } else { + if($ND_boxSearchDir==1) { + $ND_boxSearchDir = 2; + ndBoxSearchAdjacentBricks(%brick, "-0.2 0.2 -0.2", %limited); + } else if($ND_boxSearchDir==2) { + $ND_boxSearchDir = 3; + ndBoxSearchAdjacentBricks(%brick, "-0.2 -0.2 0.2", %limited); + } else { + $ND_boxSearchDir = ""; + $ND_boxSearchBrick = ""; + return 0; + } + } + + } +} + //Begin stack selection function ND_Selection::startStackSelection(%this, %brick, %direction, %limited) { @@ -158,7 +205,27 @@ function ND_Selection::startStackSelection(%this, %brick, %direction, %limited) %bl_id = %this.client.bl_id; //Add bricks connected to the first brick to queue (do not register connections yet) - if(%direction == 1) + if(%direction==2) { + while(%nextBrick = ndGetNextAdjacentBrick(%brick, %limited)) { + //If the brick is not in the list yet, add it to the queue + if($NS[%this, "I", %nextBrick] $= "") + { + if(%queueCount >= %brickLimit) + continue; + + //Check trust + if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + { + %trustFailCount++; + continue; + } + + $NS[%this, "B", %queueCount] = %nextBrick; + $NS[%this, "I", %nextBrick] = %queueCount; + %queueCount++; + } + } + } else if(%direction == 1) { //Set lower height limit %heightLimit = %this.minZ - 0.01; @@ -167,7 +234,6 @@ function ND_Selection::startStackSelection(%this, %brick, %direction, %limited) for(%i = 0; %i < %upCount; %i++) { %nextBrick = %brick.getUpBrick(%i); - //If the brick is not in the list yet, add it to the queue if($NS[%this, "I", %nextBrick] $= "") { @@ -286,110 +352,137 @@ function ND_Selection::startStackSelectionAdditive(%this, %brick, %direction, %l %admin = %this.client.isAdmin; %group = %this.client.brickGroup.getId(); %bl_id = %this.client.bl_id; + + if(%direction==2) { + %conns = 0; + + while(%nextBrick = ndGetNextAdjacentBrick(%brick, %limited)) { + //If the brick is not in the list yet, add it to the queue + %nId = $NS[%this, "I", %nextBrick]; - //Add bricks connected to the first brick to queue (do not register connections yet) - if(%direction == 1) - { - //Set lower height limit - %heightLimit = getWord(%brick.getWorldBox(), 2) - 0.01; - } - else - { - //Set upper height limit - %heightLimit = getWord(%brick.getWorldBox(), 5) + 0.01; - } - - //Process all up bricks - %upCount = %brick.getNumUpBricks(); - - for(%i = 0; %i < %upCount; %i++) - { - %nextBrick = %brick.getUpBrick(%i); - - //If the brick is not in the list yet, add it to the queue - %nId = $NS[%this, "I", %nextBrick]; - - if(%nId $= "") - { - //Don't add up bricks if we're searching down - if(%direction != 1) - continue; - - if(%queueCount >= %brickLimit) - continue; - - //Check trust - if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + if(%nId $= "") { - %trustFailCount++; - continue; + if(%queueCount >= %brickLimit) + continue; + + //Check trust + if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + { + %trustFailCount++; + continue; + } + + $NS[%this, "B", %queueCount] = %nextBrick; + $NS[%this, "I", %nextBrick] = %queueCount; + %queueCount++; } - - $NS[%this, "B", %queueCount] = %nextBrick; - $NS[%this, "I", %nextBrick] = %queueCount; - %queueCount++; } - else if(%brickIsNew) + } else { + + //Add bricks connected to the first brick to queue (do not register connections yet) + if(%direction == 1) { - //If this brick already exists, we have to add the connection now - //(Start brick won't be processed again unlike the others) - $NS[%this, "C", %brickIndex, %conns] = %nId; - %conns++; - - %ci = $NS[%this, "N", %nId]++; - $NS[%this, "C", %nId, %ci - 1] = %brickIndex; - - if(%ci > %this.maxConnections) - %this.maxConnections = %ci; - - %this.connectionCount++; + //Set lower height limit + %heightLimit = getWord(%brick.getWorldBox(), 2) - 0.01; } - } - - //Process all down bricks - %downCount = %brick.getNumDownBricks(); - - for(%i = 0; %i < %downCount; %i++) - { - %nextBrick = %brick.getDownBrick(%i); - - //If the brick is not in the list yet, add it to the queue - %nId = $NS[%this, "I", %nextBrick]; - - if(%nId $= "") + else { - //Don't add down bricks if we're searching up - if(%direction == 1) - continue; + //Set upper height limit + %heightLimit = getWord(%brick.getWorldBox(), 5) + 0.01; + } - if(%queueCount >= %brickLimit) - continue; + //Process all up bricks + %upCount = %brick.getNumUpBricks(); - //Check trust - if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + for(%i = 0; %i < %upCount; %i++) + { + %nextBrick = %brick.getUpBrick(%i); + + //If the brick is not in the list yet, add it to the queue + %nId = $NS[%this, "I", %nextBrick]; + + if(%nId $= "") { - %trustFailCount++; - continue; + //Don't add up bricks if we're searching down + if(%direction != 1) + continue; + + if(%queueCount >= %brickLimit) + continue; + + //Check trust + if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + { + %trustFailCount++; + continue; + } + + $NS[%this, "B", %queueCount] = %nextBrick; + $NS[%this, "I", %nextBrick] = %queueCount; + %queueCount++; } + else if(%brickIsNew) + { + //If this brick already exists, we have to add the connection now + //(Start brick won't be processed again unlike the others) + $NS[%this, "C", %brickIndex, %conns] = %nId; + %conns++; - $NS[%this, "B", %queueCount] = %nextBrick; - $NS[%this, "I", %nextBrick] = %queueCount; - %queueCount++; + %ci = $NS[%this, "N", %nId]++; + $NS[%this, "C", %nId, %ci - 1] = %brickIndex; + + if(%ci > %this.maxConnections) + %this.maxConnections = %ci; + + %this.connectionCount++; + } } - else if(%brickIsNew) + + //Process all down bricks + %downCount = %brick.getNumDownBricks(); + + for(%i = 0; %i < %downCount; %i++) { - //If this brick already exists, we have to add the connection now - //(Start brick won't be processed again unlike the others) - $NS[%this, "C", %brickIndex, %conns] = %nId; - %conns++; + %nextBrick = %brick.getDownBrick(%i); - %ci = $NS[%this, "N", %nId]++; - $NS[%this, "C", %nId, %ci - 1] = %brickIndex; + //If the brick is not in the list yet, add it to the queue + %nId = $NS[%this, "I", %nextBrick]; - if(%ci > %this.maxConnections) - %this.maxConnections = %ci; + if(%nId $= "") + { + //Don't add down bricks if we're searching up + if(%direction == 1) + continue; - %this.connectionCount++; + if(%queueCount >= %brickLimit) + continue; + + //Check trust + if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + { + %trustFailCount++; + continue; + } + + $NS[%this, "B", %queueCount] = %nextBrick; + $NS[%this, "I", %nextBrick] = %queueCount; + %queueCount++; + } + else if(%brickIsNew) + { + //If this brick already exists, we have to add the connection now + //(Start brick won't be processed again unlike the others) + $NS[%this, "C", %brickIndex, %conns] = %nId; + %conns++; + + %ci = $NS[%this, "N", %nId]++; + $NS[%this, "C", %nId, %ci - 1] = %brickIndex; + + if(%ci > %this.maxConnections) + %this.maxConnections = %ci; + + %this.connectionCount++; + } } } @@ -455,7 +548,8 @@ function ND_Selection::tickStackSelection(%this, %direction, %limited, %heightLi if(!%brick) { - messageClient(%this.client, 'MsgError', "\c0Error: \c6Queued brick does not exist anymore. Do not modify the build during selection!"); + messageClient(%this.client, 'MsgError', ""); + ndmessageClient(%this.client, '', "\c0Error: \c6Queued brick does not exist anymore. Do not modify the build during selection!"); %this.cancelStackSelection(); %this.client.ndSetMode(NDM_StackSelect); @@ -464,102 +558,129 @@ function ND_Selection::tickStackSelection(%this, %direction, %limited, %heightLi ndHighlightBrick(%highlightGroup, %brick); - //Queue all up bricks - %upCount = %brick.getNumUpBricks(); - %conns = 0; + if(%direction==2) { + %conns = 0; + + while(%nextBrick = ndGetNextAdjacentBrick(%brick, %limited)) { + //If the brick is not in the list yet, add it to the queue + %nId = $NS[%this, "I", %nextBrick]; - for(%j = 0; %j < %upCount; %j++) - { - %nextBrick = %brick.getUpBrick(%j); - - //Skip bricks out of the limit - if(%limited && %direction == 0 && getWord(%nextBrick.getWorldBox(), 5) > %heightLimit) - continue; - - //If the brick is not in the selection yet, add it to the queue to get an id - %nId = $NS[%this, "I", %nextBrick]; - - if(%nId $= "") - { - if(%queueCount >= %brickLimit) - continue; - - //Check trust - if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + if(%nId $= "") { - %trustFailCount++; + + if(%queueCount >= %brickLimit) + continue; + + //Check trust + if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + { + %trustFailCount++; + continue; + } + + $NS[%this, "B", %queueCount] = %nextBrick; + $NS[%this, "I", %nextBrick] = %queueCount; + %queueCount++; + } + } + } else { + //Queue all up bricks + %upCount = %brick.getNumUpBricks(); + %conns = 0; + + for(%j = 0; %j < %upCount; %j++) + { + %nextBrick = %brick.getUpBrick(%j); + + //Skip bricks out of the limit + if(%limited && %direction == 0 && getWord(%nextBrick.getWorldBox(), 5) > %heightLimit) continue; + + //If the brick is not in the selection yet, add it to the queue to get an id + %nId = $NS[%this, "I", %nextBrick]; + + if(%nId $= "") + { + if(%queueCount >= %brickLimit) + continue; + + //Check trust + if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + { + %trustFailCount++; + continue; + } + + $NS[%this, "B", %queueCount] = %nextBrick; + $NS[%this, "I", %nextBrick] = %queueCount; + %nId = %queueCount; + %queueCount++; } - $NS[%this, "B", %queueCount] = %nextBrick; - $NS[%this, "I", %nextBrick] = %queueCount; - %nId = %queueCount; - %queueCount++; - } + $NS[%this, "C", %i, %conns] = %nId; + %conns++; - $NS[%this, "C", %i, %conns] = %nId; - %conns++; - - //If this brick is from a previous stack selection, - //we need to link the connection back as well - if(%nId < %selectionStart) - { - %ci = $NS[%this, "N", %nId]++; - $NS[%this, "C", %nId, %ci - 1] = %i; - - if(%ci > %this.maxConnections) - %this.maxConnections = %ci; - - %this.connectionCount++; - } - } - - //Queue all down bricks - %downCount = %brick.getNumDownBricks(); - - for(%j = 0; %j < %downCount; %j++) - { - %nextBrick = %brick.getDownBrick(%j); - - //Skip bricks out of the limit - if(%limited && %direction == 1 && getWord(%nextBrick.getWorldBox(), 2) < %heightLimit) - continue; - - //If the brick is not in the selection yet, add it to the queue to get an id - %nId = $NS[%this, "I", %nextBrick]; - - if(%nId $= "") - { - if(%queueCount >= %brickLimit) - continue; - - //Check trust - if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + //If this brick is from a previous stack selection, + //we need to link the connection back as well + if(%nId < %selectionStart) { - %trustFailCount++; + %ci = $NS[%this, "N", %nId]++; + $NS[%this, "C", %nId, %ci - 1] = %i; + + if(%ci > %this.maxConnections) + %this.maxConnections = %ci; + + %this.connectionCount++; + } + } + + //Queue all down bricks + %downCount = %brick.getNumDownBricks(); + + for(%j = 0; %j < %downCount; %j++) + { + %nextBrick = %brick.getDownBrick(%j); + + //Skip bricks out of the limit + if(%limited && %direction == 1 && getWord(%nextBrick.getWorldBox(), 2) < %heightLimit) continue; + + //If the brick is not in the selection yet, add it to the queue to get an id + %nId = $NS[%this, "I", %nextBrick]; + + if(%nId $= "") + { + if(%queueCount >= %brickLimit) + continue; + + //Check trust + if(!ndTrustCheckSelect(%nextBrick, %group, %bl_id, %admin)) + { + %trustFailCount++; + continue; + } + + $NS[%this, "B", %queueCount] = %nextBrick; + $NS[%this, "I", %nextBrick] = %queueCount; + %nId = %queueCount; + %queueCount++; } - $NS[%this, "B", %queueCount] = %nextBrick; - $NS[%this, "I", %nextBrick] = %queueCount; - %nId = %queueCount; - %queueCount++; - } + $NS[%this, "C", %i, %conns] = %nId; + %conns++; - $NS[%this, "C", %i, %conns] = %nId; - %conns++; + //If this brick is from a previous stack selection, + //we need to link the connection back as well + if(%nId < %selectionStart) + { + %ci = $NS[%this, "N", %nId]++; + $NS[%this, "C", %nId, %ci - 1] = %i; - //If this brick is from a previous stack selection, - //we need to link the connection back as well - if(%nId < %selectionStart) - { - %ci = $NS[%this, "N", %nId]++; - $NS[%this, "C", %nId, %ci - 1] = %i; + if(%ci > %this.maxConnections) + %this.maxConnections = %ci; - if(%ci > %this.maxConnections) - %this.maxConnections = %ci; - - %this.connectionCount++; + %this.connectionCount++; + } } } @@ -895,7 +1016,8 @@ function ND_Selection::tickBoxSelectionProcess(%this) if(!%brick) { - messageClient(%this.client, 'MsgError', "\c0Error: \c6Queued brick does not exist anymore. Do not modify the build during selection!"); + messageClient(%this.client, 'MsgError', ""); + ndmessageClient(%this.client, '', "\c0Error: \c6Queued brick does not exist anymore. Do not modify the build during selection!"); %this.cancelBoxSelection(); %this.client.ndSetMode(NDM_BoxSelect); @@ -1016,6 +1138,9 @@ function ND_Selection::recordBrickData(%this, %i) //Rotation $NS[%this, "R", %i] = %brick.angleID; + //Owner + $NS[%this, "O", %i] = %brick.getGroup().bl_id; + //Colors if($NDHN[%brick]) { @@ -1588,7 +1713,7 @@ function ND_Selection::finishSuperCut(%this) %this.client.fillBricksAfterSuperCut = false; if(%this.trustFailCount) - messageClient(%this.client, '', "\c6Cannot run fill bricks, you do not have enough trust bricks already in the area."); + ndmessageClient(%this.client, '', "\c6Cannot run fill bricks, you do not have enough trust bricks already in the area."); else %this.client.doFillBricks(%this.client.NDFillBrickSubset); } @@ -2070,9 +2195,10 @@ function ND_Selection::getGhostWorldBox(%this) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Start planting bricks! -function ND_Selection::startPlant(%this, %position, %angleID, %forcePlant) +function ND_Selection::startPlant(%this, %position, %angleID, %forcePlant, %ownership) { %this.forcePlant = %forcePlant; + %this.ownership = %ownership; %this.plantSearchIndex = 0; %this.plantQueueIndex = 0; @@ -2349,6 +2475,29 @@ function ND_Selection::tickPlantTree(%this, %remainingPlants, %position, %angleI %this.plantSchedule = %this.schedule(30, tickPlantTree, $Pref::Server::ND::ProcessPerTick, %position, %angleID); } +function ndBrickGroupFromBlid(%blid) { + %bg = "BrickGroup_" @ %blid; + if (isObject(%bg)) { + return %bg.getId(); + } else { + %bg = new SimGroup("BrickGroup_" @ %blid){}; + %bg.client = 0; + %bg.name = "\c2BL_ID: " @ %blid @ "\c2\c1"; + %bg.bl_id = %blid; + mainBrickGroup.add(%bg); + return %bg.getId(); + } +} + +function ndFindWord(%s, %w, %x, %a) { + if(%a $= "") %a = 1; + %c = getWordCount(%str); + for(%i = %x+0; %i<%c; %i+=%a) { + if(getWord(%s, %i) $= %w) return %i; + } + return -1; +} + //Attempt to plant brick with id %i //Returns brick if planted, 0 if floating, -1 if blocked, -2 if trust failure function ND_Selection::plantBrick(%this, %i, %position, %angleID, %brickGroup, %client, %bl_id) @@ -2549,7 +2698,12 @@ function ND_Selection::plantBrick(%this, %i, %position, %angleID, %brickGroup, % $LastLoadedBrick = %brick; //Add to brickgroup - %brickGroup.add(%brick); + //%brickGroup.add(%brick); + if(%this.ownership && $NS[%this, "O", %i] !$= "") { + ndBrickGroupFromBlid($NS[%this, "O", %i]).add(%brick); + } else { + %brickGroup.add(%brick); + } //Attempt plant %error = %brick.plant(); @@ -2728,8 +2882,9 @@ function ND_Selection::plantBrick(%this, %i, %position, %angleID, %brickGroup, % %param = ndRotateVector(%param, %angleID); case "list": - %value = getWord(%paramType, %param * 2 + 1); - + //%value = getWord(%paramType, %param * 2 + 1); + %value = getWord(%paramType, ndFindWord(%paramType, %param, 2, 2)-1); + switch$(%value) { case "Up": %dir = 0; @@ -2743,6 +2898,8 @@ function ND_Selection::plantBrick(%this, %i, %position, %angleID, %brickGroup, % if(%dir >= 0) { + %oldvalue = %value; + %oldparam = %param; switch(ndTransformDirection(%dir, %angleID, %mirrX, %mirrY, %mirrZ)) { case 0: %value = "Up"; @@ -2753,14 +2910,15 @@ function ND_Selection::plantBrick(%this, %i, %position, %angleID, %brickGroup, % case 5: %value = "West"; } - for(%l = 1; %l < getWordCount(%paramType); %l += 2) - { - if(getWord(%paramType, %l) $= %value) - { - %param = getWord(%paramType, %l + 1); - break; - } - } + //for(%l = 1; %l < getWordCount(%paramType); %l += 2) + //{ + // if(getWord(%paramType, %l) $= %value) + // { + // %param = getWord(%paramType, %l + 1); + // break; + // } + //} + %param = getWord(%paramType, ndFindWord(%paramType, %value, 1, 2)+1); } } } @@ -2814,7 +2972,7 @@ function ND_Selection::finishPlant(%this) { //Report mirror errors if($NS[%this.client, "MXC"] > 0 || $NS[%this.client, "MZC"] > 0) - messageClient(%this.client, '', "\c6Some bricks were probably mirrored incorrectly. Say \c3/mirErrors\c6 to find out more."); + ndMessageClient(%this.client, '', "\c6Some bricks were probably mirrored incorrectly. Say \c3/mirErrors\c6 to find out more."); %count = %this.brickCount; %planted = %this.plantSuccessCount; @@ -3572,6 +3730,11 @@ function ND_Selection::tickSaveBricks(%this) SPC !$NS[%this, "NC", %i] SPC !$NS[%this, "NR", %i] ); + + // Write ownership + if($NS[%this, "O", %i] !$= "") { + %file.writeLine("+-OWNER " @ $NS[%this, "O", %i]); + } //Write brick name if((%tmp = $NS[%this, "NT", %i]) !$= "") @@ -3849,7 +4012,8 @@ function ND_Selection::finishSaving(%this) %s1 = %this.brickCount == 1 ? "" : "s"; %s2 = %this.connectionCount == 1 ? "" : "s"; - messageClient(%this.client, 'MsgProcessComplete', "\c6Finished saving selection, wrote \c3" + messageClient(%this.client, 'MsgProcessComplete'); + ndmessageClient(%this.client, '', "\c6Finished saving selection, wrote \c3" @ %this.brickCount @ "\c6 Brick" @ %s1 @ " with \c3" @ %this.connectionCount @ "\c6 Connection" @ %s2 @ "!"); %this.client.ndLastSaveTime = $Sim::Time; @@ -4151,10 +4315,12 @@ function ND_Selection::tickLoadBricks(%this) warn("LOAD DUP: Got connection data before connection sizes"); - //Line is irrelevant + //Line is owner case "+-OWNER": - - %nothing = ""; + //%ownerBlid = trim(getSubStr(%line, 7, strLen(%line)-7)); + %ownerBlid = getWord(%line, 1); + %ownerBlid = mAbs(mFloor(%ownerBlid)); + $NS[%this, "O", %index] = %ownerBlid; //Line is brick default: @@ -4475,7 +4641,8 @@ function ND_Selection::finishLoading(%this) %s1 = %this.brickCount == 1 ? "" : "s"; %s2 = %this.connectionCount == 1 ? "" : "s"; - messageClient(%this.client, 'MsgProcessComplete', "\c6Finished loading selection, got \c3" + messageClient(%this.client, 'MsgProcessComplete', ""); + ndmessageClient(%this.client, '', "\c6Finished loading selection, got \c3" @ %this.brickCount @ "\c6 Brick" @ %s1 @ " with \c3" @ %this.connectionCount @ "\c6 Connection" @ %s2 @ "!"); %this.client.ndLastLoadTime = $Sim::Time; diff --git a/client.cs b/client.cs new file mode 100644 index 0000000..785018e --- /dev/null +++ b/client.cs @@ -0,0 +1,29 @@ +// Executes all required scripts and initializes the client side. +// ------------------------------------------------------------------- + +// Not updating because it's useless +$ND::Version = "1.6.3"; + +$ND::FilePath = filePath($Con::File) @ "/"; +$ND::ConfigPath = "config/NewDuplicator/"; + +$ND::ClassPath = $ND::FilePath @ "classes/"; +$ND::ScriptPath = $ND::FilePath @ "scripts/"; +$ND::ResourcePath = $ND::FilePath @ "resources/"; + +exec($ND::ScriptPath @ "client/guis/fillwrench.gui"); + +exec($ND::ScriptPath @ "client/controls.cs"); +exec($ND::ScriptPath @ "client/handshake.cs"); +exec($ND::ScriptPath @ "client/wrench.cs"); + +//if(!$Pref::ND::DisableUpdater +// && !$SupportUpdaterMigration +// && !isFile("Add-Ons/Support_Updater.zip")) +//{ +// exec($ND::ScriptPath @ "client/tcpclient.cs"); +// exec($ND::ScriptPath @ "client/updater.cs"); +//} + +activatePackage(NewDuplicator_Client); +ndRegisterKeybinds(); diff --git a/description.txt b/description.txt index 4babe57..cc42675 100644 --- a/description.txt +++ b/description.txt @@ -1,4 +1,4 @@ -Title: New Duplicator -Author: Zeblote (1163) +Title: New Duplicator (Redo Edit) +Author: Zeblote (1163), Redo (12878) New lag-free duplicator with intelligent selection modes -Redo's mod v1: better dupsave listing and search, fill and supercut logic wires, V20 support, possibly some other stuff I forgot about +See readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..166ff06 --- /dev/null +++ b/readme.md @@ -0,0 +1,29 @@ +# Redo's New Duplicator Edit +A fork of the original New Duplicator by Zeblote, presently maintained and with many improvements. + +## New Features +- Added the `/ownership` or `/o` command, which plants each brick in the current selection with its original ownership. Use in plant mode after copying/cutting. +`/savedup` now saves ownership, and `/ownership` can be used while holding a loaded duplication to load it. +(Loading ownership only works if the duplication was saved with this version, as the original newdup does not save ownership) +- Holding ctrl while making an initial stack selection selects all adjacent bricks of the same color, ignoring diagonals. +With limited mode off, all adjacent bricks will be selected regardless of color. +- The `/alldups` list is nicely formatted, sorted by date, and shows who saved each item. +- Support for Brick_LuaLogic +Supercut can be used on wire bricks. +`/FillBrick LogicWire` or `/fbw` can be used to fill with wire bricks. +Initial-multi-box-selecting a ROM sets the box to its data volume. +- Initial multi-box-selecting a brick with a zone sets the box to its zone. +Hitting plant with this box updates the first Event_SetZoneBox event if present. + +## Tweaks +- Made the "Create Sym Table on Start" pref default to true. +- Changed a lot of chat messages to be center-prints instead. +- Multi-selecting in box mode now only selects a single stud if ctrl was/is held for the first selection, otherwise it selects the entire brick. + +## Fixes +- Fixed "Nonexistent undo state" message when undoing a plant that has been supercut. +- Fixed preventing unequipping any tool for 1.5s after using `/duplicator` +- Removed useless files from the add-on root directory +- Removed the annoying messages about mismatched newdup versions when joining a server. +- Removed the worm known as Support_Updater. +- Probably some more stuff I forgot about. diff --git a/scripts/client/controls.cs b/scripts/client/controls.cs new file mode 100644 index 0000000..1cde87d --- /dev/null +++ b/scripts/client/controls.cs @@ -0,0 +1,116 @@ +// Registers hotkeys used to control the new duplicator. +// ------------------------------------------------------------------- + +//Register rebind-able controls +function ndRegisterKeybinds() +{ + if($ND::KeybindsRegistered) + return; + + $RemapDivision[$RemapCount] = "New Duplicator"; + $RemapName[$RemapCount] = "Copy Selection (Ctrl C)"; + $RemapCmd[$RemapCount] = "ndInputCopy"; + $RemapCount++; + + $RemapName[$RemapCount] = "Paste Selection (Ctrl V)"; + $RemapCmd[$RemapCount] = "ndInputPaste"; + $RemapCount++; + + $RemapName[$RemapCount] = "Cut Selection (Ctrl X)"; + $RemapCmd[$RemapCount] = "ndInputCut"; + $RemapCount++; + + $RemapName[$RemapCount] = "Multiselect (Ctrl, Hold to use)"; + $RemapCmd[$RemapCount] = "ndInputMultiSelect"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /NewDuplicator"; + $RemapCmd[$RemapCount] = "ndInputNewDuplicator"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /FillWrench"; + $RemapCmd[$RemapCount] = "ndInputFillWrench"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /ForcePlant"; + $RemapCmd[$RemapCount] = "ndInputForcePlant"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /ToggleForcePlant"; + $RemapCmd[$RemapCount] = "ndInputToggleForcePlant"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /MirrorX"; + $RemapCmd[$RemapCount] = "ndInputMirrorX"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /MirrorY"; + $RemapCmd[$RemapCount] = "ndInputMirrorY"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /MirrorZ"; + $RemapCmd[$RemapCount] = "ndInputMirrorZ"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /SuperCut (Shift-Ctrl X)"; + $RemapCmd[$RemapCount] = "ndInputSuperCut"; + $RemapCount++; + + $RemapName[$RemapCount] = "Send /FillBricks (Shift-Ctrl V)"; + $RemapCmd[$RemapCount] = "ndInputFillBricks"; + $RemapCount++; + + $ND::KeybindsRegistered = true; +} + +//Enable the copy, paste, cut keybinds +function clientCmdNdEnableKeybinds(%bool) +{ + if(%bool && !$ND::KeybindsEnabled) + { + %map = new ActionMap(ND_KeyMap); + + if(MoveMap.getBinding("ndInputCopy") $= "") + %map.bind("keyboard", isWindows() ? "ctrl c" : "cmd c", "ndInputCopy"); + + if(MoveMap.getBinding("ndInputPaste") $= "") + %map.bind("keyboard", isWindows() ? "ctrl v" : "cmd v", "ndInputPaste"); + + if(MoveMap.getBinding("ndInputCut") $= "") + %map.bind("keyboard", isWindows() ? "ctrl x" : "cmd x", "ndInputCut"); + + if(MoveMap.getBinding("ndInputMultiSelect") $= "") + %map.bind("keyboard", isWindows() ? "lcontrol" : "cmd", "ndInputMultiSelect"); + + if(MoveMap.getBinding("ndInputSuperCut") $= "") + %map.bind("keyboard", isWindows() ? "shift-ctrl x" : "shift-cmd x", "ndInputSuperCut"); + + if(MoveMap.getBinding("ndInputFillBricks") $= "") + %map.bind("keyboard", isWindows() ? "shift-ctrl v" : "shift-cmd v", "ndInputFillBricks"); + + %map.push(); + $ND::KeybindsEnabled = true; + } + else if(!%bool && $ND::KeybindsEnabled) + { + ND_KeyMap.pop(); + ND_KeyMap.delete(); + $ND::KeybindsEnabled = false; + } +} + +//Input handlers +function ndInputNewDuplicator (%bool) {if(!%bool)return; commandToServer('newDuplicator' );} +function ndInputCopy (%bool) {if(!%bool)return; commandToServer('ndCopy' );} +function ndInputPaste (%bool) {if(!%bool)return; commandToServer('ndPaste' );} +function ndInputCut (%bool) {if(!%bool)return; commandToServer('ndCut' );} +function ndInputFillWrench (%bool) {if(!%bool)return; commandToServer('fillWrench' );} +function ndInputForcePlant (%bool) {if(!%bool)return; commandToServer('forcePlant' );} +function ndInputToggleForcePlant(%bool) {if(!%bool)return; commandToServer('toggleForcePlant');} +function ndInputMirrorX (%bool) {if(!%bool)return; commandToServer('mirrorX' );} +function ndInputMirrorY (%bool) {if(!%bool)return; commandToServer('mirrorY' );} +function ndInputMirrorZ (%bool) {if(!%bool)return; commandToServer('mirrorZ' );} +function ndInputSuperCut (%bool) {if(!%bool)return; commandToServer('superCut' );} +function ndInputFillBricks (%bool) {if(!%bool)return; commandToServer('fillBricks' );} + +function ndInputMultiSelect(%bool) {commandToServer('ndMultiSelect', %bool);} diff --git a/scripts/client/guis/fillwrench.gui b/scripts/client/guis/fillwrench.gui new file mode 100644 index 0000000..090db91 --- /dev/null +++ b/scripts/client/guis/fillwrench.gui @@ -0,0 +1,507 @@ +// Modified wrench dialog window with toggle-able settings. +// ------------------------------------------------------------------- + +new GuiControl(ND_WrenchDlg) +{ + profile = "GuiDefaultProfile"; + position = "0 0"; + extent = "1024 768"; + + new GuiWindowCtrl(ND_Wrench_Window) + { + profile = "BlockWindowProfile"; + horizSizing = "center"; + vertSizing = "center"; + position = "363 197"; + extent = "297 373"; + text = "New Duplicator | Fill Wrench"; + resizeWidth = "0"; + resizeHeight = "0"; + canMove = "1"; + canClose = "1"; + canMinimize = "0"; + canMaximize = "0"; + minSize = "50 50"; + closeCommand = "canvas.popDialog(ND_WrenchDlg);"; + + new GuiTextCtrl() + { + profile = "GuiTextProfile"; + position = "13 33"; + extent = "57 18"; + text = "Brick Name:"; + }; + new GuiTextEditCtrl(ND_Wrench_Name) + { + profile = "GuiTextEditProfile"; + position = "76 33"; + extent = "162 18"; + maxLength = "32"; + }; + + + new GuiTextCtrl() + { + profile = "GuiTextProfile"; + position = "13 63"; + extent = "26 18"; + text = "Light:"; + }; + new GuiPopUpMenuCtrl(ND_Wrench_Lights) + { + profile = "BlockButtonProfile"; + position = "76 60"; + extent = "162 22"; + maxPopupHeight = "200"; + }; + + + new GuiTextCtrl() + { + profile = "GuiTextProfile"; + position = "13 93"; + extent = "35 18"; + text = "Emitter:"; + }; + new GuiPopUpMenuCtrl(ND_Wrench_Emitters) + { + profile = "BlockButtonProfile"; + position = "76 90"; + extent = "162 22"; + maxPopupHeight = "200"; + }; + + + new GuiTextCtrl() + { + profile = "GuiTextProfile"; + position = "13 113"; + extent = "51 18"; + text = "Emitter Dir:"; + }; + new GuiRadioCtrl(ND_Wrench_EmitterDir0) + { + profile = "GuiRadioProfile"; + position = "78 110"; + extent = "27 22"; + text = "U"; + groupNum = "1"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_EmitterDir1) + { + profile = "GuiRadioProfile"; + position = "104 110"; + extent = "27 22"; + text = "D"; + groupNum = "1"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_EmitterDir2) + { + profile = "GuiRadioProfile"; + position = "130 110"; + extent = "27 22"; + text = "N"; + groupNum = "1"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_EmitterDir3) + { + profile = "GuiRadioProfile"; + position = "156 110"; + extent = "27 22"; + text = "E"; + groupNum = "1"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_EmitterDir4) + { + profile = "GuiRadioProfile"; + position = "182 110"; + extent = "27 22"; + text = "S"; + groupNum = "1"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_EmitterDir5) + { + profile = "GuiRadioProfile"; + position = "208 110"; + extent = "27 22"; + text = "W"; + groupNum = "1"; + buttonType = "RadioButton"; + }; + + + new GuiTextCtrl() + { + profile = "GuiTextProfile"; + position = "13 153"; + extent = "22 18"; + text = "Item:"; + }; + new GuiPopUpMenuCtrl(ND_Wrench_Items) + { + profile = "BlockButtonProfile"; + position = "76 150"; + extent = "162 22"; + maxPopupHeight = "200"; + }; + + + new GuiTextCtrl() + { + profile = "GuiTextProfile"; + position = "13 173"; + extent = "43 18"; + text = "Item Pos:"; + }; + new GuiRadioCtrl(ND_Wrench_ItemPos1) + { + profile = "GuiRadioProfile"; + position = "104 170"; + extent = "27 22"; + text = "D"; + groupNum = "2"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_ItemPos0) + { + profile = "GuiRadioProfile"; + position = "78 170"; + extent = "27 22"; + text = "U"; + groupNum = "2"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_ItemPos2) + { + profile = "GuiRadioProfile"; + position = "130 170"; + extent = "27 22"; + text = "N"; + groupNum = "2"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_ItemPos3) + { + profile = "GuiRadioProfile"; + position = "156 170"; + extent = "27 22"; + text = "E"; + groupNum = "2"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_ItemPos4) + { + profile = "GuiRadioProfile"; + position = "182 170"; + extent = "27 22"; + text = "S"; + groupNum = "2"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_ItemPos5) + { + profile = "GuiRadioProfile"; + position = "208 170"; + extent = "27 22"; + text = "W"; + groupNum = "2"; + buttonType = "RadioButton"; + }; + + + new GuiTextCtrl() + { + profile = "GuiTextProfile"; + position = "13 193"; + extent = "38 18"; + text = "Item Dir:"; + }; + new GuiRadioCtrl(ND_Wrench_ItemDir5) + { + profile = "GuiRadioProfile"; + position = "208 190"; + extent = "27 22"; + text = "W"; + groupNum = "3"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_ItemDir2) + { + profile = "GuiRadioProfile"; + position = "130 190"; + extent = "27 22"; + text = "N"; + groupNum = "3"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_ItemDir3) + { + profile = "GuiRadioProfile"; + position = "156 190"; + extent = "27 22"; + text = "E"; + groupNum = "3"; + buttonType = "RadioButton"; + }; + new GuiRadioCtrl(ND_Wrench_ItemDir4) + { + profile = "GuiRadioProfile"; + position = "182 190"; + extent = "27 22"; + text = "S"; + groupNum = "3"; + buttonType = "RadioButton"; + }; + + + new GuiTextCtrl() + { + profile = "GuiTextProfile"; + position = "13 213"; + extent = "97 18"; + text = "Item Respawn Time:"; + }; + new GuiTextEditCtrl(ND_Wrench_ItemTime) + { + profile = "GuiTextEditProfile"; + position = "117 213"; + extent = "121 18"; + }; + + + new GuiCheckBoxCtrl(ND_Wrench_RayCasting) + { + profile = "GuiCheckBoxProfile"; + position = "14 240"; + extent = "78 22"; + text = "Ray Casting"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_Collision) + { + profile = "GuiCheckBoxProfile"; + position = "14 260"; + extent = "74 22"; + text = "Collision"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_Rendering) + { + profile = "GuiCheckBoxProfile"; + position = "14 280"; + extent = "74 22"; + text = "Rendering"; + buttonType = "ToggleButton"; + }; + + + new GuiCheckBoxCtrl(ND_Wrench_ToggleName) + { + profile = "GuiCheckBoxProfile"; + position = "244 32"; + extent = "42 22"; + command = "ND_Wrench_BlockName.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleLights) + { + profile = "GuiCheckBoxProfile"; + position = "244 60"; + extent = "42 22"; + command = "ND_Wrench_BlockLights.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleEmitters) + { + profile = "GuiCheckBoxProfile"; + position = "244 90"; + extent = "42 22"; + command = "ND_Wrench_BlockEmitters.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleEmitterDir) + { + profile = "GuiCheckBoxProfile"; + position = "244 110"; + extent = "42 22"; + command = "ND_Wrench_BlockEmitterDir.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleItems) + { + profile = "GuiCheckBoxProfile"; + position = "244 150"; + extent = "42 22"; + command = "ND_Wrench_BlockItems.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleItemPos) + { + profile = "GuiCheckBoxProfile"; + position = "244 170"; + extent = "42 22"; + command = "ND_Wrench_BlockItemPos.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleItemDir) + { + profile = "GuiCheckBoxProfile"; + position = "244 190"; + extent = "42 22"; + command = "ND_Wrench_BlockItemDir.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleItemTime) + { + profile = "GuiCheckBoxProfile"; + position = "244 210"; + extent = "42 22"; + command = "ND_Wrench_BlockItemTime.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleRayCasting) + { + profile = "GuiCheckBoxProfile"; + position = "244 240"; + extent = "42 22"; + command = "ND_Wrench_BlockRaycasting.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleCollision) + { + profile = "GuiCheckBoxProfile"; + position = "244 260"; + extent = "42 22"; + command = "ND_Wrench_BlockCollision.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + new GuiCheckBoxCtrl(ND_Wrench_ToggleRendering) + { + profile = "GuiCheckBoxProfile"; + position = "244 280"; + extent = "42 22"; + command = "ND_Wrench_BlockRendering.setVisible(!$ThisControl.getValue());"; + text = "Apply"; + buttonType = "ToggleButton"; + }; + + + new GuiSwatchCtrl(ND_Wrench_BlockName) + { + profile = "GuiDefaultProfile"; + position = "11 32"; + extent = "233 24"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockLights) + { + profile = "GuiDefaultProfile"; + position = "11 60"; + extent = "233 24"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockEmitters) + { + profile = "GuiDefaultProfile"; + position = "11 89"; + extent = "233 24"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockEmitterDir) + { + profile = "GuiDefaultProfile"; + position = "11 114"; + extent = "233 24"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockItems) + { + profile = "GuiDefaultProfile"; + position = "11 149"; + extent = "233 24"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockItemPos) + { + profile = "GuiDefaultProfile"; + position = "11 173"; + extent = "233 20"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockItemDir) + { + profile = "GuiDefaultProfile"; + position = "11 191"; + extent = "233 20"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockItemTime) + { + profile = "GuiDefaultProfile"; + position = "11 212"; + extent = "233 20"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockRaycasting) + { + profile = "GuiDefaultProfile"; + position = "11 242"; + extent = "233 20"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockCollision) + { + profile = "GuiDefaultProfile"; + position = "11 262"; + extent = "233 20"; + color = "200 200 200 200"; + }; + new GuiSwatchCtrl(ND_Wrench_BlockRendering) + { + profile = "GuiDefaultProfile"; + position = "11 282"; + extent = "233 20"; + color = "200 200 200 200"; + }; + + + new GuiBitmapButtonCtrl(ND_Wrench_Cancel) + { + profile = "BlockButtonProfile"; + position = "16 317"; + extent = "91 38"; + command = "canvas.popDialog(ND_WrenchDlg);"; + accelerator = "escape"; + text = "<< Cancel"; + buttonType = "PushButton"; + bitmap = "base/client/ui/button2"; + mColor = "255 255 255 255"; + }; + new GuiBitmapButtonCtrl(ND_Wrench_Send) + { + profile = "BlockButtonProfile"; + position = "119 317"; + extent = "160 38"; + command = "ndSendFillWrenchData();"; + text = "Apply Selected to All >>"; + buttonType = "PushButton"; + bitmap = "base/client/ui/button1"; + mColor = "255 255 255 255"; + }; + }; +}; diff --git a/scripts/client/handshake.cs b/scripts/client/handshake.cs new file mode 100644 index 0000000..93149e8 --- /dev/null +++ b/scripts/client/handshake.cs @@ -0,0 +1,33 @@ +// Responds to the handshake request sent by the server. +// ------------------------------------------------------------------- + +//Assume server doesn't have the new duplicator +$ND::ServerVersion = "0.0.0"; +$ND::ServerHasND = false; + +//Receive handshake from server +function clientCmdNdHandshake(%serverVersion) +{ + $ND::ServerVersion = %serverVersion; + $ND::ServerHasND = true; + + // Prevent servers from pestering us about version mismatches by pretending to have the same version as them. + // The version is basically not used for anything else, so need to send our actual version. + //commandToServer('ndHandshake', $ND::Version); + commandToServer('ndHandshake', %serverVersion); +} + +package NewDuplicator_Client +{ + //Reset server version on leaving server + function disconnectedCleanup(%bool) + { + $ND::ServerVersion = "0.0.0"; + $ND::ServerHasND = false; + + //Disable the keybinds + clientCmdNdEnableKeybinds(false); + + parent::disconnectedCleanup(%bool); + } +}; diff --git a/scripts/client/wrench.cs b/scripts/client/wrench.cs new file mode 100644 index 0000000..a92e6ee --- /dev/null +++ b/scripts/client/wrench.cs @@ -0,0 +1,164 @@ +// Prepares the fillWrench gui and handles submitting the settings. +// ------------------------------------------------------------------- + +package NewDuplicator_Client +{ + function clientCmdWrench_LoadMenus() + { + parent::clientCmdWrench_LoadMenus(); + + $ND::WrenchReloadRequired = true; + } +}; + +//Open the wrench gui for fill wrench mode +function clientCmdNdOpenWrenchGui() +{ + if($ND::WrenchReloadRequired) + { + //Reload the drop down lists + ND_Wrench_Lights.clear(); + ND_Wrench_Emitters.clear(); + ND_Wrench_Items.clear(); + + ND_Wrench_Lights.add(" NONE", 0); + ND_Wrench_Emitters.add(" NONE", 0); + ND_Wrench_Items.add(" NONE", 0); + + //Add all datablocks to list + %cnt = getDatablockGroupSize(); + + for(%i = 0; %i < %cnt; %i++) + { + %data = getDatablock(%i); + %uiName = %data.uiName; + + //Skip non-selectable datablocks + if(%uiName $= "") + continue; + + //Put datablock in correct list + switch$(%data.getClassName()) + { + case "FxLightData": + ND_Wrench_Lights.add(%uiName, %data); + + case "ParticleEmitterData": + ND_Wrench_Emitters.add(%uiName, %data); + + case "ItemData": + ND_Wrench_Items.add(%uiName, %data); + } + } + + //Sort lists + ND_Wrench_Lights.sort(); + ND_Wrench_Emitters.sort(); + ND_Wrench_Items.sort(); + + //Select NONE + ND_Wrench_Lights.setSelected(0); + ND_Wrench_Emitters.setSelected(0); + ND_Wrench_Items.setSelected(0); + + $ND::WrenchReloadRequired = false; + } + + //Open gui + Canvas.pushDialog(ND_WrenchDlg); +} + +//Send the settings to the server +function ndSendFillWrenchData() +{ + //Close gui + Canvas.popDialog(ND_WrenchDlg); + + //Pack all enabled settings in string + %str = ""; + + if(ND_Wrench_ToggleName.getValue()) + %str = %str TAB "N" SPC trim(ND_Wrench_Name.getValue()); + + if(ND_Wrench_ToggleLights.getValue()) + %str = %str TAB "LDB" SPC ND_Wrench_Lights.getSelected(); + + if(ND_Wrench_ToggleEmitters.getValue()) + %str = %str TAB "EDB" SPC ND_Wrench_Emitters.getSelected(); + + if(ND_Wrench_ToggleEmitterDir.getValue()) + { + %dir = -1; + + for(%i = 0; %i < 6; %i++) + { + %obj = "ND_Wrench_EmitterDir" @ %i; + + if(%obj.getValue()) + { + %dir = %i; + break; + } + } + + if(%dir >= 0) + %str = %str TAB "EDIR" SPC %dir; + } + + if(ND_Wrench_ToggleItems.getValue()) + %str = %str TAB "IDB" SPC ND_Wrench_Items.getSelected(); + + if(ND_Wrench_ToggleItemPos.getValue()) + { + %pos = -1; + + for(%i = 0; %i < 6; %i++) + { + %obj = "ND_Wrench_ItemPos" @ %i; + + if(%obj.getValue()) + { + %pos = %i; + break; + } + } + + if(%pos >= 0) + %str = %str TAB "IPOS" SPC %pos; + } + + if(ND_Wrench_ToggleItemDir.getValue()) + { + %dir = -1; + + for(%i = 2; %i < 6; %i++) + { + %obj = "ND_Wrench_ItemDir" @ %i; + + if(%obj.getValue()) + { + %dir = %i; + break; + } + } + + if(%dir >= 2) + %str = %str TAB "IDIR" SPC %dir; + } + + if(ND_Wrench_ToggleItemTime.getValue()) + %str = %str TAB "IRT" SPC trim(ND_Wrench_ItemTime.getValue()) * 1; + + if(ND_Wrench_ToggleRayCasting.getValue()) + %str = %str TAB "RC" SPC ND_Wrench_RayCasting.getValue(); + + if(ND_Wrench_ToggleCollision.getValue()) + %str = %str TAB "C" SPC ND_Wrench_Collision.getValue(); + + if(ND_Wrench_ToggleRendering.getValue()) + %str = %str TAB "R" SPC ND_Wrench_Rendering.getValue(); + + //Send string + if(strLen(%str)) + commandToServer('ndStartFillWrench', trim(%str)); +} diff --git a/scripts/server/commands.cs b/scripts/server/commands.cs index 0bd5402..c1d4d70 100644 --- a/scripts/server/commands.cs +++ b/scripts/server/commands.cs @@ -1,3 +1,5 @@ +//bls 3 + // General server commands used to control the new duplicator. // ------------------------------------------------------------------- @@ -7,7 +9,7 @@ //Shows version of blockland and the new duplicator function serverCmdDupVersion(%client) { - messageClient(%client, '', "\c6Blockland version: \c3r" @ getBuildNumber()); + //messageClient(%client, '', "\c6Blockland version: \c3r" @ getBuildNumber()); messageClient(%client, '', "\c6New duplicator version: \c3" @ $ND::Version); if(%client.ndClient) @@ -17,19 +19,19 @@ function serverCmdDupVersion(%client) } //Shows versions of other clients -function serverCmdDupClients(%client) -{ - messageClient(%client, '', "\c6New duplicator versions:"); - - %cnt = ClientGroup.getCount(); - for(%i = 0; %i < %cnt; %i++) - { - %cl = ClientGroup.getObject(%i); - - if(%cl.ndClient) - messageClient(%client, '', "\c3" @ %cl.name @ "\c6 has \c3" @ %cl.ndVersion); - } -} +//function serverCmdDupClients(%client) +//{ +// messageClient(%client, '', "\c6New duplicator versions:"); +// +// %cnt = ClientGroup.getCount(); +// for(%i = 0; %i < %cnt; %i++) +// { +// %cl = ClientGroup.getObject(%i); +// +// if(%cl.ndClient) +// messageClient(%client, '', "\c3" @ %cl.name @ "\c6 has \c3" @ %cl.ndVersion); +// } +//} //Shows list of commands function serverCmdDupHelp(%client) @@ -74,8 +76,8 @@ function serverCmdDupHelp(%client) } //Alternative short commands -function serverCmdDV(%client){serverCmdDupVersion(%client);} -function serverCmdDC(%client){serverCmdDupClients(%client);} +//function serverCmdDV(%client){serverCmdDupVersion(%client);} +//function serverCmdDC(%client){serverCmdDupClients(%client);} function serverCmdDH(%client){serverCmdDupHelp(%client);} @@ -89,27 +91,33 @@ function serverCmdNewDuplicator(%client) //Check admin if($Pref::Server::ND::AdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6The new duplicator is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6The new duplicator is admin only. Ask an admin for help."); return; } //Check minigame if(isObject(%client.minigame) && !%client.minigame.enablebuilding) { - messageClient(%client, '', "\c6You cannot use the new duplicator while building is disabled in your minigame."); + ndmessageClient(%client, '', "\c6You cannot use the new duplicator while building is disabled in your minigame."); return; } //Check player if(!isObject(%player = %client.player)) { - messageClient(%client, '', "\c6You must be spawned to equip the new duplicator."); + ndmessageClient(%client, '', "\c6You must be spawned to equip the new duplicator."); return; } + + // Abort if already holding the dup + if(isObject(%player.getMountedImage(0)) && getSubStr(%player.getMountedImage(0).getName(), 0, 8) $= "ND_Image") + return; - //Hide brick selector and tool gui - %client.ndLastEquipTime = $Sim::Time; - commandToClient(%client, 'setScrollMode', 3); + // If a tool is equipped, hide brick selector and tool gui + if(isObject(%player.getMountedImage(0))) { + %client.ndLastEquipTime = $Sim::Time; + commandToClient(%client, 'setScrollMode', 3); + } //Give player a duplicator %image = %client.ndImage; @@ -224,7 +232,8 @@ package NewDuplicator_Server if(%obj.brickCount > 10 && %client.ndUndoConfirm != %obj) { - messageClient(%client, '', "\c6Next undo will affect \c3" @ %obj.brickCount @ "\c6 bricks. Press undo again to continue."); + //messageClient(%client, '', "\c6Next undo will affect \c3" @ %obj.brickCount @ "\c6 bricks. Press undo again to continue."); + commandToClient(%client, 'centerPrint', "\c6Next undo will affect \c3" @ %obj.brickCount @ "\c6 bricks. Press undo again to continue.", 4); %client.undoStack.push(%state); %client.ndUndoConfirm = %obj; return; @@ -237,7 +246,8 @@ package NewDuplicator_Server %client.ndUndoConfirm = 0; }else{ - talk("serverCmdUndoBrick(" @ %client.name @ ") - Nonexistent undo state " @ %state); + // seems to happen when you SC a plant and then undo it + //talk("serverCmdUndoBrick(" @ %client.name @ ") - Nonexistent undo state " @ %state); } return; } @@ -306,19 +316,19 @@ function serverCmdSuperCut(%client) { if(%client.ndModeIndex != $NDM::BoxSelect) { - messageClient(%client, '', "\c6Supercut can only be used on box selection mode."); + ndmessageClient(%client, '', "\c6Supercut can only be used on box selection mode."); return; } if(!isObject(%client.ndSelectionBox)) { - messageClient(%client, '', "\c6Supercut can only be used with a selection box."); + ndmessageClient(%client, '', "\c6Supercut can only be used with a selection box."); return; } if(%client.ndSelectionAvailable) { - messageClient(%client, '', "\c6Supercut can not be used with any bricks selected."); + ndmessageClient(%client, '', "\c6Supercut can not be used with any bricks selected."); return; } @@ -333,19 +343,19 @@ function serverCmdNdConfirmSuperCut(%client) { if(%client.ndModeIndex != $NDM::BoxSelect) { - messageClient(%client, '', "\c6Supercut can only be used on box selection mode."); + ndmessageClient(%client, '', "\c6Supercut can only be used on box selection mode."); return; } if(!isObject(%client.ndSelectionBox)) { - messageClient(%client, '', "\c6Supercut can only be used with a selection box."); + ndmessageClient(%client, '', "\c6Supercut can only be used with a selection box."); return; } if(%client.ndSelectionAvailable) { - messageClient(%client, '', "\c6Supercut can not be used with any bricks selected."); + ndmessageClient(%client, '', "\c6Supercut can not be used with any bricks selected."); return; } @@ -363,25 +373,25 @@ function serverCmdFillBricks(%client, %conf, %subsetname) { if($Pref::Server::ND::FillBricksAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Fill Bricks is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Fill Bricks is admin only. Ask an admin for help."); return; } if(!isObject(%client.ndSelectionBox)) { - messageClient(%client, '', "\c6The fillBricks command can only be used with a selection box."); + ndmessageClient(%client, '', "\c6The fillBricks command can only be used with a selection box."); return; } if(%client.ndSelectionAvailable) { - messageClient(%client, '', "\c6The fillBricks command can not be used with any bricks selected."); + ndmessageClient(%client, '', "\c6The fillBricks command can not be used with any bricks selected."); return; } if(!%client.ndSelectionBox.hasVolume()) { - messageClient(%client, '', "\c6The fillBricks command can only be used with a selection box that has a volume."); + ndmessageClient(%client, '', "\c6The fillBricks command can only be used with a selection box that has a volume."); return; } @@ -403,25 +413,25 @@ function serverCmdNdConfirmFillBricks(%client, %subsetname) { if($Pref::Server::ND::FillBricksAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Fill Bricks is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Fill Bricks is admin only. Ask an admin for help."); return; } if(!isObject(%client.ndSelectionBox)) { - messageClient(%client, '', "\c6The fillBricks command can only be used with a selection box."); + ndmessageClient(%client, '', "\c6The fillBricks command can only be used with a selection box."); return; } if(%client.ndSelectionAvailable) { - messageClient(%client, '', "\c6The fillBricks command can not be used with any bricks selected."); + ndmessageClient(%client, '', "\c6The fillBricks command can not be used with any bricks selected."); return; } if(!%client.ndSelectionBox.hasVolume()) { - messageClient(%client, '', "\c6The fillBricks command can only be used with a selection box that has a volume."); + ndmessageClient(%client, '', "\c6The fillBricks command can only be used with a selection box that has a volume."); return; } @@ -494,7 +504,7 @@ function GameConnection::ndMirror(%client, %axis) if(!$ND::SymmetryTableCreating) ndCreateSymmetryTable(); - messageClient(%client, '', "\c6Please wait for the symmetry table to finish, then mirror again."); + ndmessageClient(%client, '', "\c6Please wait for the symmetry table to finish, then mirror again."); return; } @@ -513,7 +523,7 @@ function GameConnection::ndMirror(%client, %axis) } //We didn't mirror anything - messageClient(%client, '', "\c6The mirror command can only be used in plant mode or with a ghost brick."); + ndmessageClient(%client, '', "\c6The mirror command can only be used in plant mode or with a ghost brick."); } //List potential mirror errors in last plant @@ -555,6 +565,29 @@ function serverCmdME(%client){serverCmdMirErrors(%client);} +/////////////////////////////////////////////////////////////////////////// +// Ownership +function serverCmdOwnership(%client) { + if(%client.ndModeIndex != $NDM::PlantCopy) { + ndmessageClient(%client, '', "\c6Ownership plant can only be used in Plant Mode."); + return; + } + if(!%client.isAdmin) { + ndmessageClient(%client, '', "\c6Ownership plant is admin only."); + return; + } + %client.ndOwnership = !%client.ndOwnership; + if(%client.ndOwnership) { + ndmessageClient(%client, '', "\c6Bricks will now be planted in the group of the original owner."); + } else { + ndmessageClient(%client, '', "\c6Bricks will now be planted in your own group."); + } + %client.ndUpdateBottomPrint(); +} +function serverCmdOwn(%client) { serverCmdOwnership(%client); } +function serverCmdO(%client) { serverCmdOwnership(%client); } + + //Force plant /////////////////////////////////////////////////////////////////////////// @@ -564,18 +597,18 @@ function serverCmdForcePlant(%client) //Check mode if(%client.ndModeIndex != $NDM::PlantCopy) { - messageClient(%client, '', "\c6Force Plant can only be used in Plant Mode."); + ndmessageClient(%client, '', "\c6Force Plant can only be used in Plant Mode."); return; } //Check admin if($Pref::Server::ND::FloatAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Force Plant is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Force Plant is admin only. Ask an admin for help."); return; } - NDM_PlantCopy.conditionalPlant(%client, true); + NDM_PlantCopy.conditionalPlant(%client, true, false); } //Alternative short command @@ -587,16 +620,16 @@ function serverCmdToggleForcePlant(%client) //Check admin if($Pref::Server::ND::FloatAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Force Plant is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Force Plant is admin only. Ask an admin for help."); return; } %client.ndForcePlant = !%client.ndForcePlant; if(%client.ndForcePlant) - messageClient(%client, '', "\c6Force Plant has been enabled. Use \c3/toggleForcePlant\c6 to disable it."); + ndmessageClient(%client, '', "\c6Force Plant has been enabled. Use \c3/toggleForcePlant\c6 to disable it."); else - messageClient(%client, '', "\c6Force Plant has been disabled. Use \c3/toggleForcePlant\c6 to enable it again."); + ndmessageClient(%client, '', "\c6Force Plant has been disabled. Use \c3/toggleForcePlant\c6 to enable it again."); } //Alternative short command @@ -672,34 +705,34 @@ function serverCmdFillWrench(%client) //Check version if(!%client.ndClient) { - messageClient(%client, '', "\c6You need to have the new duplicator installed to use Fill Wrench."); + ndmessageClient(%client, '', "\c6You need to have the new duplicator installed to use Fill Wrench."); return; } if(ndCompareVersion("1.2.0", %client.ndVersion) == 1) { - messageClient(%client, '', "\c6Your version of the new duplicator is too old to use Fill Wrench."); + ndmessageClient(%client, '', "\c6Your version of the new duplicator is too old to use Fill Wrench."); return; } //Check admin if($Pref::Server::ND::WrenchAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Fill Wrench is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Fill Wrench is admin only. Ask an admin for help."); return; } //Check mode if(%client.ndModeIndex != $NDM::StackSelect && %client.ndModeIndex != $NDM::BoxSelect) { - messageClient(%client, '', "\c6Fill Wrench can only be used in Selection Mode."); + ndmessageClient(%client, '', "\c6Fill Wrench can only be used in Selection Mode."); return; } //Check selection if(!isObject(%client.ndSelection) || !%client.ndSelection.brickCount) { - messageClient(%client, '', "\c6Fill Wrench can only be used with a selection."); + ndmessageClient(%client, '', "\c6Fill Wrench can only be used with a selection."); return; } @@ -716,21 +749,21 @@ function serverCmdNdStartFillWrench(%client, %data) //Check admin if($Pref::Server::ND::WrenchAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Fill Wrench is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Fill Wrench is admin only. Ask an admin for help."); return; } //Check mode if(%client.ndModeIndex != $NDM::StackSelect && %client.ndModeIndex != $NDM::BoxSelect) { - messageClient(%client, '', "\c6Fill Wrench can only be used in Selection Mode."); + ndmessageClient(%client, '', "\c6Fill Wrench can only be used in Selection Mode."); return; } //Check selection if(!isObject(%client.ndSelection) || !%client.ndSelection.brickCount) { - messageClient(%client, '', "\c6Fill Wrench can only be used with a selection."); + ndmessageClient(%client, '', "\c6Fill Wrench can only be used with a selection."); return; } @@ -757,21 +790,21 @@ package NewDuplicator_Server_Final if(%remain != 1) %s = "s"; - messageClient(%client, '', "\c6Please wait\c3 " @ %remain @ "\c6 second" @ %s @ " before saving again!"); + ndmessageClient(%client, '', "\c6Please wait\c3 " @ %remain @ "\c6 second" @ %s @ " before saving again!"); return; } //Check admin if($Pref::Server::ND::SaveAdminOnly && !%client.isAdmin) { - messageClient(%client, '', "\c6Saving duplications is admin only. Ask an admin for help."); + ndmessageClient(%client, '', "\c6Saving duplications is admin only. Ask an admin for help."); return; } //Check mode if(%client.ndModeIndex != $NDM::PlantCopy) { - messageClient(%client, '', "\c6Saving duplications can only be used in Plant Mode."); + ndmessageClient(%client, '', "\c6Saving duplications can only be used in Plant Mode."); return; } @@ -958,7 +991,7 @@ function ND_SaveFileInfo(%filename) { %info = $ND::FileDate[%filename]; %info_aftername = getSubStr(%info, strStr(%info, " (")+2, strLen(%info)); %date = getSubStr(%info_aftername, strLen(%info_aftername)-17, 17); - %blid = getSubStr(%info_aftername, 0, strStr(%info_aftername, ")")); + //%blid = getSubStr(%info_aftername, 0, strStr(%info_aftername, ")")); %name = getSubStr(%info, 9, strStr(%info, " (") - 9); // Fix date format for sorting @@ -970,7 +1003,7 @@ function ND_SaveFileInfo(%filename) { %filetext = %sort @ "\c3" @ %namepart TAB "\c3" @ %name TAB - "\c6" @ %blid TAB + //"\c6" @ %blid TAB "\c6" @ %date ; @@ -1031,7 +1064,7 @@ function serverCmdAllDups(%client, %pattern) %format = ""; if(%fileCount>0) { - messageClient(%client, '', %format @ "\c6Name\t\c6Saved By\t\c6BL_ID\t\c6Date"); + messageClient(%client, '', %format @ "\c6Name\t\c6Saved By\t\t\c6Date"); } for(%i = 0; %i < %fileCount; %i++) { %text = %sort.getRowText(%i); @@ -1064,6 +1097,7 @@ function serverCmdAD(%client, %pattern) {serverCmdAllDups(%client, %pattern);} //Cancel all active dups in case of spamming function serverCmdClearDups(%client) { + echo("serverCmdClearDups " @ %client.name); if(!%client.isAdmin) { messageClient(%client, '', "\c6Canceling all duplicators is admin only. Ask an admin for help."); @@ -1084,6 +1118,7 @@ function serverCmdClearDups(%client) //Plant as a different brick group function serverCmdPlantAs(%client, %t0, %t1, %t2, %t3, %t4) { + echo("serverCmdPlantAs " @ %client.name @ " - " @ %t0 SPC %t1 SPC %t2 SPC %t3 SPC %t4); //Check mode if(%client.ndModeIndex != $NDM::PlantCopy) { @@ -1119,7 +1154,7 @@ function serverCmdPlantAs(%client, %t0, %t1, %t2, %t3, %t4) if(!isObject(%targetGroup)) { messageClient(%client, '', "\c6No brick group was found for \"\c3" @ %target @ "\c6\"."); - messageClient(%client, '', "\c6Bricks will be planted in your own group!"); + ndmessageClient(%client, '', "\c6Bricks will be planted in your own group!"); %client.ndSelection.targetGroup = ""; %client.ndSelection.targetBlid = ""; %client.ndUpdateBottomPrint(); diff --git a/scripts/server/functions.cs b/scripts/server/functions.cs index 6decff2..ca2a941 100644 --- a/scripts/server/functions.cs +++ b/scripts/server/functions.cs @@ -1,6 +1,12 @@ -// This file should not exist. Fix later... +//bls 3 + // ------------------------------------------------------------------- +// Utility +function ndmessageClient(%client, %ignore, %msg) { + commandToClient(%client, 'centerPrint', "" @ %msg, 4); +} + //Math functions /////////////////////////////////////////////////////////////////////////// @@ -33,6 +39,21 @@ function ndTransformDirection(%dir, %steps, %mirrX, %mirrY, %mirrZ) return %dir; } +function ndColorFToI(%f){ + %i = %f*255; + %i = mFloor(%i + 0.5); + return %i; +} + +function ndGetColorI(%color){ + %color2 = + ndColorFToI(getWord(%color, 0)) SPC + ndColorFToI(getWord(%color, 1)) SPC + ndColorFToI(getWord(%color, 2)) SPC + ndColorFToI(getWord(%color, 3)) + ; +} + //Get the closest paint color to an rgb value function ndGetClosestColorID(%rgb) { @@ -42,7 +63,7 @@ function ndGetClosestColorID(%rgb) for(%i = 0; %i < 64; %i++) { - %color = getColorI(getColorIdTable(%i)); + %color = ndGetColorI(getColorIdTable(%i)); %diff = vectorLen(vectorSub(%rgb, %color)); @@ -71,7 +92,7 @@ function ndGetClosestColorID2(%rgba) for(%i = 0; %i < 64; %i++) { - %color = getColorI(getColorIdTable(%i)); + %color = ndGetColorI(getColorIdTable(%i)); %alpha = getWord(%color, 3); %diff = vectorLen(vectorSub(%rgb, %color)); @@ -292,7 +313,7 @@ function FxDtsBrick::ndMirrorGhost(%brick, %client, %axis) } else { - messageClient(%client, '', "\c6Sorry, your ghost brick is asymmetric and cannot be mirrored."); + ndmessageClient(%client, '', "\c6Sorry, your ghost brick is asymmetric and cannot be mirrored."); return; } @@ -341,7 +362,7 @@ function FxDtsBrick::ndMirrorGhost(%brick, %client, %axis) } else { - messageClient(%client, '', "\c6Sorry, your ghost brick is asymmetric and cannot be mirrored."); + ndmessageClient(%client, '', "\c6Sorry, your ghost brick is asymmetric and cannot be mirrored."); return; } @@ -384,7 +405,7 @@ function FxDtsBrick::ndMirrorGhost(%brick, %client, %axis) } else { - messageClient(%client, '', "\c6Sorry, your ghost brick is not vertically symmetric and cannot be mirrored."); + ndmessageClient(%client, '', "\c6Sorry, your ghost brick is not vertically symmetric and cannot be mirrored."); return; } } @@ -443,6 +464,7 @@ function ndCreateSimpleBrickTable() } %db.ndSubset = ndSubsetOfDatablock(%db); + if(%db.ndSubset $= "") continue; %file.openForRead(%db.brickFile); %file.readLine(); @@ -694,34 +716,41 @@ function GameConnection::doFillBricks(%this, %subset) %box = %this.ndSelectionBox.getWorldBox(); $ND::FillBrickCount = 0; ndUpdateSpawnedClientList(); - ndFillAreaWithBricks(getWords(%box, 0, 2), getWords(%box, 3, 5)); + + if(%subset == $ND::SubsetLogicBus) { + $ND::FillBrickSubset = $ND::SubsetLogicWire; + ndFillBus(getWords(%box, 0, 2), getWords(%box, 3, 5), getAngleIDFromPlayer(%this.getControlObject()), %this.currentColor); + } else { + ndFillAreaWithBricks(getWords(%box, 0, 2), getWords(%box, 3, 5)); + } - //%s = ($ND::FillBrickCount == 1 ? "" : "s"); - //messageClient(%this, '', "\c6Filled in \c3" @ $ND::FillBrickCount @ "\c6 brick" @ %s); + %s = ($ND::FillBrickCount == 1 ? "" : "s"); + ndmessageClient(%this, '', "\c6Filled in \c3" @ $ND::FillBrickCount @ "\c6 brick" @ %s); } $ND::SubsetDefault = 0; $ND::SubsetLogicWire = 1; -$ND::SubsetLogicBuffer = 2; -$ND::SubsetLogicBufferAl = 3; -$ND::SubsetLogicDff = 4; -$ND::SubsetLogicDffAl = 5; -$ND::SubsetLogicEnabler = 6; -$ND::SubsetLogicEnablerAl = 7; +$ND::SubsetLogicBus = 2; +//$ND::SubsetLogicBuffer = 2; +//$ND::SubsetLogicBufferAl = 3; +//$ND::SubsetLogicDff = 4; +//$ND::SubsetLogicDffAl = 5; +//$ND::SubsetLogicEnabler = 6; +//$ND::SubsetLogicEnablerAl = 7; // Which subset of fill bricks to use - normal or wire function ndSubsetOfDatablock(%data){ if(%data.isLogic) { if(%data.isLogicWire) { return $ND::SubsetLogicWire; - } else if(strStr(%data.uiName, "Buffer") == 0) { - return (strStr(%data.uiName, "Active Low")==-1) ? $ND::SubsetLogicBuffer : $ND::SubsetLogicBufferAl; - } else if(strStr(%data.uiName, "D FlipFlop") == 0) { - return (strStr(%data.uiName, "Active Low")==-1) ? $ND::SubsetLogicDff : $ND::SubsetLogicDffAl; - }else if(strStr(%data.uiName, "Enabler") == 0) { - return (strStr(%data.uiName, "Active Low")==-1) ? $ND::SubsetLogicEnabler : $ND::SubsetLogicEnablerAl; + //} else if(strStr(%data.uiName, "Buffer") == 0) { + // return (strStr(%data.uiName, "Active Low")==-1) ? $ND::SubsetLogicBuffer : $ND::SubsetLogicBufferAl; + //} else if(strStr(%data.uiName, "D FlipFlop") == 0) { + // return (strStr(%data.uiName, "Active Low")==-1) ? $ND::SubsetLogicDff : $ND::SubsetLogicDffAl; + //}else if(strStr(%data.uiName, "Enabler") == 0) { + // return (strStr(%data.uiName, "Active Low")==-1) ? $ND::SubsetLogicEnabler : $ND::SubsetLogicEnablerAl; } else { - return $ND::SubsetDefault; + return ""; } } else { return $ND::SubsetDefault; diff --git a/scripts/server/handshake.cs b/scripts/server/handshake.cs index 2108f6c..3e3de72 100644 --- a/scripts/server/handshake.cs +++ b/scripts/server/handshake.cs @@ -17,28 +17,30 @@ package NewDuplicator_Server //Client responded, so he has new duplicator function serverCmdNdHandshake(%this, %version) { + echo("serverCmdNdHandshake " @ %this.name @ " - " @ %version); cancel(%this.ndHandshakeTimeout); %this.ndClient = true; %this.ndVersion = %version; //Inform client whether he has an outdated version - switch(ndCompareVersion($ND::Version, %version)) - { - case 1: - %m = "\c6Your version of the \c3New Duplicator\c6 is outdated! Some features might not work. "; - %m = %m @ "(Server Version: \c3" @ $ND::Version @ "\c6 | Your Version: \c0" @ %version @ "\c6)"; - //messageClient(%this, '', %m); - - case 2: - //Hide this message on long-running dedicated servers - if($Sim::Time < 86400) - { - %m = "\c6Your version of the \c3New Duplicator\c6 is newer than the server's! Ask the host to update it! "; - %m = %m @ "(Server Version: \c0" @ $ND::Version @ "\c6 | Your Version: \c3" @ %version @ "\c6)"; - //messageClient(%this, '', %m); - } - } + // nobody gives a shit + //switch(ndCompareVersion($ND::Version, %version)) + //{ + // case 1: + // %m = "\c6Your version of the \c3New Duplicator\c6 is outdated! Some features might not work. "; + // %m = %m @ "(Server Version: \c3" @ $ND::Version @ "\c6 | Your Version: \c0" @ %version @ "\c6)"; + // messageClient(%this, '', %m); + // + // case 2: + // //Hide this message on long-running dedicated servers + // if($Sim::Time < 86400) + // { + // %m = "\c6Your version of the \c3New Duplicator\c6 is newer than the server's! Ask the host to update it! "; + // %m = %m @ "(Server Version: \c0" @ $ND::Version @ "\c6 | Your Version: \c3" @ %version @ "\c6)"; + // messageClient(%this, '', %m); + // } + //} } //Compares two version numbers (major.minor.patch) diff --git a/scripts/server/images.cs b/scripts/server/images.cs index 085b42a..0429dea 100644 --- a/scripts/server/images.cs +++ b/scripts/server/images.cs @@ -1,3 +1,4 @@ +//bls 3 // Handles interactions with the handheld duplicator item. // ------------------------------------------------------------------- @@ -230,15 +231,22 @@ package NewDuplicator_Server //Prevent accidently unequipping the duplicator function serverCmdUnUseTool(%client) { - if(%client.ndLastEquipTime + 1.5 > $Sim::Time) - return; - - if(%client.ndModeIndex == $NDM::StackSelect || %client.ndModeIndex == $NDM::BoxSelect) - { - %client.ndToolSchedule = %client.schedule(100, ndUnUseTool); + if( + %client.ndLastEquipTime + 1.5 > $Sim::Time && + isObject(%client.player) && + getSubStr(%client.player.getMountedImage(0).getName(), 0, 8) $= "ND_Image" + ) { + %client.ndLastEquipTime = ""; return; } - + + if(%client.ndModeIndex == $NDM::StackSelect || %client.ndModeIndex == $NDM::BoxSelect) + { + //%client.ndToolSchedule = %client.schedule(100, ndUnUseTool); + %client.ndUnUseTool(); + return; + } + parent::serverCmdUnUseTool(%client); } diff --git a/scripts/server/logicFillBus.cs b/scripts/server/logicFillBus.cs new file mode 100644 index 0000000..4912385 --- /dev/null +++ b/scripts/server/logicFillBus.cs @@ -0,0 +1,29 @@ +//bls 3 + +//function ndRotateVector(%vector, %steps) +function ndFillBus(%pos1, %pos2, %angleId, %color) { + talk(%pos1 @ ", " @ %pos2 @ ", " @ %angleId); + $ND::FillBrickColorID = %color + 1; + ndFillAreaWithBricks(%pos1, %pos2); +} + +function ndNormalizeBox(%box) { + %x1 = getWord(%box, 0); + %y1 = getWord(%box, 1); + %z1 = getWord(%box, 2); + %x2 = getWord(%box, 3); + %y2 = getWord(%box, 4); + %z2 = getWord(%box, 5); + return + mMin(%x1, %x2) SPC + mMin(%y1, %y2) SPC + mMin(%z1, %z2) SPC + mMax(%x1, %x2) SPC + mMax(%y1, %y2) SPC + mMax(%z1, %z2) ; +} +function ndFillAreaWithBricks_box(%pos, %boxSize) { + %boxHalf = vectorScale(%boxSize, 0.5); + %box = vectorSub(%pos, %boxHalf) SPC vectorAdd(%pos, %boxHalf); + ndFillAreaWithBricks(getWords(%box, 0, 2), getWords(%box, 3, 5)); +} diff --git a/scripts/server/modes.cs b/scripts/server/modes.cs index a306116..4dc7bca 100644 --- a/scripts/server/modes.cs +++ b/scripts/server/modes.cs @@ -21,17 +21,17 @@ function NewDuplicatorMode::onCancelBrick(%this, %client){} function NewDuplicatorMode::onCopy(%this, %client) { - messageClient(%client, '', "\c6Copy can not be used in your current duplicator mode."); + ndmessageClient(%client, '', "\c6Copy can not be used in your current duplicator mode."); } function NewDuplicatorMode::onPaste(%this, %client) { - messageClient(%client, '', "\c6Paste can not be used in your current duplicator mode."); + ndmessageClient(%client, '', "\c6Paste can not be used in your current duplicator mode."); } function NewDuplicatorMode::onCut(%this, %client) { - messageClient(%client, '', "\c6Cut can not be used in your current duplicator mode."); + ndmessageClient(%client, '', "\c6Cut can not be used in your current duplicator mode."); } function NewDuplicatorMode::getBottomPrint(%this, %client){} diff --git a/scripts/server/prefs.cs b/scripts/server/prefs.cs index eadb0e2..7e5f1ff 100644 --- a/scripts/server/prefs.cs +++ b/scripts/server/prefs.cs @@ -48,7 +48,7 @@ function ndRegisterPrefsToRtb() RTB_registerPref("Scatter Ghost Bricks", "New Duplicator | Advanced", "$Pref::Server::ND::ScatterGhostBricks", "bool", "Tool_NewDuplicator", true, false, false, ""); RTB_registerPref("Process Bricks per Tick", "New Duplicator | Advanced", "$Pref::Server::ND::ProcessPerTick", "int 1 50000", "Tool_NewDuplicator", 300, false, false, ""); RTB_registerPref("Box Selection Chunk Size", "New Duplicator | Advanced", "$Pref::Server::ND::BoxSelectChunkDim", "int 1 50000", "Tool_NewDuplicator", 6, false, false, ""); - RTB_registerPref("Create Sym Table on Start", "New Duplicator | Advanced", "$Pref::Server::ND::SymTableOnStart", "bool", "Tool_NewDuplicator", false, false, false, ""); + RTB_registerPref("Create Sym Table on Start", "New Duplicator | Advanced", "$Pref::Server::ND::SymTableOnStart", "bool", "Tool_NewDuplicator", true, false, false, ""); //Restore default prefs RTB_registerPref("Check to restore defaults", "New Duplicator | Reset Prefs", "$ND::RestoreDefaultPrefs", "bool", "Tool_NewDuplicator", false, false, false, "ndRestoreDefaultPrefs"); @@ -96,7 +96,7 @@ function ndExtendDefaultPrefValues() if($Pref::Server::ND::ScatterGhostBricks $= "") $Pref::Server::ND::ScatterGhostBricks = true; if($Pref::Server::ND::ProcessPerTick $= "") $Pref::Server::ND::ProcessPerTick = 300; if($Pref::Server::ND::BoxSelectChunkDim $= "") $Pref::Server::ND::BoxSelectChunkDim = 6; - if($Pref::Server::ND::SymTableOnStart $= "") $Pref::Server::ND::SymTableOnStart = false; + if($Pref::Server::ND::SymTableOnStart $= "") $Pref::Server::ND::SymTableOnStart = true; //Always set this to false so we don't accidently reset the prefs $ND::RestoreDefaultPrefs = false; @@ -138,7 +138,7 @@ function ndApplyDefaultPrefValues() $Pref::Server::ND::ScatterGhostBricks = true; $Pref::Server::ND::ProcessPerTick = 300; $Pref::Server::ND::BoxSelectChunkDim = 6; - $Pref::Server::ND::SymTableOnStart = false; + $Pref::Server::ND::SymTableOnStart = true; //Always set this to false so we don't accidently reset the prefs $ND::RestoreDefaultPrefs = false; @@ -189,7 +189,7 @@ function ndDeleteOutdatedPrefs() $Pref::Server::ND::FloatAdminOnly = %floatAdminOnly; $Pref::Server::ND::SaveAdminOnly = %saveAdminOnly; $Pref::Server::ND::LoadAdminOnly = %loadAdminOnly; - $Pref::Server::ND::FillBricksAdminOnly = %fillBricksAdminOnl; + $Pref::Server::ND::FillBricksAdminOnly = %fillBricksAdminOnly; //Settings $Pref::Server::ND::TrustLimit = %trustLimit; $Pref::Server::ND::AdminTrustBypass1 = %adminTrustBypass1; diff --git a/server.cs b/server.cs index 47e0f76..b4114a2 100644 --- a/server.cs +++ b/server.cs @@ -1,7 +1,8 @@ // Executes all required scripts and initializes the server side. // ------------------------------------------------------------------- -$ND::Version = "1.6.2"; +// Not updating because it's useless +$ND::Version = "1.6.3"; $ND::FilePath = filePath($Con::File) @ "/"; $ND::ConfigPath = "config/NewDuplicator/"; @@ -61,5 +62,3 @@ ndResendHandshakes(); if($Pref::Server::ND::SymTableOnStart && !$ND::SymmetryTableCreated){ schedule(10, 0, ndCreateSymmetryTable); } - -exec("./v20fix.cs"); diff --git a/v20fix.cs b/v20fix.cs deleted file mode 100644 index b6b648b..0000000 --- a/v20fix.cs +++ /dev/null @@ -1,15 +0,0 @@ - -function colorFToI(%f){ - %i = %f*255; - %i = mFloor(%i + 0.5); - return %i; -} - -function getColorI(%color){ - %color2 = - colorFToI(getWord(%color, 0)) SPC - colorFToI(getWord(%color, 1)) SPC - colorFToI(getWord(%color, 2)) SPC - colorFToI(getWord(%color, 3)) - ; -}