/* * This file is part of Applied Energistics 2. * Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved. * * Applied Energistics 2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Applied Energistics 2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Applied Energistics 2. If not, see . */ package appeng.services.compass; import java.io.File; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import javax.annotation.Nonnull; import com.google.common.base.Preconditions; import appeng.core.worlddata.MeteorDataNameEncoder; public final class CompassRegion { private final int lowX; private final int lowZ; private final int world; private final File worldCompassFolder; private final MeteorDataNameEncoder encoder; private boolean hasFile = false; private RandomAccessFile raf = null; private ByteBuffer buffer; public CompassRegion( int cx, int cz, int worldID, @Nonnull final File worldCompassFolder ) { Preconditions.checkNotNull( worldCompassFolder ); Preconditions.checkArgument( worldCompassFolder.isDirectory() ); this.world = worldID; this.worldCompassFolder = worldCompassFolder; this.encoder = new MeteorDataNameEncoder( 0 ); final int region_x = cx >> 10; final int region_z = cz >> 10; this.lowX = region_x << 10; this.lowZ = region_z << 10; this.openFile( false ); } public void close() { try { if( this.hasFile ) { this.buffer = null; this.raf.close(); this.raf = null; this.hasFile = false; } } catch( Throwable t ) { throw new CompassException( t ); } } public boolean hasBeacon( int cx, int cz ) { if( this.hasFile ) { cx &= 0x3FF; cz &= 0x3FF; final int val = this.read( cx, cz ); if( val != 0 ) { return true; } } return false; } public void setHasBeacon( int cx, int cz, int cdy, boolean hasBeacon ) { cx &= 0x3FF; cz &= 0x3FF; this.openFile( hasBeacon ); if( this.hasFile ) { int val = this.read( cx, cz ); final int originalVal = val; if( hasBeacon ) { val |= 1 << cdy; } else { val &= ~( 1 << cdy ); } if( originalVal != val ) { this.write( cx, cz, val ); } } } @Override protected void finalize() throws Throwable { try { if( this.raf != null ) { this.raf.close(); } } finally { super.finalize(); } } private void openFile( boolean create ) { if( this.hasFile ) { return; } final File file = this.getFile(); if( create || this.isFileExistent( file ) ) { try { this.raf = new RandomAccessFile( file, "rw" ); final FileChannel fc = this.raf.getChannel(); this.buffer = fc.map( FileChannel.MapMode.READ_WRITE, 0, 0x400 * 0x400 );// fc.size() ); this.hasFile = true; } catch( final Throwable t ) { throw new CompassException( t ); } } } private File getFile() { final String fileName = this.encoder.encode( this.world, this.lowX, this.lowZ ); return new File( this.worldCompassFolder, fileName ); } private boolean isFileExistent( File file ) { return file.exists() && file.isFile(); } private int read( int cx, int cz ) { try { return this.buffer.get( cx + cz * 0x400 ); // raf.seek( cx + cz * 0x400 ); // return raf.readByte(); } catch( IndexOutOfBoundsException outOfBounds ) { return 0; } catch( Throwable t ) { throw new CompassException( t ); } } private void write( int cx, int cz, int val ) { try { this.buffer.put( cx + cz * 0x400, (byte) val ); // raf.seek( cx + cz * 0x400 ); // raf.writeByte( val ); } catch( Throwable t ) { throw new CompassException( t ); } } }