Search in sources :

Example 6 with ClientInterface

use of io.xol.chunkstories.api.client.ClientInterface in project chunkstories-api by Hugobros3.

the class EntityComponentController method pull.

@Override
public void pull(StreamSource from, DataInputStream dis) throws IOException {
    long controllerUUID = 0;
    boolean isControllerNotNull = dis.readBoolean();
    if (isControllerNotNull)
        controllerUUID = dis.readLong();
    // This is strictly illegal, only remotely connected client worlds will accept such requests
    if (!(entity.getWorld() instanceof WorldClientNetworkedRemote)) {
        // Terminate connections immediately
        if (from instanceof Player)
            ((Player) from).disconnect("Illegal controller set attempt, terminating client connection for " + from);
        return;
    }
    LocalPlayer player = ((ClientInterface) entity.getWorld().getGameContext()).getPlayer();
    assert player != null;
    if (isControllerNotNull) {
        // long controllerUUID = dis.readLong();
        long clientUUID = player.getUUID();
        System.out.println("Entity " + entity + " is now in control of " + controllerUUID + " me=" + clientUUID);
        // This update tells us we are now in control of this entity
        if (clientUUID == controllerUUID) {
            EntityControllable controlledEntity = (EntityControllable) entity;
            // TODO sort out local hosted worlds properly ?
            // Client.getInstance().getServerConnection().subscribe(entity);
            controller = player;
            player.setControlledEntity(controlledEntity);
            System.out.println("The client is now in control of entity " + controlledEntity);
        } else {
            // If we receive a different UUID than ours in a EntityComponent change, it means that we don't control it anymore and someone else does.
            if (player.getControlledEntity() != null && player.getControlledEntity().equals(entity)) {
                player.setControlledEntity(null);
                // Client.getInstance().getServerConnection().unsubscribe(entity);
                controller = null;
                System.out.println("Lost control of entity " + entity + " to " + controllerUUID);
            }
        }
    } else {
        // If we receive a different UUID than ours in a EntityComponent change, it means that we don't control it anymore and someone else does.
        if (player.getControlledEntity() != null && player.getControlledEntity().equals(entity)) {
            player.setControlledEntity(null);
            // Client.getInstance().getServerConnection().unsubscribe(entity);
            controller = null;
            System.out.println("Lost control of entity " + entity);
        }
    }
}
Also used : Player(io.xol.chunkstories.api.player.Player) LocalPlayer(io.xol.chunkstories.api.client.LocalPlayer) LocalPlayer(io.xol.chunkstories.api.client.LocalPlayer) ClientInterface(io.xol.chunkstories.api.client.ClientInterface) EntityControllable(io.xol.chunkstories.api.entity.interfaces.EntityControllable) WorldClientNetworkedRemote(io.xol.chunkstories.api.world.WorldClientNetworkedRemote)

Example 7 with ClientInterface

use of io.xol.chunkstories.api.client.ClientInterface in project chunkstories by Hugobros3.

the class VoxelTexturesStoreAndAtlaser method buildTextureAtlas.

