diff --git a/README.md b/README.md index ad5ff9e..7695286 100644 --- a/README.md +++ b/README.md @@ -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)) @@ -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) @@ -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 @@ -315,7 +324,6 @@ 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` @@ -323,21 +331,28 @@ Switch to `lslforge` subfolder. ### 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. diff --git a/doc/update_site_map.jpg b/doc/update_site_map.jpg new file mode 100644 index 0000000..0b8806b Binary files /dev/null and b/doc/update_site_map.jpg differ diff --git a/eclipse/artifacts.jar b/eclipse/artifacts.jar index aba669c..3187608 100644 Binary files a/eclipse/artifacts.jar and b/eclipse/artifacts.jar differ diff --git a/eclipse/content.jar b/eclipse/content.jar index afb184d..55f1075 100644 Binary files a/eclipse/content.jar and b/eclipse/content.jar differ diff --git a/eclipse/features/lslforge_0.1.9.9.jar b/eclipse/features/lslforge_0.1.9.9.jar index fd972b9..c449b58 100644 Binary files a/eclipse/features/lslforge_0.1.9.9.jar and b/eclipse/features/lslforge_0.1.9.9.jar differ diff --git a/eclipse/features/lslforge_part_linux_x86_0.1.9.9.jar b/eclipse/features/lslforge_part_linux_x86_0.1.9.9.jar index a46d8cb..34a57b0 100644 Binary files a/eclipse/features/lslforge_part_linux_x86_0.1.9.9.jar and b/eclipse/features/lslforge_part_linux_x86_0.1.9.9.jar differ diff --git a/eclipse/features/lslforge_part_linux_x86_64_0.1.9.9.jar b/eclipse/features/lslforge_part_linux_x86_64_0.1.9.9.jar index a7e9fc9..29614fc 100644 Binary files a/eclipse/features/lslforge_part_linux_x86_64_0.1.9.9.jar and b/eclipse/features/lslforge_part_linux_x86_64_0.1.9.9.jar differ diff --git a/eclipse/features/lslforge_part_macosx_x86_64_0.1.9.9.jar b/eclipse/features/lslforge_part_macosx_x86_64_0.1.9.9.jar index f9c7441..71acd58 100644 Binary files a/eclipse/features/lslforge_part_macosx_x86_64_0.1.9.9.jar and b/eclipse/features/lslforge_part_macosx_x86_64_0.1.9.9.jar differ diff --git a/eclipse/features/lslforge_part_win32_x86_0.1.9.9.jar b/eclipse/features/lslforge_part_win32_x86_0.1.9.9.jar index 46f7a7b..90af10d 100644 Binary files a/eclipse/features/lslforge_part_win32_x86_0.1.9.9.jar and b/eclipse/features/lslforge_part_win32_x86_0.1.9.9.jar differ diff --git a/eclipse/plugins/lslforge_0.1.9.9.jar b/eclipse/plugins/lslforge_0.1.9.9.jar index d0ca3b0..7748f55 100644 Binary files a/eclipse/plugins/lslforge_0.1.9.9.jar and b/eclipse/plugins/lslforge_0.1.9.9.jar differ diff --git a/eclipse/plugins/lslforge_linux_x86_0.1.9.9.jar b/eclipse/plugins/lslforge_linux_x86_0.1.9.9.jar index 6c0b05f..61df93c 100644 Binary files a/eclipse/plugins/lslforge_linux_x86_0.1.9.9.jar and b/eclipse/plugins/lslforge_linux_x86_0.1.9.9.jar differ diff --git a/eclipse/plugins/lslforge_linux_x86_64_0.1.9.9.jar b/eclipse/plugins/lslforge_linux_x86_64_0.1.9.9.jar index 77d2c00..2b4edb8 100644 Binary files a/eclipse/plugins/lslforge_linux_x86_64_0.1.9.9.jar and b/eclipse/plugins/lslforge_linux_x86_64_0.1.9.9.jar differ diff --git a/eclipse/plugins/lslforge_macosx_x86_64_0.1.9.9.jar b/eclipse/plugins/lslforge_macosx_x86_64_0.1.9.9.jar index 576d9ed..4e5092d 100644 Binary files a/eclipse/plugins/lslforge_macosx_x86_64_0.1.9.9.jar and b/eclipse/plugins/lslforge_macosx_x86_64_0.1.9.9.jar differ diff --git a/eclipse/plugins/lslforge_win32_x86_0.1.9.9.jar b/eclipse/plugins/lslforge_win32_x86_0.1.9.9.jar index 0bfa281..f337082 100644 Binary files a/eclipse/plugins/lslforge_win32_x86_0.1.9.9.jar and b/eclipse/plugins/lslforge_win32_x86_0.1.9.9.jar differ diff --git a/lslforge/eclipse/lslforge/src/lslforge/util/Util.java b/lslforge/eclipse/lslforge/src/lslforge/util/Util.java index 91e1c99..091f16d 100644 --- a/lslforge/eclipse/lslforge/src/lslforge/util/Util.java +++ b/lslforge/eclipse/lslforge/src/lslforge/util/Util.java @@ -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; @@ -238,7 +239,6 @@ public static Object find(Predicate p, Object[] list) { return null; } - @SuppressWarnings("unchecked") public static T[] arrayMap(ArrayMapFunc f, Object[] list) { T[] o = (T[]) Array.newInstance(f.elementType(), list.length); @@ -250,7 +250,6 @@ public static T[] arrayMap(ArrayMapFunc f, Object[] list) { } public static T[] listMapToArray(MapFunc f, List list) { - @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(f.elementType(), list.size()); int i = 0; @@ -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(); @@ -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) { diff --git a/lslforge/haskell/src/Language/Lsl/Internal/SimLL.hs b/lslforge/haskell/src/Language/Lsl/Internal/SimLL.hs index 3a0d68b..1c40c98 100644 --- a/lslforge/haskell/src/Language/Lsl/Internal/SimLL.hs +++ b/lslforge/haskell/src/Language/Lsl/Internal/SimLL.hs @@ -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) @@ -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 @@ -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 @@ -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 @@ -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! @@ -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), diff --git a/lslforge/haskell/stack.yaml b/lslforge/haskell/stack.yaml index adec8d1..bbea385 100644 --- a/lslforge/haskell/stack.yaml +++ b/lslforge/haskell/stack.yaml @@ -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. diff --git a/lslforge/haskell/stack.yaml.lock b/lslforge/haskell/stack.yaml.lock index 9d48cbc..84717da 100644 --- a/lslforge/haskell/stack.yaml.lock +++ b/lslforge/haskell/stack.yaml.lock @@ -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