Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 32 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@ Because it is an Eclipse plugin, when you use LSLForge you can take advantage of
### Changelog

* **0.1.9.9**
* [@PellSmit](https://github.com/PellSmit) did an amazing job bringing this version up-to-date with the Mac Silicone, newest Java and Eclipse:
* [@PellSmit](https://github.com/PellSmit) did an amazing job bringing this version up-to-date with newer Haskell(we'll see Apple Silicon Native LSLForge soon), newest Java and Eclipse:
* Java update to 11 (`JavaSE-11`), which allows to run the latest Eclipse editions.
* Update to `ghc-8.10.7`.
* Simulator up to [2022-01-06.567269](https://releasenotes.secondlife.com/simulator/2022-01-06.567269.html)
* [2021-10-25.565008](https://releasenotes.secondlife.com/simulator/2021-10-25.565008.html)
- [x] [`PRIM_PROJECTOR`](http://wiki.secondlife.com/wiki/PRIM_PROJECTOR)
- [ ] (#66) - 1024 bytes returned from [llGetNotecardLine](http://wiki.secondlife.com/wiki/LlGetNotecardLine)
- [x] (#66) - 1024 bytes returned from [llGetNotecardLine](http://wiki.secondlife.com/wiki/LlGetNotecardLine)
starting with above simulator version.
* Fix debugger runtime functions (llSetObjectName, llSetObjectDesc and llHTTPResponse) related to #66
* Fix URIDecode to handle multi-byte character in Java plugin(Util.java)
* Plugin name for macOS:
- `lslforge_part_macosx_x86` -> `lslforge_part_macosx_x86_64`
* Enlarge input field of `new LSLForge project wizard`.

* **0.1.9.8**
* Update to `ghc-8.6.5` (Thanks [@PellSmit](https://github.com/PellSmit))
Expand Down Expand Up @@ -132,29 +137,31 @@ The official group for LSLForge Editor tool is [LSLForge Users](secondlife:///ap

## Installing

* Java 8 JDK is currently used for generating the plugin. You may find that you need to update to Java 8 or later in order to use the plugin.
* ~~Java 8 JDK is currently used for generating the plugin. You may find that you need to update to Java 8 or later in order to use the plugin.~~
* Version 0.1.9.9 was built on Eclipse RCP 2021-12 with Java 11, we have no compatibility test for older Eclipse. It seems work with Java 17.

### Eclipse Plugin

#### Incompatible Versions

* **WARNING** Doesn't seem to work in:
* Eclipse IDE `2021-09` R (`4.21.0`)
* ~~**WARNING** Doesn't seem to work in:~~
* ~~Eclipse IDE `2021-09` R (`4.21.0`)~~

#### Compatible Versions

The following [Eclipse Distributions](https://www.eclipse.org/downloads/packages/release) were found working:

* Eclipse IDE `2020-12` (`4.18.0`)
* Eclipse IDE `2019-12` (`4.14.0`)
* Eclipse IDE `2019‑06` (`4.12.0`)
* Eclipse Photon (`4.8.0`)
* Eclipse Oxygen
* Eclipse IDE `2021-12` (`4.22.0`)

> NOTE: Oomph seems to restore LSLForge native setting despite attempts to overwrite the field. The only workaround for now is to check `[X] Skip automatic task execution at startup time` under Oomph > Setup Tasks in Preferences.

Platforms that used to work but **not tested recently**:

* Eclipse IDE `2020-12` (`4.18.0`)
* Eclipse IDE `2019-12` (`4.14.0`)
* Eclipse IDE `2019‑06` (`4.12.0`)
* Eclipse Photon (`4.8.0`)
* Eclipse Oxygen
* Eclipse Neon (4.6.0)
* Eclipse Mars.2 (4.5.2)
* Eclipse Mars.1 (4.5.1)
Expand Down Expand Up @@ -273,6 +280,8 @@ Run `stack upgrade` to upgrade to the latest version.
You will need to enter `stack setup` if you have a freshly installed Stack, or don't have the relevant compiler already set up. (Stack will tell you if you need to run this additional step.)

Now run with admin terminal `stack install` in `lslforge/haskell` folder to build and install the **LSLForge** binary in one step. (Weird access denied errors are due to Antivirus.)
On Mac or linux, `stack build` installs LSLForge binary to ~/.local/bin,
no need root priviledge.

### Post-compilation

Expand Down Expand Up @@ -315,29 +324,35 @@ Switch to `lslforge` subfolder.
* `./codegen.sh`
* `(cd eclipse/update-site; ./clean.sh)`
* macOS
* ``
* `(cd haskell; stack install --executable-stripping)`
* `./copy_mac_x86_64.sh`
* `./codegen.sh`
* `(cd eclipse/update-site; ./clean.sh)`

### Eclipse Plug-in Compilation

* Move existing plugin files from `eclipse\` to `eclipse\archive\x.x.x\` (keep `index.html`).
* If you are a first builder of that version, move existing plugin files from `eclipse\` to `eclipse\archive\x.x.x\` (keep `index.html`).
* if you want to contribute some platform specific plugins, leave the `eclipse` folder as it is.

* Eclipse for RCP and RAP Developers - Using `Luna SR2`
* Eclipse for RCP and RAP Developers - Using `2021-12`
* Use empty workspace
* Import projects from `lslforge\eclipse\` (without copying)
* If you see artifacts in the `update-site`'s project folder (`features`, `plugins`, `artifacts.jar`, `content.jar`), run `clean.bat` or `clean.sh` to delete them.
* Double-click `update-site\site.xml` and select `Build All`
* For the first builder, double-click `update-site\site.xml` and select `Build All`
* Generated files are:
* `features`
* `plugins`
* `artifacts.jar`
* `content.jar`
* Move generated files to `eclipse\`

* Copy `index.html` (static file) to `eclipse\` if it is missing.
* Move generated files to `eclipse\` if you are the first builder.

![Image](doc/update_site_map.jpg)
* For the contributer, double-click `update-site/site.xml`, click the plugin name you want to build in the list then click `Build` button.
* Generated files are same as above, but ignore artifacts.jar, content.jar and features/*.jar
* Move `lslforge/eclipse/update-site/plugins/lslforge_xxxxx.jar` to `eclipse/plugins/`
* Push the moved file to your repository and make a pull request.

* Copy `index.html` (static file) to `eclipse\` if it is missing.

* Test generated update site with a fresh installation of Eclipse using Local path for plugin:
* If you don't want fresh Eclipse, uninstall existing LSLForge plug-in and carefully remove every folder from the Eclipse cache.
Expand Down
Binary file added doc/update_site_map.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified eclipse/artifacts.jar
Binary file not shown.
Binary file modified eclipse/content.jar
Binary file not shown.
Binary file modified eclipse/features/lslforge_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/features/lslforge_part_linux_x86_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/features/lslforge_part_linux_x86_64_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/features/lslforge_part_macosx_x86_64_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/features/lslforge_part_win32_x86_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/plugins/lslforge_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/plugins/lslforge_linux_x86_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/plugins/lslforge_linux_x86_64_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/plugins/lslforge_macosx_x86_64_0.1.9.9.jar
Binary file not shown.
Binary file modified eclipse/plugins/lslforge_win32_x86_0.1.9.9.jar
Binary file not shown.
35 changes: 25 additions & 10 deletions lslforge/eclipse/lslforge/src/lslforge/util/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
Expand Down Expand Up @@ -238,7 +239,6 @@ public static Object find(Predicate p, Object[] list) {
return null;
}

@SuppressWarnings("unchecked")
public static <T> T[] arrayMap(ArrayMapFunc<T> f, Object[] list) {
T[] o = (T[]) Array.newInstance(f.elementType(), list.length);

Expand All @@ -250,7 +250,6 @@ public static <T> T[] arrayMap(ArrayMapFunc<T> f, Object[] list) {
}

public static <S,T> T[] listMapToArray(MapFunc<S,T> f, List<S> list) {
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(f.elementType(), list.size());

int i = 0;
Expand Down Expand Up @@ -338,6 +337,7 @@ public static String URIEncode(String s) {

public static String URIDecode(String s) {
StringBuilder buf = new StringBuilder();
ByteBuffer tmp = ByteBuffer.allocate(s.length());

char[] cs = s.toCharArray();

Expand All @@ -350,21 +350,36 @@ public static String URIDecode(String s) {
char c1 = cs[++i];
char c2 = cs[++i];

char c3 = Character.toLowerCase(c1);
char c4 = Character.toLowerCase(c2);
byte c3 = (byte)Character.toLowerCase(c1);
byte c4 = (byte)Character.toLowerCase(c2);

if ((c3 >= 0 && c3 <= '9' || c3 >= 'a' && c3 <= 'f') &&
(c4 >= 0 && c4 <= '9' || c4 >= 'a' && c4 <= 'f')) {
char c = (char)(
if ((c3 >= '0' && c3 <= '9' || c3 >= 'a' && c3 <= 'f') &&
(c4 >= '0' && c4 <= '9' || c4 >= 'a' && c4 <= 'f')) {
byte c = (byte)(
(((c3 <= '9') ? (c3 - '0') : 10 + c3 - 'a') << 4) |
(((c4 <= '9') ? (c4 - '0') : 10 + c4 - 'a')));
buf.append(c);
tmp.put(c);
} else {
buf.append('%').append(c1).append(c2);
}
} else buf.append(cs[i]);
} else {
if ( tmp.position() > 0 ) {
try {
buf.append(new String(tmp.array(), 0, tmp.position(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
// Nothing to do here
}
tmp.clear();
}
buf.append(cs[i]);
}
}

if ( tmp.position() > 0 )
try {
buf.append(new String(tmp.array(), 0, tmp.position(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
// Nothing to do
}
return buf.toString();
}
private static boolean shouldEncode(char c) {
Expand Down
40 changes: 33 additions & 7 deletions lslforge/haskell/src/Language/Lsl/Internal/SimLL.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import Control.Monad(
import Control.Monad.Except(MonadError(..))
import Data.List(find,foldl',isSuffixOf,elemIndex)
import Data.Bits((.&.),(.|.),bit,clearBit,complement,setBit,shiftL,testBit)
import qualified Data.ByteString.Lazy as B
import qualified Data.ByteString.Lazy.UTF8 as U
import Data.Int()
import Data.LabelExtras
import Data.Maybe(fromMaybe,isNothing, isJust, catMaybes)
Expand Down Expand Up @@ -166,7 +168,7 @@ llHTTPResponse (ScriptInfo _ _ sn pk mevent) [KVal k, IVal status, SVal body] =
throwError $ "trying to repsond to a HTTP request " ++
"received by a different script!"
worldPendingHTTPResponses `modM_` M.delete k
putWorldEvent 0 (AvatarInputEvent av (AvatarHTTPResponse k status (take 2048 body)))
putWorldEvent 0 (AvatarInputEvent av (AvatarHTTPResponse k status (takeBytes 2048 body)))

llGetHTTPHeader (ScriptInfo _ _ sn pk _) [KVal k, SVal header] = do
PendingHTTPResponse av (pk',sn') base path query ip ua _ <- getM $ lm k.worldPendingHTTPResponses
Expand Down Expand Up @@ -1202,10 +1204,10 @@ llGetObjectName (ScriptInfo _ _ _ pkey _) [] =
continueS =<< getM (primName.wprim pkey)

llSetObjectName (ScriptInfo _ _ _ pkey _) [SVal name] =
(primName.wprim pkey) =: take 255 name >> continueV
(primName.wprim pkey) =: takeBytes 63 name >> continueV

llSetObjectDesc (ScriptInfo _ _ _ pkey _) [SVal desc] =
primDescription.wprim pkey =: take 127 desc >> continueV
primDescription.wprim pkey =: takeBytes 127 desc >> continueV

llGetObjectPermMask (ScriptInfo oid _ _ _ _) [IVal maskId] =
getObjectPermMask oid maskId >>= continueI
Expand Down Expand Up @@ -1891,7 +1893,7 @@ llGetNotecardLine info@(ScriptInfo _ _ sn pk _) [SVal name, IVal lineNumber] =
Nothing -> sayErr info ("Couldn't find notecard " ++ name) >> continueK nullKey
Just notecard -> do
key <- newKey
pushDataserverEvent pk sn key $ maybe cEOF (take 255) $
pushDataserverEvent pk sn key $ maybe cEOF (takeBytes 1024) $
lookupByIndex lineNumber $ invNotecardLines $ inventoryItemData notecard
continueK key

Expand Down Expand Up @@ -2171,15 +2173,15 @@ llRemoteDataSetRegion info [] = void $
-------------------------------------------------------------------------------

llDialog info@(ScriptInfo _ _ _ pk _) [KVal ak, SVal message, LVal buttons, IVal channel] =
do when (length message > 512) $
do when (B.length (U.fromString message) > 512) $
doErr "message too long, must be less than 512 characters"
when (null message) $
doErr "must supply a message"
unless (all ((==LLString) . typeOfLSLValue) buttons) $
doErr "button list must contain only strings"
let buttons' = take 12 $ map ( \ (SVal s) -> s) buttons
when (any ((24 <) . length) buttons') $
doErr "Button Labels cannot have more that 24 characters"
when (any ((24 <) . B.length . U.fromString) buttons') $
doErr "Button Labels cannot have more that 24 bytes"
when (any null buttons') $ doErr "all buttons must have label strings"
getM (wav ak) <||> throwError ("no such agent/avatar - " ++ unLslKey ak)
putWorldEvent 0 (DialogEvent ak message buttons' channel pk) -- deprecated!
Expand Down Expand Up @@ -2302,6 +2304,30 @@ yieldV t = yieldWith t VoidVal
doneWith v = return (EvalComplete Nothing,v)
doneV = doneWith VoidVal

takeBytes n = toString . B.take n . U.fromString

-- | Convert a UTF8 encoded bytestring into a Haskell string.
-- Invalid characters are replaced with @\'?\'@ after SL SIMs.
toString :: B.ByteString -> String
toString = foldrU (:) []

-- | Traverse a bytestring (right biased).
foldrU cons nil cs =
case uncons cs of
Just (a,n,as) ->
(if a == U.replacement_char then napp n (cons '?') else cons a) $ foldrU cons nil as
Nothing -> nil
where
napp n f | n <= 0 = id
| n == 1 = f
| otherwise = f . napp (n - 1) f
(.) f g = \x -> f (g x)

-- | Get the first character of a byte string, if any.
-- Malformed characters are replaced by @\'?\'@ after SL SIMs.
uncons bs = do (c,n) <- U.decode bs
return (c, n, B.drop n bs)

defaultPredefs :: Monad m => M.Map String (PredefFunc m)
defaultPredefs = M.fromList $ map (\(x,y) -> (x, defaultPredef x y)) [
("llAddToLandBanList",llAddToLandBanList),
Expand Down
2 changes: 1 addition & 1 deletion lslforge/haskell/stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# resolver:
# name: custom-snapshot
# location: "./custom-snapshot.yaml"
resolver: lts-18.21
resolver: lts-18.24

# User packages to be built.
# Various formats can be used as shown in the example below.
Expand Down
8 changes: 4 additions & 4 deletions lslforge/haskell/stack.yaml.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
packages: []
snapshots:
- completed:
size: 586110
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/21.yaml
sha256: ce4fb8d44f3c6c6032060a02e0ebb1bd29937c9a70101c1517b92a87d9515160
original: lts-18.21
size: 587821
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/24.yaml
sha256: 06d844ba51e49907bd29cb58b4a5f86ee7587a4cd7e6cf395eeec16cba619ce8
original: lts-18.24