public void buildTextureAtlas() {
    try {
        // Clear previous values
        texMap.clear();
        // colors.clear();
        // Compute all sizes first.
        int totalSurfacedNeeded = 0;
        // File folder = new File("./res/voxels/textures/");
        // Get all sizes :
        List<VoxelTextureAtlased> voxelTexturesSortedBySize = new ArrayList<VoxelTextureAtlased>();
        // First we want to iterate over every file to get an idea of how many textures (and of how many sizes) we are dealing
        Iterator<AssetHierarchy> allFiles = content.modsManager().getAllUniqueEntries();
        AssetHierarchy entry;
        Asset f;
        while (allFiles.hasNext()) {
            entry = allFiles.next();
            if (entry.getName().startsWith("./voxels/textures/")) {
                String name = entry.getName().replace("./voxels/textures/", "");
                if (name.contains("/"))
                    continue;
                f = entry.topInstance();
                if (f.getName().endsWith(".png")) {
                    String textureName = name.replace(".png", "");
                    // System.out.println("texName:"+textureName+" "+entry.getKey());
                    if (!texMap.containsKey(textureName)) {
                        VoxelTextureAtlased voxelTexture = new VoxelTextureAtlased(textureName, uniquesIds);
                        uniquesIds++;
                        voxelTexture.imageFileDimensions = getImageSize(f);
                        voxelTexturesSortedBySize.add(voxelTexture);
                        totalSurfacedNeeded += voxelTexture.imageFileDimensions * voxelTexture.imageFileDimensions;
                    }
                }
            }
        }
        // Sort them by size
        Collections.sort(voxelTexturesSortedBySize, new Comparator<VoxelTextureAtlased>() {

            @Override
            public int compare(VoxelTextureAtlased a, VoxelTextureAtlased b) {
                return Integer.compare(b.imageFileDimensions, a.imageFileDimensions);
            }
        });
        for (VoxelTextureAtlased voxelTexture : voxelTexturesSortedBySize) {
            // System.out.println(vt.imageFileDimensions);
            texMap.put(voxelTexture.getName(), voxelTexture);
        }
        // Estimates the required texture atlas size by surface
        int sizeRequired = 16;
        for (int i = 4; i < 14; i++) {
            int iSize = (int) Math.pow(2, i);
            if (iSize * iSize >= totalSurfacedNeeded) {
                sizeRequired = iSize;
                break;
            }
        }
        // ChunkStoriesLogger.getInstance().info("At least " + sizeRequired + " by " + sizeRequired + " for TextureAtlas (surfacedNeeded : " + totalSurfacedNeeded + ")");
        // Delete previous atlases
        File diffuseTextureFile = new File(GameDirectory.getGameFolderPath() + "/cache/tiles_merged_albedo.png");
        if (diffuseTextureFile.exists())
            diffuseTextureFile.delete();
        File normalTextureFile = new File(GameDirectory.getGameFolderPath() + "/cache/tiles_merged_normal.png");
        if (normalTextureFile.exists())
            normalTextureFile.delete();
        File materialTextureFile = new File(GameDirectory.getGameFolderPath() + "/cache/tiles_merged_material.png");
        if (materialTextureFile.exists())
            materialTextureFile.delete();
        // Build the new one
        boolean loadedOK = false;
        while (// Security to prevend
        !loadedOK && sizeRequired <= 8192) // HUGE-ASS textures
        {
            // We need this
            BLOCK_ATLAS_SIZE = sizeRequired;
            BLOCK_ATLAS_FACTOR = 32768 / BLOCK_ATLAS_SIZE;
            loadedOK = true;
            // Create boolean bitfield
            boolean[][] used = new boolean[sizeRequired / 16][sizeRequired / 16];
            diffuseTextureImage = null;
            normalTextureImage = null;
            materialTextureImage = null;
            if (content.getContext() instanceof ClientInterface) {
                diffuseTextureImage = new BufferedImage(sizeRequired, sizeRequired, Transparency.TRANSLUCENT);
                normalTextureImage = new BufferedImage(sizeRequired, sizeRequired, Transparency.TRANSLUCENT);
                materialTextureImage = new BufferedImage(sizeRequired, sizeRequired, Transparency.TRANSLUCENT);
                logger.debug("This is a client so we'll make the texture atlas");
            }
            BufferedImage imageBuffer;
            for (VoxelTextureAtlased vt : voxelTexturesSortedBySize) {
                // Find a free spot on the atlas
                boolean foundSpot = false;
                int spotX = 0, spotY = 0;
                for (int a = 0; (a < sizeRequired / 16 && !foundSpot); a++) for (int b = 0; (b < sizeRequired / 16 && !foundSpot); b++) {
                    if (// Unused
                    used[a][b] == false && a + vt.imageFileDimensions / 16 <= sizeRequired / 16 && b + vt.imageFileDimensions / 16 <= sizeRequired / 16) {
                        boolean usedAlready = false;
                        // Not pretty loops that do clamped space checks
                        for (int i = 0; (i < vt.imageFileDimensions / 16 && a + i < sizeRequired / 16); i++) for (int j = 0; (j < vt.imageFileDimensions / 16 && b + j < sizeRequired / 16); j++) if (// Well
                        used[a + i][b + j] == true)
                            // fuck
                            // it
                            usedAlready = true;
                        if (!usedAlready) {
                            spotX = a * 16;
                            spotY = b * 16;
                            vt.setAtlasS(spotX * BLOCK_ATLAS_FACTOR);
                            vt.setAtlasT(spotY * BLOCK_ATLAS_FACTOR);
                            vt.setAtlasOffset(vt.imageFileDimensions * BLOCK_ATLAS_FACTOR);
                            foundSpot = true;
                            for (int i = 0; (i < vt.imageFileDimensions / 16 && a + i < sizeRequired / 16); i++) for (int j = 0; (j < vt.imageFileDimensions / 16 && b + j < sizeRequired / 16); j++) used[a + i][b + j] = true;
                        }
                    }
                }
                if (!foundSpot) {
                    System.out.println("Failed to find a space to place the texture in. Retrying with a larger atlas.");
                    loadedOK = false;
                    break;
                }
                imageBuffer = ImageIO.read(content.modsManager().getAsset("./voxels/textures/" + vt.getName() + ".png").read());
                // imageBuffer = ImageIO.read(GameContent.getTextureFileLocation());
                float alphaTotal = 0;
                int nonNullPixels = 0;
                Vector3f color = new Vector3f();
                for (int x = 0; x < vt.imageFileDimensions; x++) {
                    for (int y = 0; y < vt.imageFileDimensions; y++) {
                        int rgb = imageBuffer.getRGB(x, y);
                        if (diffuseTextureImage != null)
                            diffuseTextureImage.setRGB(spotX + x, spotY + y, rgb);
                        float alpha = ((rgb & 0xFF000000) >>> 24) / 255f;
                        // System.out.println("a:"+alpha);
                        alphaTotal += alpha;
                        if (alpha > 0)
                            nonNullPixels++;
                        float red = ((rgb & 0xFF0000) >> 16) / 255f * alpha;
                        float green = ((rgb & 0x00FF00) >> 8) / 255f * alpha;
                        float blue = (rgb & 0x0000FF) / 255f * alpha;
                        color.add(new Vector3f(red, green, blue));
                    // Vector3f.add(color, new Vector3f(red, green, blue), color);
                    }
                }
                color.mul(1f / alphaTotal);
                if (nonNullPixels > 0)
                    alphaTotal /= nonNullPixels;
                vt.setColor(new Vector4f(color.x(), color.y(), color.z(), alphaTotal));
                // Don't bother if it's not a Client context
                if (diffuseTextureImage == null)
                    continue;
                // Do also the normal maps !
                Asset normalMap = content.modsManager().getAsset("./voxels/textures/normal/" + vt.getName() + ".png");
                if (normalMap == null)
                    normalMap = content.modsManager().getAsset("./voxels/textures/normal/notex.png");
                imageBuffer = ImageIO.read(normalMap.read());
                for (int x = 0; x < vt.imageFileDimensions; x++) {
                    for (int y = 0; y < vt.imageFileDimensions; y++) {
                        int rgb = imageBuffer.getRGB(x % imageBuffer.getWidth(), y % imageBuffer.getHeight());
                        normalTextureImage.setRGB(spotX + x, spotY + y, rgb);
                    }
                }
                // And the materials !
                Asset materialMap = content.modsManager().getAsset("./voxels/textures/material/" + vt.getName() + ".png");
                if (materialMap == null)
                    materialMap = content.modsManager().getAsset("./voxels/textures/material/notex.png");
                imageBuffer = ImageIO.read(materialMap.read());
                for (int x = 0; x < vt.imageFileDimensions; x++) {
                    for (int y = 0; y < vt.imageFileDimensions; y++) {
                        int rgb = imageBuffer.getRGB(x % imageBuffer.getWidth(), y % imageBuffer.getHeight());
                        materialTextureImage.setRGB(spotX + x, spotY + y, rgb);
                    }
                }
            }
            if (loadedOK && diffuseTextureImage != null) {
                // save it son
                ImageIO.write(diffuseTextureImage, "PNG", diffuseTextureFile);
                ImageIO.write(normalTextureImage, "PNG", normalTextureFile);
                ImageIO.write(materialTextureImage, "PNG", materialTextureFile);
                diffuseTexture = null;
                normalTexture = null;
                materialTexture = null;
            } else
                // It's too small, initial estimation was wrong !
                sizeRequired *= 2;
        }
        // Read textures metadata
        // TODO read all overrides in priority
        readTexturesMeta(content.modsManager().getAsset("./voxels/textures/meta.txt"));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Also used : ArrayList(java.util.ArrayList) ClientInterface(io.xol.chunkstories.api.client.ClientInterface) BufferedImage(java.awt.image.BufferedImage) IOException(java.io.IOException) Vector4f(org.joml.Vector4f) Vector3f(org.joml.Vector3f) Asset(io.xol.chunkstories.api.content.Asset) AssetHierarchy(io.xol.chunkstories.api.content.mods.AssetHierarchy) File(java.io.File)

Example 8 with ClientInterface

use of io.xol.chunkstories.api.client.ClientInterface in project chunkstories-core by Hugobros3.

the class CoreContentPlugin method onEnable.

@Override
public void onEnable() {
    itemsLogic = new ItemsLogicListener(this);
    pluginExecutionContext.getPluginManager().registerEventListener(itemsLogic, this);
    if (this.getPluginExecutionContext() instanceof ClientInterface) {
        renderingLogic = new RenderingEventsListener(this, (ClientInterface) getPluginExecutionContext());
        pluginExecutionContext.getPluginManager().registerEventListener(renderingLogic, this);
    }
}
Also used : RenderingEventsListener(io.xol.chunkstories.core.rendering.RenderingEventsListener) ItemsLogicListener(io.xol.chunkstories.core.logic.ItemsLogicListener) ClientInterface(io.xol.chunkstories.api.client.ClientInterface)

Aggregations

ClientInterface (io.xol.chunkstories.api.client.ClientInterface)8 EntityControllable (io.xol.chunkstories.api.entity.interfaces.EntityControllable)2 Player (io.xol.chunkstories.api.player.Player)2 File (java.io.File)2 Location (io.xol.chunkstories.api.Location)1 LocalPlayer (io.xol.chunkstories.api.client.LocalPlayer)1 Asset (io.xol.chunkstories.api.content.Asset)1 AssetHierarchy (io.xol.chunkstories.api.content.mods.AssetHierarchy)1 Controller (io.xol.chunkstories.api.entity.Controller)1 Entity (io.xol.chunkstories.api.entity.Entity)1 EntityWithInventory (io.xol.chunkstories.api.entity.interfaces.EntityWithInventory)1 EntityWorldModifier (io.xol.chunkstories.api.entity.interfaces.EntityWorldModifier)1 PlayerVoxelModificationEvent (io.xol.chunkstories.api.events.player.voxel.PlayerVoxelModificationEvent)1 WorldException (io.xol.chunkstories.api.exceptions.world.WorldException)1 InputsManager (io.xol.chunkstories.api.input.InputsManager)1 ItemPile (io.xol.chunkstories.api.item.inventory.ItemPile)1 World (io.xol.chunkstories.api.world.World)1 WorldCell (io.xol.chunkstories.api.world.World.WorldCell)1 WorldClientNetworkedRemote (io.xol.chunkstories.api.world.WorldClientNetworkedRemote)1 WorldMaster (io.xol.chunkstories.api.world.WorldMaster)1