| Blockland Forums > Modification Help |
| Scriptgroup, Scriptobject |
| << < (4/4) |
| heedicalking:
how does that onplant thing even work? it won't load bricks not in a chunk, and won't put them in one? |
| Port:
I'll be very generous here and provide the chunk system from my Minecraft game-mode. --- Code: (chunk.cs) ---function roundToChunkIndex( %pos ) { %x = mFloor( getWord( %pos, 0 ) / 16 ); // 32x Cube %y = mFloor( getWord( %pos, 1 ) / 16 ); // 32x Cube return %x SPC %y; } function chunkGroup() { if ( !strLen( $MC::CurrWorld ) ) { return -1; } if ( isObject( %obj = nameToID( "chunkGroup" ) ) ) { return %obj; } %obj = new scriptGroup( "chunkGroup" ); %obj.loadWorld(); %obj.saveWorldTick = %obj.schedule( 0, "saveWorldTick" ); return %obj; } function chunkGroup::loadWorld( %this ) { if ( !strLen( $MC::CurrWorld ) ) { return false; } %path = "config/mc/world/" @ $MC::CurrWorld @ "/world.dat"; if ( !isFile( %path ) ) { return false; } %fo = new fileObject(); %fo.openForWrite( %path ); while ( !%fo.isEOF() ) { %line = %fo.readLine(); if ( !strLen( %line ) ) { continue; } if ( getSubStr( %line, 0, 1 ) $= "#" ) { continue; } %ploc = strPos( %line, "\t" ); if ( %ploc < 0 ) { continue; } %field = getSubStr( %line, 0, %ploc ); %value = getSubStr( %line, %ploc + 1, strLen( %line ) ); switch$ ( %field ) { case "name": // currently unused case "seed": $MC::CurrSeed = %value; case "time": mcTickSO().time = %value % 24000; } } %fo.close(); %fo.delete(); return true; } function chunkGroup::saveWorldTick( %this ) { cancel( %this.saveWorldTick ); if ( !strLen( $MC::CurrWorld ) ) { return false; } %path = "config/mc/world/" @ $MC::CurrWorld @ "/world.dat"; if ( !isWriteableFileName( %path ) ) { return false; } %fo = new fileObject(); %fo.openForWrite( %path ); %fo.writeLine( "name" TAB $MC::CurrWorld ); %fo.writeLine( "seed" TAB $MC::CurrSeed ); %fo.writeLine( "time" TAB mcTickSO().time % 24000 ); %fo.close(); %fo.delete(); %this.saveWorldTick = %this.schedule( 120000, "saveWorldTick" ); return true; } function chunkSO( %x, %y, %dim ) { if ( !strLen( $MC::CurrWorld ) ) { return -1; } if ( !strLen( %dim ) ) { %dim = 0; } %ndst = ( %dim != 0 ? "DIM_" @ %dim @ "_" : "" ); %name = "chunkSO_" @ %ndst @ %x @ "_" @ %y; if ( isObject( %obj = nameToID( %name ) ) ) { return %obj; } %obj = new scriptObject() { class = "chunkSO"; dimension = %dim; position = %x SPC %y SPC 0; initializing = true; index = %x SPC %y; blockCount = 0; }; %obj.setName( %name ); chunkGroup().add( %obj ); if ( !%obj.loadChunk() ) { %obj.generateChunk(); } else { %obj.unloadCheckTick(); } return %obj; } function chunkSO::unloadCheckTick( %this ) { cancel( %this.unloadCheckTick ); if ( vectorDist( %this.position, "0 0 0" ) <= 1 ) { return; } %near = false; %count = clientGroup.getCount(); for ( %i = 0 ; %i < %count ; %i++ ) { %cl = clientGroup.getObject( %i ); if ( !isObject( %pl = %cl.player ) ) { continue; } if ( %pl.dimension !$= %this.dimension ) { continue; } if ( vectorDist( %this.position, roundToChunkIndex( %pl.getPosition() ) SPC 0 ) <= 3 ) { %near = true; break; } } if ( !%near ) { %this.unloadChunk(); return; } %this.unloadCheckTick = %this.schedule( 5000, "unloadCheckTick" ); } function chunkSO::unloadChunk( %this ) { if ( %this.unloading ) { return; } cancel( %this.loadChunkTick ); cancel( %this.generateChunkTick ); %this.unloading = true; %this.unloadChunkTick = %this.schedule( 100, "unloadChunkTick", 0 ); } function chunkSO::unloadChunkTick( %this, %idx ) { cancel( %this.unloadChunkTick ); %quotaUsage = 0; %quotaLimit = 32; for ( %idx ; %idx < %this.blockCount && %quotaUsage < %quotaLimit ; %idx++ ) { if ( !isObject( %obj = %this.blockObject[ %idx ] ) ) { continue; } %obj.delete(); %quotaUsage++; } if ( %idx >= %this.blockCount ) { %this.schedule( 0, "delete" ); return; } %this.unloadChunkTick = %this.schedule( 100, "unloadChunkTick", %idx ); } function chunkSO::getFilePath( %this ) { if ( !strLen( $MC::CurrWorld ) ) { return ""; } %index = strReplace( %this.index, " ", "_" ); if ( %this.dimension != 0 ) { %dim_string = "/DIM_" @ %this.dimension; } return "config/mc/world/" @ $MC::CurrWorld @ %dim_string @ "/chunk_" @ %index @ ".chk"; } function chunkSO::getPosition( %this ) { return vectorAdd( vectorScale( %this.position, 16 ), "0 0" SPC 1024 * %this.dimension ); } function chunkSO::setBlock( %this, %x, %y, %z, %type ) { %x = mFloor( %x ); %y = mFloor( %y ); %z = mfloor( %z ); if ( %x < 0 ) { return false; } if ( %y < 0 ) { return false; } if ( %z < 0 ) { return false; } if ( %x > 15 ) { return false; } if ( %y > 15 ) { return false; } if ( %z > 255 ) { return false; } %curr = %this.blockByPos[ %x SPC %y SPC %z ]; if ( strLen( %curr ) && %curr >= 0 ) { if ( isObject( %obj = %this.blockObject[ %curr ] ) ) { %obj.delete(); } %idx = %curr; } else { %idx = %this.blockCount; %this.blockCount++; } %this.blockType[ %idx ] = ""; %this.blockPos[ %idx ] = ""; %this.blockByPos[ %x SPC %y SPC %z ] = ""; %this.blockObject[ %idx ] = ""; if ( !isObject( %db = "mc_blockData_" @ %type ) ) { %this.reflowBlockArray( %idx ); return true; } %this.generatedPoint[ %x, %y, %z ] = true; %this.blockType[ %idx ] = %type; %this.blockPos[ %idx ] = %x SPC %y SPC %z; %this.blockByPos[ %x SPC %y SPC %z ] = %idx; %rpos = vectorAdd( %this.getPosition(), %x SPC %y SPC %z ); %rpos = vectorAdd( %rpos, "0 0" SPC $MC::GlobalBlockOffsetZ ); if ( strLen( %db.mcBlockOffsetZ ) ) { %rpos = vectorAdd( %rpos, "0 0" SPC %db.mcBlockOffsetZ ); } %obj = new fxDTSBrick() { position = %rpos; dataBlock = %db; colorId = 0; // printId = $printNameTable[ "2x2f/" @ ( strLen( %db.printUI ) ? %db.printUI : "MCNone" ) ]; // colorFxId = %db.colorFxId; // shapeFxId = %db.shapeFxId; isPlanted = true; chunkSO = %this; indexInChunk = %idx; }; %obj.setTrusted( true ); getMCBrickGroup().add( %obj ); %obj.plant(); %this.blockObject[ %idx ] = %obj; if ( isFunction( %func = "block_" @ %type @ "_onPlant" ) ) { call( %func, %obj, %this ); } if ( !%this.initializing ) { %this.saveChunk(); } return true; } function chunkSO::getBlock( %this, %x, %y, %z ) { return %this.blockType[ %this.blockByPos[ %x SPC %y SPC %z ] ]; } function chunkSO::reflowBlockArray( %this, %index ) { if ( !strLen( %index ) || %index < 0 || %index >= %this.blockCount ) { return false; } for ( %i = %index ; %i < %this.blockCount ; %i++ ) { %this.blockType[ %i ] = %this.blockType[ %i + 1 ]; %this.blockPos[ %i ] = %this.blockPos[ %i + 1 ]; %px = getWord( %this.blockPos[ %i ], 0 ); %py = getWord( %this.blockPos[ %i ], 1 ); %pz = getWord( %this.blockPos[ %i ], 2 ); %this.blockByPos[ %px SPC %py SPC %pz ] = %i; %this.blockObject[ %i ] = %this.blockObject[ %i + 1 ]; if ( isObject( %obj = %this.blockObject[ %i ] ) ) { %obj.indexInChunk = %i; } } %this.blockCount--; %this.blockType[ %this.blockCount ] = ""; %this.blockObject[ %this.blockCount ] = ""; %this.blockPos[ %this.blockCount ] = ""; return true; } --- End code --- --- Code: (chunk_saving.cs) ---$chunkd::XYBase = "0123456789abcdef"; function chunkSO::loadChunkTick( %this, %str, %idx ) { cancel( %this.loadChunkTick ); %quotaUsage = 0; %quotaLimit = 32; %count = getFieldCount( %str ); for ( %idx ; %idx < %count && %quotaUsage < %quotaLimit ; %idx++ ) { %field = getField( %str, %idx ); %px = strPos( $chunkd::XYBase, getSubStr( %field, 0, 1 ) ); %py = strPos( $chunkd::XYBase, getSubStr( %field, 1, 1 ) ); %pz = mFloor( getSubStr( %field, 2, 3 ) ); %tp = getSubStr( %field, 5, strLen( %field ) ); %this.setBlock( %px, %py, %pz, %tp ); %quotaUsage++; } if ( %idx >= %count ) { %this.initializing = false; return; } %this.loadChunkTick = %this.schedule( 128, "loadChunkTick", %str, %idx ); } function chunkSO::loadChunk( %this ) { if ( %this.blockCount ) { return true; } if ( isEventPending( %this.loadChunkTick ) ) { return true; } if ( isEventPending( %this.generateChunkTick ) ) { return true; } if ( !isFile( %path = %this.getFilePath() ) ) { return false; } %fo = new fileObject(); %fo.openForRead( %path ); %str = %fo.readLine(); while( !%fo.isEOF() ) { %str = %str NL %fo.readLine(); } %fo.close(); %fo.delete(); %str = strReplace( %str, "\xFA", "\t" ); %this.loadChunkTick( %str, 0 ); } function chunkSO::saveChunk( %this ) { if ( %this.unloading ) { return; } if ( getSimTime() - %this.lastSaveTime < 30000 ) { if ( isEventPending( %this.queuedSavePoint ) ) { %this.queuedSavePoint = %this.schedule( ( getSimTime() - %this.lastSaveTime ) + 16, "saveChunk" ); } return false; } else if ( isEventPending( %this.queuedSavePoint ) ) { cancel( %this.queuedSavePoint ); } if ( isEventPending( %this.loadChunkTick ) ) { return false; } if ( isEventPending( %this.generateChunkTick ) ) { return false; } %path = %this.getFilePath(); %this.lastSaveTime = getSimTime(); if ( !isWriteableFileName( %path ) ) { return false; } %fo = new fileObject(); %fo.openForWrite( %path ); for ( %i = 0 ; %i < %this.blockCount ; %i++ ) { %type = %this.blockType[ %i ]; %pos = %this.blockPos[ %i ]; %px = getWord( %pos, 0 ); %py = getWord( %pos, 1 ); %pz = getWord( %pos, 2 ); %px = getSubStr( $chunkd::XYBase, %px, 1 ); %py = getSubStr( $chunkd::XYBase, %py, 1 ); if ( strLen( %pz ) == 2 ) { %pz = "0" @ %pz; } else if ( strLen( %pz ) == 1 ) { %pz = "00" @ %pz; } %string = %string @ ( strLen( %string ) ? "\xFA" : "" ) @ %px @ %py @ %pz @ %type; } %fo.writeLine( %string ); %fo.close(); %fo.delete(); return true; } --- End code --- --- Code: (chunk_properties.cs) ---// Overworld function chunkSO::getTerrainHeight( %this, %x, %y ) { if ( strLen( %height = %this.terrainHeight[ %x, %y ] ) ) { return %height; } %height = 63; if ( %height > 119 ) { %height = 119; } %this.terrainHeight[ %x, %y ] = %height; return %height; } // These functions are currently just dummy functions. function chunkSO::getBiome( %this, %x, %y ) { return "forest"; } function chunkSO::getTemperature( %this, %x, %y ) { return 50; } function chunkSO::getHumidity( %this, %x, %y ) { return 50; } // Nether // Aether // The End --- End code --- --- Code: (chunk_generate.cs) ---function chunkSO::generateChunk( %this ) { if ( %this.blockCount ) { return; } switch$ ( %this.dimension ) { case 2: %this.generateTheEnd(); case 1: %this.generateAether(); case 0: %this.generateOverworld(); case -1: %this.generateNether(); } %this.initializing = false; %this.saveChunk(); %this.unloadCheckTick(); } // Overworld function chunkSO::generateOverworld( %this ) { // Generate base terrain. for ( %x = 0 ; %x < 16 ; %x++ ) { for ( %y = 0 ; %y < 16 ; %y++ ) { %height = %this.getTerrainHeight( %x, %y ); %this.setBlock( %x, %y, %height, "grass" ); } } // Generate trees. %tree_count = getRandom( -5, 3 ); for ( %i = 0 ; %i < %tree_count ; %i++ ) { %x = getRandom( 4, 12 ); %y = getRandom( 4, 12 ); %x = mFloor( %x / 2 ) * 2; %y = mFloor( %y / 2 ) * 2; if ( %water[ %x, %y ] ) { continue; } if ( %madeTree[ %x, %y ] ) { continue; } %madeTree[ %x, %y ] = true; %this.generateTree( %x, %y ); } } function chunkSO::generateTree( %this, %x, %y ) { %terr = %this.getTerrainHeight( %x, %y ); %height = getRandom( 4, 10 ); %width = getRandom( 3, 5 ); if ( %width >= %height ) { %width = %height - 1; } for ( %z = 1 ; %z <= %height ; %z++ ) { %this.setBlock( %x, %y, %terr + %z, "log" ); } %trp = %x SPC %y SPC %terr + %height; for ( %xi = %x - %width ; %xi <= %x + %width ; %xi++ ) { for ( %yi = %y - %width ; %yi <= %y + %width ; %yi++ ) { for ( %zi = %terr + 1 ; %zi <= %terr + %height + %width ; %zi++ ) { if ( %xi == %x && %yi == %y && %zi <= %terr + %height ) { continue; } if ( vectorDist( %xi SPC %yi SPC %zi, %trp ) > %width ) { continue; } %this.setBlock( %xi, %yi, %zi, "leaves" ); } } } } function chunkSO::generateBelowTerrain( %px, %py, %pz, %bl, %th, %obj ) { if ( $MC::Clearing ) { return; } // px: generate 1 block out from this starting point // py: generate 1 block out from this starting point // pz: generate 1 block out from this starting point // bl: the starting point is this amount of blocks below ground level // th: ground level at starting point // obj: an object at starting point //if ( getRandom() <= 0.02 ) // Create a cave system? //{ // chunkSO::generateBelowCaveSystem( %px, %py, %pz ); // Generate the cave system. // return; // Don't do normal underground generation. //} for ( %x = -1 ; %x <= 1 ; %x++ ) { for ( %y = -1 ; %y <= 1 ; %y++ ) { for ( %z = -1 ; %z <= 1 ; %z++ ) { %rx = %px + %x; %ry = %py + %y; %rz = %pz + %z; if ( %x == 0 && %y == 0 && %z == 0 ) { continue; } if ( %rz > %th ) // Does this cause us to arrive on ground? { continue; // If so, don't screw with ground level; go to next iteration. } if ( %rz < 0 ) // Does this cause us to arrive below bedrock? { continue; // If so, don't cause index errors; go to next iteration. } if ( %rz > 255 ) // Does this cause us to arrive above world? { // (note: I'm not sure how this could happen) continue; // If so, don't cause index errors; go to next iteration. } if ( strLen( getBlock( %rx, %ry, %rz ) ) ) // Is there already something here? { continue; // If so, don't overwrite it; go to next iteration. } if ( generatedPoint( %rx, %ry, %rz ) ) // Did we already generate something here .. { // .. which was destroyed by some force? continue; // If so, don't generate it again; go to next iteration. } %dp = %bl - %z; // Determine distance to ground at current point. %block = ""; if ( %dp < 3 ) { %block = "dirt"; //if ( getRandom() <= 0.15 ) //{ // %block = "gravel"; //} } else { if ( %rz <= 7 ) { %block = "smoothStone"; } //else if ( %rz <= 10 ) //{ // %block = "lava"; //} else { %block = "smoothStone"; //if ( getRandom() <= 0.1 ) //{ // %block = "gravel"; //} //else //{ // if ( %rz <= 63 && getRandom() <= 0.05 ) // { // %block = "ironOre"; // } // else if ( %rz <= 31 && getRandom() <= 0.05 ) // { // %block = "goldOre"; // } //} } } setBlock( %rx, %ry, %rz, %block ); } } } } // Nether function chunkSO::generateNether( %this ) { %this.generateOverworld(); } // Aether function chunkSO::generateAether( %this ) { %this.generateOverworld(); } // The End function chunkSO::generateTheEnd( %this ) { %this.generateOverworld(); } --- End code --- |
| Navigation |
| Message Index |
| Previous page |