Added block placement
This commit is contained in:
BIN
core/assets/roof.png
Normal file
BIN
core/assets/roof.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.1 KiB |
BIN
core/assets/wall.png
Normal file
BIN
core/assets/wall.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -3,6 +3,8 @@ package com.mygdx.game.Character;
|
|||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.Input;
|
import com.badlogic.gdx.Input;
|
||||||
import com.badlogic.gdx.graphics.g2d.Animation;
|
import com.badlogic.gdx.graphics.g2d.Animation;
|
||||||
|
import com.badlogic.gdx.math.Vector3;
|
||||||
|
import com.mygdx.game.Dimension.Chunks;
|
||||||
import com.mygdx.game.Restrictions;
|
import com.mygdx.game.Restrictions;
|
||||||
|
|
||||||
import static com.mygdx.game.Main.cam;
|
import static com.mygdx.game.Main.cam;
|
||||||
@@ -21,61 +23,62 @@ public class InputController implements Restrictions {
|
|||||||
if (Gdx.input.isKeyPressed(Input.Keys.Q)) {
|
if (Gdx.input.isKeyPressed(Input.Keys.Q)) {
|
||||||
cam.zoom -= 5;
|
cam.zoom -= 5;
|
||||||
}
|
}
|
||||||
|
if (Gdx.input.isTouched()) {
|
||||||
|
Vector3 mousePos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
|
||||||
|
cam.unproject(mousePos);
|
||||||
|
int x = Mouse.getSelectedX(mousePos) >> TILE_SHIFT;
|
||||||
|
int y = Mouse.getSelectedY(mousePos) >> TILE_SHIFT;
|
||||||
|
|
||||||
|
Chunks.placeBlock(x,y,"wood");
|
||||||
|
}
|
||||||
|
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.UP) && Gdx.input.isKeyPressed(Input.Keys.LEFT) && i > KEY_DELAY) {
|
if (Gdx.input.isKeyPressed(Input.Keys.UP) && Gdx.input.isKeyPressed(Input.Keys.LEFT) && i > KEY_DELAY) {
|
||||||
i = 0;
|
i = 0;
|
||||||
directionAnimation("UpLeft");
|
directionAnimation("UpLeft");
|
||||||
Player.addX(-MOVEMENT_SPEED);
|
Player.addX(-MOVEMENT_SPEED);
|
||||||
Player.addY(MOVEMENT_SPEED);
|
Player.addY(MOVEMENT_SPEED);
|
||||||
cam.translate(-MOVEMENT_SPEED,MOVEMENT_SPEED);
|
cam.translate(-MOVEMENT_SPEED, MOVEMENT_SPEED);
|
||||||
}
|
} else if (Gdx.input.isKeyPressed(Input.Keys.UP) && Gdx.input.isKeyPressed(Input.Keys.RIGHT) && i > KEY_DELAY) {
|
||||||
else if (Gdx.input.isKeyPressed(Input.Keys.UP)&& Gdx.input.isKeyPressed(Input.Keys.RIGHT) &&i > KEY_DELAY) {
|
|
||||||
i = 0;
|
i = 0;
|
||||||
directionAnimation("UpRight");
|
directionAnimation("UpRight");
|
||||||
Player.addX(MOVEMENT_SPEED);
|
Player.addX(MOVEMENT_SPEED);
|
||||||
Player.addY(MOVEMENT_SPEED);
|
Player.addY(MOVEMENT_SPEED);
|
||||||
cam.translate(MOVEMENT_SPEED,MOVEMENT_SPEED);
|
cam.translate(MOVEMENT_SPEED, MOVEMENT_SPEED);
|
||||||
}
|
} else if (Gdx.input.isKeyPressed(Input.Keys.DOWN) && Gdx.input.isKeyPressed(Input.Keys.LEFT) && i > KEY_DELAY) {
|
||||||
else if (Gdx.input.isKeyPressed(Input.Keys.DOWN)&& Gdx.input.isKeyPressed(Input.Keys.LEFT) && i > KEY_DELAY) {
|
|
||||||
i = 0;
|
i = 0;
|
||||||
directionAnimation("DownLeft");
|
directionAnimation("DownLeft");
|
||||||
Player.addX(-MOVEMENT_SPEED);
|
Player.addX(-MOVEMENT_SPEED);
|
||||||
Player.addY(-MOVEMENT_SPEED);
|
Player.addY(-MOVEMENT_SPEED);
|
||||||
cam.translate(-MOVEMENT_SPEED,-MOVEMENT_SPEED);
|
cam.translate(-MOVEMENT_SPEED, -MOVEMENT_SPEED);
|
||||||
}
|
} else if (Gdx.input.isKeyPressed(Input.Keys.DOWN) && Gdx.input.isKeyPressed(Input.Keys.RIGHT) && i > KEY_DELAY) {
|
||||||
else if (Gdx.input.isKeyPressed(Input.Keys.DOWN)&& Gdx.input.isKeyPressed(Input.Keys.RIGHT) && i > KEY_DELAY) {
|
|
||||||
i = 0;
|
i = 0;
|
||||||
directionAnimation("DownRight");
|
directionAnimation("DownRight");
|
||||||
Player.addX(MOVEMENT_SPEED);
|
Player.addX(MOVEMENT_SPEED);
|
||||||
Player.addY(-MOVEMENT_SPEED);
|
Player.addY(-MOVEMENT_SPEED);
|
||||||
|
|
||||||
cam.translate(MOVEMENT_SPEED,-MOVEMENT_SPEED);
|
cam.translate(MOVEMENT_SPEED, -MOVEMENT_SPEED);
|
||||||
}
|
} else if (Gdx.input.isKeyPressed(Input.Keys.LEFT) && i > KEY_DELAY) {
|
||||||
|
|
||||||
else if (Gdx.input.isKeyPressed(Input.Keys.LEFT) && i > KEY_DELAY) {
|
|
||||||
i = 0;
|
i = 0;
|
||||||
directionAnimation("Left");
|
directionAnimation("Left");
|
||||||
Player.addX(-MOVEMENT_SPEED);
|
Player.addX(-MOVEMENT_SPEED);
|
||||||
cam.translate(-MOVEMENT_SPEED,0);
|
cam.translate(-MOVEMENT_SPEED, 0);
|
||||||
}
|
} else if (Gdx.input.isKeyPressed(Input.Keys.RIGHT) && i > KEY_DELAY) {
|
||||||
else if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)&& i > KEY_DELAY) {
|
|
||||||
i = 0;
|
i = 0;
|
||||||
directionAnimation("Right");
|
directionAnimation("Right");
|
||||||
Player.addX(MOVEMENT_SPEED);
|
Player.addX(MOVEMENT_SPEED);
|
||||||
cam.translate(MOVEMENT_SPEED,0);
|
cam.translate(MOVEMENT_SPEED, 0);
|
||||||
}
|
} else if (Gdx.input.isKeyPressed(Input.Keys.DOWN) && i > KEY_DELAY) {
|
||||||
else if (Gdx.input.isKeyPressed(Input.Keys.DOWN)&& i > KEY_DELAY) {
|
|
||||||
i = 0;
|
i = 0;
|
||||||
directionAnimation("Down");
|
directionAnimation("Down");
|
||||||
Player.addY(-MOVEMENT_SPEED);
|
Player.addY(-MOVEMENT_SPEED);
|
||||||
cam.translate(0,-MOVEMENT_SPEED);
|
cam.translate(0, -MOVEMENT_SPEED);
|
||||||
}
|
}
|
||||||
if (Gdx.input.isKeyPressed(Input.Keys.UP)&& i > KEY_DELAY) {
|
if (Gdx.input.isKeyPressed(Input.Keys.UP) && i > KEY_DELAY) {
|
||||||
i = 0;
|
i = 0;
|
||||||
directionAnimation("Up");
|
directionAnimation("Up");
|
||||||
Player.addY(MOVEMENT_SPEED);
|
Player.addY(MOVEMENT_SPEED);
|
||||||
|
|
||||||
cam.translate(0,MOVEMENT_SPEED);
|
cam.translate(0, MOVEMENT_SPEED);
|
||||||
}
|
}
|
||||||
|
|
||||||
cam.update();
|
cam.update();
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import static com.mygdx.game.Main.cam;
|
|||||||
public class Mouse implements Restrictions {
|
public class Mouse implements Restrictions {
|
||||||
Texture crosshair = new Texture("core/assets/crosshair.png");
|
Texture crosshair = new Texture("core/assets/crosshair.png");
|
||||||
|
|
||||||
|
|
||||||
public void selectedTile(SpriteBatch batch){
|
public void selectedTile(SpriteBatch batch){
|
||||||
Vector3 mousePos = new Vector3( Gdx.input.getX(), Gdx.input.getY(),0);
|
Vector3 mousePos = new Vector3( Gdx.input.getX(), Gdx.input.getY(),0);
|
||||||
cam.unproject(mousePos);
|
cam.unproject(mousePos);
|
||||||
@@ -21,11 +20,11 @@ public class Mouse implements Restrictions {
|
|||||||
batch.draw(crosshair, x, y);
|
batch.draw(crosshair, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSelectedX(Vector3 mousePos) {
|
public static int getSelectedX(Vector3 mousePos) {
|
||||||
return ((int)(mousePos.x)>>4)<<4;
|
return ((int)(mousePos.x)>>4)<<4;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSelectedY(Vector3 mousePos) {
|
public static int getSelectedY(Vector3 mousePos) {
|
||||||
return ((int)(mousePos.y)>>4)<<4;
|
return ((int)(mousePos.y)>>4)<<4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +40,6 @@ public class Mouse implements Restrictions {
|
|||||||
return (getSelectedY(mousePos) + Player.getY()>>1)/TILE_SIZE;
|
return (getSelectedY(mousePos) + Player.getY()>>1)/TILE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void render(SpriteBatch batch) {
|
public void render(SpriteBatch batch) {
|
||||||
selectedTile(batch);
|
selectedTile(batch);
|
||||||
//System.out.println("X = " + getTileX(cam) + " Y = "+ getTileY(cam));
|
//System.out.println("X = " + getTileX(cam) + " Y = "+ getTileY(cam));
|
||||||
|
|||||||
@@ -1,19 +1,31 @@
|
|||||||
package com.mygdx.game.Dimension;
|
package com.mygdx.game.Dimension;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
|
||||||
public class Block {
|
public class Block {
|
||||||
private String name;
|
private String name;
|
||||||
|
private Texture texture;
|
||||||
private Boolean harvestable;
|
private Boolean harvestable;
|
||||||
private Boolean breakable;
|
private Boolean breakable;
|
||||||
private Boolean passable;
|
private Boolean passable;
|
||||||
|
|
||||||
public Block(String name) {
|
public Block(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.harvestable = harvestable;
|
this.texture = new Texture("core/assets/" + name + ".png");
|
||||||
this.breakable = breakable;
|
this.harvestable = true;
|
||||||
this.passable = passable;
|
this.breakable = true;
|
||||||
|
this.passable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Texture getTexture() {
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTexture(Texture texture) {
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,13 @@
|
|||||||
package com.mygdx.game.Dimension;
|
package com.mygdx.game.Dimension;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class BlockMaterials {
|
public class BlockMaterials {
|
||||||
public static HashMap<String,Block> materials = new HashMap<>();
|
public static HashMap<String,Block> materials = new HashMap<>();
|
||||||
public static HashMap<String,Texture> textures = new HashMap<>();
|
|
||||||
|
|
||||||
//Private so the singleton can't be instantiated
|
//Private so the singleton can't be instantiated
|
||||||
private BlockMaterials() {}
|
private BlockMaterials() {}
|
||||||
|
|
||||||
public static Texture getTexture(String material) {
|
|
||||||
return textures.get(material);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void create(){
|
public static void create(){
|
||||||
materials.put("grass",new Block("grass"));
|
materials.put("grass",new Block("grass"));
|
||||||
materials.put("wood",new Block("wood"));
|
materials.put("wood",new Block("wood"));
|
||||||
@@ -23,13 +16,7 @@ public class BlockMaterials {
|
|||||||
materials.put("snow",new Block("snow"));
|
materials.put("snow",new Block("snow"));
|
||||||
materials.put("sand",new Block("sand"));
|
materials.put("sand",new Block("sand"));
|
||||||
materials.put("air",new Block("air"));
|
materials.put("air",new Block("air"));
|
||||||
|
materials.put("roof",new Block("roof"));
|
||||||
textures.put("grass", new Texture("core/assets/grass.png"));
|
materials.put("wall",new Block("wall"));
|
||||||
textures.put("wood", new Texture("core/assets/wood.png"));
|
|
||||||
textures.put("water", new Texture("core/assets/water.png"));
|
|
||||||
textures.put("stone", new Texture("core/assets/stone.png"));
|
|
||||||
textures.put("snow", new Texture("core/assets/snow.png"));
|
|
||||||
textures.put("sand", new Texture("core/assets/sand.png"));
|
|
||||||
textures.put("air", new Texture("core/assets/air.png"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
//https://www.redblobgames.com/maps/terrain-from-noise/
|
//https://www.redblobgames.com/maps/terrain-from-noise/
|
||||||
package com.mygdx.game.Dimension;
|
package com.mygdx.game.Dimension;
|
||||||
|
|
||||||
|
import com.github.czyzby.kiwi.util.tuple.immutable.Pair;
|
||||||
import com.github.czyzby.kiwi.util.tuple.immutable.Triple;
|
import com.github.czyzby.kiwi.util.tuple.immutable.Triple;
|
||||||
import com.mygdx.game.OpenSimplexNoise;
|
import com.mygdx.game.OpenSimplexNoise;
|
||||||
|
|
||||||
@@ -8,9 +9,28 @@ import java.util.HashMap;
|
|||||||
|
|
||||||
import static com.mygdx.game.Restrictions.*;
|
import static com.mygdx.game.Restrictions.*;
|
||||||
|
|
||||||
public class Chunks {
|
public class Chunks{
|
||||||
|
|
||||||
|
public static void create(){
|
||||||
|
int i = 10;
|
||||||
|
setBlock(3+i,2,"wall");
|
||||||
|
setBlock(4+i,2,"wall");
|
||||||
|
setBlock(3+i,3,"roof");
|
||||||
|
setBlock(4+i,3,"roof");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setBlock(int x, int y, String name){
|
||||||
|
buildings.put(new Pair<>(x,y),new Block(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void placeBlock(int x, int y, String name){
|
||||||
|
Triple<Integer,Integer,Integer> triple = new Triple<>(x, y,1);
|
||||||
|
Chunks.blocks.replace(triple, Chunks.blocks.get(triple), new Block(name));
|
||||||
|
}
|
||||||
|
|
||||||
public static HashMap<Triple<Integer, Integer,Integer>, Block> blocks = new HashMap<>();
|
public static HashMap<Triple<Integer, Integer,Integer>, Block> blocks = new HashMap<>();
|
||||||
private long seed = SEED;
|
|
||||||
|
public static HashMap<Pair<Integer,Integer>, Block> buildings = new HashMap<>();
|
||||||
|
|
||||||
public void ungenerateChunk(int x, int y) {
|
public void ungenerateChunk(int x, int y) {
|
||||||
int startX = x << CHUNK_SHIFT;
|
int startX = x << CHUNK_SHIFT;
|
||||||
@@ -56,21 +76,17 @@ public class Chunks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Block getBuildings(int x, int y) {
|
public Block getBuildings(int x, int y) {
|
||||||
if(x == 2 && y == 2) return new Block("wood");
|
return buildings.getOrDefault(new Pair<>(x,y),new Block("air"));
|
||||||
if(x == 2 && y == 1) return new Block("wood");
|
|
||||||
if(x == 1 && y == 2) return new Block("wood");
|
|
||||||
if(x == 1 && y == 1) return new Block("wood");
|
|
||||||
return new Block("air");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double noise1(double nx, double ny) {
|
public double noise1(double nx, double ny) {
|
||||||
OpenSimplexNoise gen1 = new OpenSimplexNoise(seed+1);
|
OpenSimplexNoise gen1 = new OpenSimplexNoise(SEED+1);
|
||||||
|
|
||||||
return gen1.eval(nx, ny)/2 + 0.5;
|
return gen1.eval(nx, ny)/2 + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double noise2(double nx, double ny) {
|
public double noise2(double nx, double ny) {
|
||||||
OpenSimplexNoise gen2 = new OpenSimplexNoise(seed);
|
OpenSimplexNoise gen2 = new OpenSimplexNoise(SEED);
|
||||||
|
|
||||||
return gen2.eval(nx, ny)/2 + 0.5;
|
return gen2.eval(nx, ny)/2 + 0.5;
|
||||||
}
|
}
|
||||||
@@ -153,7 +169,8 @@ public class Chunks {
|
|||||||
return "TropicalRainForest";
|
return "TropicalRainForest";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isEmpty(int x, int y){
|
public static Boolean isEmpty(int x, int y){
|
||||||
return blocks.get(new Triple<>(x * 8, y * 8,0)) == null;
|
return blocks.get(new Triple<>(x * 8, y * 8,0)) == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,4 +56,3 @@ public class World {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ public class WorldRenderer implements Restrictions {
|
|||||||
|
|
||||||
public void drawWorld(Batch batch, int layer) {
|
public void drawWorld(Batch batch, int layer) {
|
||||||
for (Triple<Integer, Integer, Integer> chunkpair : Chunks.blocks.keySet()) {
|
for (Triple<Integer, Integer, Integer> chunkpair : Chunks.blocks.keySet()) {
|
||||||
String name = null;
|
|
||||||
if(chunkpair.getThird() == layer) {
|
if(chunkpair.getThird() == layer) {
|
||||||
name = Chunks.blocks.get(chunkpair).getName();
|
|
||||||
batch.draw(
|
batch.draw(
|
||||||
BlockMaterials.getTexture(name),
|
Chunks.blocks.get(chunkpair).getTexture(),
|
||||||
chunkpair.getFirst() << TILE_SHIFT,
|
chunkpair.getFirst() << TILE_SHIFT,
|
||||||
chunkpair.getSecond() << TILE_SHIFT
|
chunkpair.getSecond() << TILE_SHIFT
|
||||||
);
|
);
|
||||||
@@ -33,9 +31,9 @@ public class WorldRenderer implements Restrictions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void render(SpriteBatch batch) {
|
public void render(SpriteBatch batch) {
|
||||||
|
inputController.handleInput();
|
||||||
drawWorld(batch,0);
|
drawWorld(batch,0);
|
||||||
drawWorld(batch,1);
|
drawWorld(batch,1);
|
||||||
inputController.handleInput();
|
|
||||||
batch.setProjectionMatrix(cam.combined);
|
batch.setProjectionMatrix(cam.combined);
|
||||||
cam.update();
|
cam.update();
|
||||||
mouse.render(batch);
|
mouse.render(batch);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.badlogic.gdx.utils.viewport.FitViewport;
|
|||||||
import com.mygdx.game.Character.Mouse;
|
import com.mygdx.game.Character.Mouse;
|
||||||
import com.mygdx.game.Character.Player;
|
import com.mygdx.game.Character.Player;
|
||||||
import com.mygdx.game.Dimension.BlockMaterials;
|
import com.mygdx.game.Dimension.BlockMaterials;
|
||||||
|
import com.mygdx.game.Dimension.Chunks;
|
||||||
import com.mygdx.game.Dimension.World;
|
import com.mygdx.game.Dimension.World;
|
||||||
import com.mygdx.game.Dimension.WorldRenderer;
|
import com.mygdx.game.Dimension.WorldRenderer;
|
||||||
import com.mygdx.game.UI.GUI;
|
import com.mygdx.game.UI.GUI;
|
||||||
@@ -31,6 +32,7 @@ public class Main extends ApplicationAdapter {
|
|||||||
cam = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
|
cam = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
|
||||||
fitViewport = new FitViewport(VIEWPORT_WIDTH,VIEWPORT_HEIGHT, cam);
|
fitViewport = new FitViewport(VIEWPORT_WIDTH,VIEWPORT_HEIGHT, cam);
|
||||||
BlockMaterials.create();
|
BlockMaterials.create();
|
||||||
|
Chunks.create();
|
||||||
|
|
||||||
//Starting location of the player
|
//Starting location of the player
|
||||||
cam.translate(TILE_SIZE >> 1, TILE_SIZE >> 1);
|
cam.translate(TILE_SIZE >> 1, TILE_SIZE >> 1);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public interface Restrictions {
|
|||||||
float VIEWPORT_HEIGHT = 9/2f;
|
float VIEWPORT_HEIGHT = 9/2f;
|
||||||
float VIEWPORT_WIDTH = 16/2f;
|
float VIEWPORT_WIDTH = 16/2f;
|
||||||
|
|
||||||
int MOVEMENT_SPEED = 1;
|
int MOVEMENT_SPEED = 2;
|
||||||
int KEY_DELAY = 0;
|
int KEY_DELAY = 0;
|
||||||
|
|
||||||
int TILE_SIZE = 16;
|
int TILE_SIZE = 16;
|
||||||
@@ -19,5 +19,5 @@ public interface Restrictions {
|
|||||||
//int SUPER_CHUNK_SHIFT = 0;
|
//int SUPER_CHUNK_SHIFT = 0;
|
||||||
|
|
||||||
int RENDER_DISTANCE = 3;
|
int RENDER_DISTANCE = 3;
|
||||||
float RENDER_TIME = 1f;
|
float RENDER_TIME = 1/60f;
|
||||||
}
|
}
|
||||||
|
|||||||
4
core/src/com/mygdx/game/Storage.java
Normal file
4
core/src/com/mygdx/game/Storage.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package com.mygdx.game;
|
||||||
|
|
||||||
|
public class Storage {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user