mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* added debugs for boatmove * log component send * added option to resend components * compilation fix * activate by default * cleanup fix no1 more debug logs * test client now ignores/removes objects out of range lets see what explodes * syntax fix * syntax fix.. * need a copy of the keys * handle equipped items * handle server side view range change * test char on boat and move to npc * compilation fix? * more logs * corrected logs * the boat needs to move more * change order, first smooth move then new objects * correct fix I think send new objects for all newer clients on the boat after the boat pkt is send (which also updates the position for the client) * cleanup, fixed first test by sending also the playerposition when a new obj appears * test for item on boat * need to move the boat further so that components are in range * is the test wrong or is it a bug? * move further * ability to disable auto delete of objects to be able to test serverside remove pkts * change start position of the boat * cleanup and fixed tests? * more cleanup * docs
256 lines
7.1 KiB
C++
256 lines
7.1 KiB
C++
use file;
|
|
use uo;
|
|
use os;
|
|
use polsys;
|
|
|
|
const IGNORE_TEST := 255; // only valid for setup or programs
|
|
|
|
function ret_error( str )
|
|
return error{ errortext := str };
|
|
endfunction
|
|
|
|
function ret_error_not_equal( actual, expected, message )
|
|
if ( actual != expected )
|
|
return ret_error( $"{message}" );
|
|
endif
|
|
|
|
return 1;
|
|
endfunction
|
|
|
|
function createAccountWithChar( accname, psw )
|
|
var a := FindAccount( accname );
|
|
if ( !a )
|
|
a := CreateAccount( accname, psw, 1 );
|
|
if ( !a )
|
|
return ret_error( "Failed to create account" );
|
|
endif
|
|
a.set_uo_expansion( "AOS" );
|
|
a.addcharacter( 0 );
|
|
endif
|
|
var char := a.getcharacter( 1 );
|
|
if ( !char )
|
|
return ret_error( "Could not find char at slot 1" );
|
|
endif
|
|
return char;
|
|
endfunction
|
|
|
|
function dprint( unused what )
|
|
// print( what );
|
|
endfunction
|
|
|
|
class ResourceManager()
|
|
function ResourceManager( this )
|
|
this.resources := array{};
|
|
endfunction
|
|
|
|
function Cleanup( this )
|
|
dprint( $"CLEANUP! {this.resources}" );
|
|
while ( this.resources.size() )
|
|
var resource_entry := this.resources[this.resources.size()];
|
|
var resource := resource_entry[1];
|
|
var cleanup_fn := resource_entry[2];
|
|
|
|
dprint( $"cleanup 0x{resource.serial:x} ({TypeOf( resource )}):" );
|
|
var res := cleanup_fn.call( resource );
|
|
dprint( $" - {res}" );
|
|
this.resources.shrink( this.resources.size() - 1 );
|
|
endwhile
|
|
return 1;
|
|
endfunction
|
|
|
|
function UpdateConfiguration( this, configs, filename := "::config/servspecopt.cfg" )
|
|
var originalConf := ReadFile( filename );
|
|
if ( originalConf == error )
|
|
return ret_error( $"Could not read {filename} file: ${originalConf}" );
|
|
endif
|
|
|
|
var newConf := array;
|
|
foreach line in originalConf
|
|
if ( line.length() > 1 && line[1, 1] != "#" )
|
|
var keyIndex := line.find( "=" );
|
|
if ( keyIndex )
|
|
var key := line[1, keyIndex - 1];
|
|
if ( configs.exists( key ) )
|
|
continue;
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
newConf.append( line );
|
|
endforeach
|
|
|
|
foreach key in configs
|
|
newConf.append( $"{_key_iter}={key}" );
|
|
endforeach
|
|
|
|
var writeResult := WriteFile( filename, newConf );
|
|
if ( writeResult == error )
|
|
return ret_error( $"Could not write ${filename} file: ${writeResult}" );
|
|
endif
|
|
|
|
var res := ReloadConfiguration();
|
|
|
|
// Apend the config before returning error, so we can still restore it.
|
|
this.resources.append( array{ struct{ filename := filename, configuration := originalConf },
|
|
@RestoreConfiguration } );
|
|
if ( !res )
|
|
return res;
|
|
endif
|
|
|
|
return 1;
|
|
endfunction
|
|
|
|
function GrantPrivilege( this, character, privilege )
|
|
var res := uo::GrantPrivilege( character, privilege );
|
|
if ( !res )
|
|
return res;
|
|
endif
|
|
|
|
character.enable( privilege );
|
|
|
|
this.resources.append( array{ { character, privilege }, @RevokePrivilege } );
|
|
|
|
return 1;
|
|
endfunction
|
|
|
|
function RevokePrivilege( privilege_resource )
|
|
var [ character, privilege ] := privilege_resource;
|
|
|
|
return uo::RevokePrivilege( character, privilege );
|
|
endfunction
|
|
|
|
function RestoreConfiguration( configuration_resource )
|
|
var { filename, configuration } := configuration_resource;
|
|
WriteFile( filename, configuration );
|
|
ReloadConfiguration();
|
|
return 1;
|
|
endfunction
|
|
|
|
function CreateMultiAtLocation( this, x, y, z, objtype, flags := 0, realm := _DEFAULT_REALM )
|
|
// Module functions are registered in global scope as well
|
|
var resource :=::CreateMultiAtLocation( x, y, z, objtype, flags, realm );
|
|
if ( !resource )
|
|
return resource;
|
|
endif
|
|
|
|
this.resources.append( array{ resource, @DestroyMultiResource } );
|
|
dprint( $"created resource resource={resource} this.resources={this.resources}" );
|
|
return resource;
|
|
endfunction
|
|
|
|
function DestroyMultiResource( multi )
|
|
dprint( $"cleanup multi 0x{multi.serial:x}" );
|
|
return DestroyMulti( multi );
|
|
endfunction
|
|
|
|
function CreateItemAtLocation( this, x, y, z, objtype, amount := 1, realm := _DEFAULT_REALM )
|
|
var resource := uo::CreateItemAtLocation( x, y, z, objtype, amount, realm );
|
|
if ( !resource )
|
|
return resource;
|
|
endif
|
|
this.resources.append( array{ resource, @DestroyItemResource } );
|
|
return resource;
|
|
endfunction
|
|
|
|
function CreateItemInContainer( this, container, objtype, amount := 1, x := -1, y := -1 )
|
|
var resource := uo::CreateItemInContainer( container, objtype, amount, x, y );
|
|
if ( !resource )
|
|
return resource;
|
|
endif
|
|
this.resources.append( array{ resource, @DestroyItemResource } );
|
|
return resource;
|
|
endfunction
|
|
|
|
function Start_Script( this, script_name, byref param := 0 )
|
|
var resource := os::Start_Script( script_name, param );
|
|
if ( !resource )
|
|
return resource;
|
|
endif
|
|
this.resources.append( array{ resource, @DestroyScriptResource } );
|
|
return resource;
|
|
endfunction
|
|
|
|
function DestroyScriptResource( script )
|
|
dprint( $"cleanup script {script} {script.state} {script.pid}" );
|
|
// Swallow the "Script has been destroyed" error
|
|
return script.kill() ?: 1;
|
|
endfunction
|
|
|
|
function DestroyItemResource( item )
|
|
dprint( $"cleanup item 0x{item.serial:x}" );
|
|
return DestroyItem( item );
|
|
endfunction
|
|
|
|
function CreateNPCFromTemplate( this, template, x, y, z, override_properties := 0,
|
|
realm := _DEFAULT_REALM, forcelocation := 0 )
|
|
|
|
var resource := uo::CreateNPCFromTemplate( template, x, y, z, override_properties, realm,
|
|
forcelocation );
|
|
if ( !resource )
|
|
return resource;
|
|
endif
|
|
this.resources.append( array{ resource, @DestroyNpcResource } );
|
|
return resource;
|
|
endfunction
|
|
|
|
function DestroyNpcResource( npc )
|
|
dprint( $"cleanup npc {npc.name} 0x{npc.serial:x}" );
|
|
var x := npc.x, y := npc.y, z := npc.z, serial := npc.serial;
|
|
var res := npc.kill();
|
|
if ( !res )
|
|
return res;
|
|
endif
|
|
|
|
var corpses := ListItemsNearLocationOfType( x, y, z, 0, 0x2006 );
|
|
foreach corpse in corpses
|
|
if ( serial == corpse.ownerserial )
|
|
return DestroyItem( corpse );
|
|
endif
|
|
endforeach
|
|
|
|
return ret_error( $"Could not find corpse for NPC 0x{serial:x} at ({x}, {y}, {z}) (corpses: {corpses.size()})" );
|
|
endfunction
|
|
|
|
function AddRealm( this, realm_name, base_realm )
|
|
var res := polsys::AddRealm( realm_name, base_realm );
|
|
if ( !res )
|
|
return res;
|
|
endif
|
|
|
|
this.resources.append( array{ realm_name, @DestroyRealmResource } );
|
|
|
|
return res;
|
|
endfunction
|
|
|
|
function DestroyRealmResource( realm_name )
|
|
return DeleteRealm( realm_name );
|
|
endfunction
|
|
endclass
|
|
|
|
function copy_file( source, destination )
|
|
var file_in := OpenBinaryFile( source, OPENMODE_IN );
|
|
if ( !file_in )
|
|
return file_in;
|
|
endif
|
|
|
|
var file_out := OpenBinaryFile( destination, OPENMODE_OUT | OPENMODE_TRUNC );
|
|
if ( !file_out )
|
|
return file_out;
|
|
endif
|
|
|
|
var byte, i := 0;
|
|
|
|
do
|
|
byte := file_in.getInt8();
|
|
if ( byte == error )
|
|
break;
|
|
endif
|
|
file_out.setInt8( byte );
|
|
dowhile ( 1 );
|
|
|
|
file_in.close();
|
|
file_out.close();
|
|
|
|
return 1;
|
|
endfunction
|
|
|