1616import org .byteskript .skript .compiler .SkriptCompiler ;
1717import org .byteskript .skript .error .ScriptCompileError ;
1818import org .byteskript .skript .error .ScriptLoadError ;
19- import org .byteskript .skript .runtime .internal .EventHandler ;
20- import org .byteskript .skript .runtime .internal .GlobalVariableMap ;
21- import org .byteskript .skript .runtime .internal .Instruction ;
22- import org .byteskript .skript .runtime .internal .ModifiableCompiler ;
19+ import org .byteskript .skript .runtime .internal .*;
2320import org .byteskript .skript .runtime .threading .*;
2421
2522import java .io .*;
@@ -43,7 +40,9 @@ public final class Skript {
4340 final ModifiableCompiler compiler ;
4441 final List <OperationController > processes ;
4542 final Map <Class <? extends Event >, EventHandler > events ;
46- final SkriptMirror mirror = new SkriptMirror (Skript .class );
43+ final SkriptMirror mirror = new SkriptMirror (LOADER );
44+ final WeakList <ScriptClassLoader > loaders = new WeakList <>();
45+ final List <Script > scripts = new ArrayList <>(); // the only strong reference, be careful!
4746 static final GlobalVariableMap VARIABLES = new GlobalVariableMap ();
4847
4948 public static class RuntimeClassLoader extends ClassLoader implements ClassProvider {
@@ -53,14 +52,32 @@ protected RuntimeClassLoader(ClassLoader parent) {
5352
5453 @ Override
5554 public Class <?> loadClass (String name ) throws ClassNotFoundException {
56- return super .loadClass (name );
55+ try {
56+ return super .loadClass (name );
57+ } catch (ClassNotFoundException ex ) {
58+ for (final ScriptClassLoader value : Skript .currentInstance ().loaders .collectRemaining ()) {
59+ if (value == null ) continue ;
60+ try {
61+ return value .loadClass0 (name );
62+ } catch (ClassNotFoundException ignored ) {
63+ }
64+ }
65+ throw ex ;
66+ }
5767 }
5868
5969 @ Override
6070 public Class <?> findClass (String name ) {
6171 try {
6272 return super .findClass (name );
6373 } catch (ClassNotFoundException e ) {
74+ for (final ScriptClassLoader value : Skript .currentInstance ().loaders .collectRemaining ()) {
75+ if (value == null ) continue ;
76+ try {
77+ return value .findClass0 (name );
78+ } catch (ClassNotFoundException ignored ) {
79+ }
80+ }
6481 return Skript .currentInstance ().getClass (name );
6582 }
6683 }
@@ -80,9 +97,9 @@ public Class<?> loadClass(Class<?> aClass, String name, byte[] bytecode) {
8097 }
8198
8299 static class SkriptMirror extends Mirror <Object > {
83- protected SkriptMirror (Object target ) {
84- super (target );
85- useProvider (LOADER );
100+ protected SkriptMirror (ClassProvider provider ) {
101+ super (Skript . class );
102+ useProvider (provider );
86103 }
87104
88105 @ Override
@@ -91,6 +108,16 @@ public Class<?> loadClass(String name, byte[] bytecode) {
91108 }
92109 }
93110
111+ private Class <?> loadClass (String name , byte [] bytecode ) {
112+ return this .createLoader ().loadClass (name , bytecode );
113+ }
114+
115+ private SkriptMirror createLoader () {
116+ final ScriptClassLoader loader = new ScriptClassLoader ();
117+ this .loaders .addActual (loader );
118+ return new SkriptMirror (loader );
119+ }
120+
94121 public Skript (ModifiableCompiler compiler ) {
95122 this (new SkriptThreadProvider (), compiler , Thread .currentThread ());
96123 }
@@ -337,6 +364,33 @@ public PostCompileClass compileScript(final InputStream stream, final String nam
337364 //endregion
338365
339366 //region Script Loading
367+ public void unloadScript (Class <?> main ) {
368+ for (Script script : scripts .toArray (new Script [0 ])) {
369+ if (script .mainClass () == main ) this .unloadScript (script );
370+ }
371+ }
372+
373+ public void unloadScript (Script script ) {
374+ synchronized (events ) {
375+ for (final EventHandler value : events .values ()) {
376+ for (final ScriptRunner trigger : value .getTriggers ().toArray (new ScriptRunner [0 ])) {
377+ if (trigger .owner () != script .mainClass ()) continue ;
378+ value .getTriggers ().remove (trigger );
379+ UnsafeAccessor .graveyard (trigger );
380+ }
381+ }
382+ }
383+ scripts .remove (script );
384+ UnsafeAccessor .graveyard (script );
385+ }
386+
387+ @ Deprecated
388+ public Script compileLoad (File file , String name ) throws IOException {
389+ try (final InputStream stream = new FileInputStream (file )) {
390+ return compileLoad (stream , null );
391+ }
392+ }
393+
340394 @ Deprecated
341395 public Script compileLoad (InputStream stream , String name ) {
342396 return loadScript (compileScript (stream , name ));
@@ -386,22 +440,26 @@ public Script assembleScript(final PostCompileClass... data) {
386440 if (data .length == 0 ) return null ;
387441 final List <Class <?>> classes = new ArrayList <>();
388442 for (PostCompileClass datum : data ) {
389- final Class <?> part = mirror .loadClass (datum .name (), datum .code ());
443+ final Class <?> part = this . createLoader () .loadClass (datum .name (), datum .code ());
390444 classes .add (part );
391445 }
392- return new Script ( false , this , null , classes .toArray (new Class [0 ]));
446+ return assembleScript ( classes .toArray (new Class [0 ]));
393447 }
394448
395- public Script assembleScript (final Class <?> loaded ) {
396- return new Script (false , this , null , loaded );
449+ public Script assembleScript (final Class <?>... loaded ) {
450+ final Script script = new Script (false , this , null , loaded );
451+ this .scripts .add (script );
452+ return script ;
397453 }
398454
399455 public Script loadScript (final Class <?> loaded ) {
400- return new Script (this , null , loaded );
456+ final Script script = new Script (this , null , loaded );
457+ this .scripts .add (script );
458+ return script ;
401459 }
402460
403461 public Script loadScript (final PostCompileClass datum ) {
404- return new Script (this , null , mirror .loadClass (datum .name (), datum .code ()));
462+ return loadScript (this .loadClass (datum .name (), datum .code ()));
405463 }
406464
407465 public Collection <Script > loadScripts (final PostCompileClass [] data ) {
@@ -413,7 +471,7 @@ public Collection<Script> loadScripts(final PostCompileClass[] data) {
413471 }
414472
415473 public Script loadScript (final byte [] bytecode , final String name ) {
416- return new Script (this , null , mirror .loadClass (name , bytecode ));
474+ return loadScript (this .loadClass (name , bytecode ));
417475 }
418476
419477 public Script loadScript (final byte [] bytecode ) throws IOException {
@@ -422,7 +480,7 @@ public Script loadScript(final byte[] bytecode) throws IOException {
422480
423481 public Script loadScript (final InputStream stream , final String name )
424482 throws IOException {
425- return new Script (this , null , mirror .loadClass (name , stream .readAllBytes ()));
483+ return loadScript (this .loadClass (name , stream .readAllBytes ()));
426484 }
427485
428486 public Script loadScript (final InputStream stream )
@@ -440,7 +498,7 @@ public Script loadScript(final File source)
440498 public Script loadScript (final File source , final String name )
441499 throws IOException {
442500 try (InputStream stream = new FileInputStream (source )) {
443- return new Script (this , source , mirror .loadClass (name , stream .readAllBytes ()));
501+ return loadScript (this .loadClass (name , stream .readAllBytes ()));
444502 }
445503 }
446504 //endregion
0 commit comments