SFX changes
This commit is contained in:
@@ -31,12 +31,12 @@ public class LoopControl{
|
||||
|
||||
boolean play = data.curVolume > 0.01f;
|
||||
float pan = Mathf.zero(data.total, 0.0001f) ? 0f : sound.calcPan(data.sum.x / data.total, data.sum.y / data.total);
|
||||
if(data.soundID <= 0){
|
||||
if(data.soundID <= 0 || !sound.isPlaying(data.soundID)){
|
||||
if(play){
|
||||
data.soundID = sound.loop(data.curVolume, 1f, pan);
|
||||
}
|
||||
}else{
|
||||
if(data.curVolume <= 0.01f){
|
||||
if(data.curVolume <= 0.001f){
|
||||
sound.stop();
|
||||
data.soundID = -1;
|
||||
return;
|
||||
|
||||
@@ -1163,6 +1163,9 @@ public class Blocks implements ContentList{
|
||||
requirements(Category.power, with(Items.copper, 25, Items.lead, 15));
|
||||
powerProduction = 1f;
|
||||
itemDuration = 120f;
|
||||
|
||||
ambientSound = Sounds.smelter;
|
||||
ambientSoundVolume = 0.03f;
|
||||
}};
|
||||
|
||||
thermalGenerator = new ThermalGenerator("thermal-generator"){{
|
||||
@@ -1171,6 +1174,8 @@ public class Blocks implements ContentList{
|
||||
generateEffect = Fx.redgeneratespark;
|
||||
size = 2;
|
||||
floating = true;
|
||||
ambientSound = Sounds.hum;
|
||||
ambientSoundVolume = 0.04f;
|
||||
}};
|
||||
|
||||
steamGenerator = new BurnerGenerator("steam-generator"){{
|
||||
@@ -1180,6 +1185,9 @@ public class Blocks implements ContentList{
|
||||
consumes.liquid(Liquids.water, 0.1f);
|
||||
hasLiquids = true;
|
||||
size = 2;
|
||||
|
||||
ambientSound = Sounds.smelter;
|
||||
ambientSoundVolume = 0.05f;
|
||||
}};
|
||||
|
||||
differentialGenerator = new SingleTypeGenerator("differential-generator"){{
|
||||
@@ -1216,6 +1224,8 @@ public class Blocks implements ContentList{
|
||||
|
||||
thoriumReactor = new NuclearReactor("thorium-reactor"){{
|
||||
requirements(Category.power, with(Items.lead, 300, Items.silicon, 200, Items.graphite, 150, Items.thorium, 150, Items.metaglass, 50));
|
||||
ambientSound = Sounds.hum;
|
||||
ambientSoundVolume = 0.16f;
|
||||
size = 3;
|
||||
health = 700;
|
||||
itemDuration = 360f;
|
||||
@@ -1231,6 +1241,9 @@ public class Blocks implements ContentList{
|
||||
health = 900;
|
||||
powerProduction = 130f;
|
||||
itemDuration = 140f;
|
||||
ambientSound = Sounds.pulse;
|
||||
ambientSoundVolume = 0.2f;
|
||||
|
||||
consumes.power(25f);
|
||||
consumes.item(Items.blastCompound);
|
||||
consumes.liquid(Liquids.cryofluid, 0.25f);
|
||||
@@ -1491,7 +1504,6 @@ public class Blocks implements ContentList{
|
||||
shootEffect = Fx.shootLiquid;
|
||||
range = 110f;
|
||||
health = 250 * size * size;
|
||||
shootSound = Sounds.splash;
|
||||
}};
|
||||
|
||||
lancer = new ChargeTurret("lancer"){{
|
||||
@@ -1639,7 +1651,6 @@ public class Blocks implements ContentList{
|
||||
shootEffect = Fx.shootLiquid;
|
||||
range = 190f;
|
||||
health = 250 * size * size;
|
||||
shootSound = Sounds.splash;
|
||||
}};
|
||||
|
||||
fuse = new ItemTurret("fuse"){{
|
||||
@@ -1759,7 +1770,7 @@ public class Blocks implements ContentList{
|
||||
shots = 1;
|
||||
size = 4;
|
||||
shootCone = 2f;
|
||||
shootSound = Sounds.shootBig;
|
||||
shootSound = Sounds.railgun;
|
||||
unitSort = (u, x, y) -> -u.maxHealth;
|
||||
|
||||
coolantMultiplier = 0.11f;
|
||||
|
||||
@@ -287,6 +287,8 @@ public class UnitTypes implements ContentList{
|
||||
alternate = false;
|
||||
ejectEffect = Fx.none;
|
||||
recoil = 2f;
|
||||
shootSound = Sounds.lasershoot;
|
||||
|
||||
bullet = new LaserBoltBulletType(5.2f, 14){{
|
||||
healPercent = 5f;
|
||||
collidesTeam = true;
|
||||
@@ -328,7 +330,7 @@ public class UnitTypes implements ContentList{
|
||||
spacing = 0f;
|
||||
ejectEffect = Fx.none;
|
||||
recoil = 2.5f;
|
||||
shootSound = Sounds.pew;
|
||||
shootSound = Sounds.spark;
|
||||
|
||||
bullet = new LightningBulletType(){{
|
||||
lightningColor = hitColor = Pal.heal;
|
||||
@@ -636,7 +638,7 @@ public class UnitTypes implements ContentList{
|
||||
ejectEffect = Fx.none;
|
||||
recoil = 2f;
|
||||
rotate = true;
|
||||
shootSound = Sounds.flame;
|
||||
shootSound = Sounds.sap;
|
||||
|
||||
x = 8.5f;
|
||||
y = -1.5f;
|
||||
@@ -659,6 +661,7 @@ public class UnitTypes implements ContentList{
|
||||
rotate = true;
|
||||
x = 4f;
|
||||
y = 3f;
|
||||
shootSound = Sounds.sap;
|
||||
|
||||
bullet = new SapBulletType(){{
|
||||
sapStrength = 0.8f;
|
||||
@@ -723,6 +726,7 @@ public class UnitTypes implements ContentList{
|
||||
y = 8f;
|
||||
rotate = true;
|
||||
bullet = sapper;
|
||||
shootSound = Sounds.sap;
|
||||
}},
|
||||
new Weapon("spiroct-weapon"){{
|
||||
reload = 15f;
|
||||
@@ -730,6 +734,7 @@ public class UnitTypes implements ContentList{
|
||||
y = 6f;
|
||||
rotate = true;
|
||||
bullet = sapper;
|
||||
shootSound = Sounds.sap;
|
||||
}},
|
||||
new Weapon("spiroct-weapon"){{
|
||||
reload = 23f;
|
||||
@@ -737,6 +742,7 @@ public class UnitTypes implements ContentList{
|
||||
y = 0f;
|
||||
rotate = true;
|
||||
bullet = sapper;
|
||||
shootSound = Sounds.sap;
|
||||
}},
|
||||
new Weapon("large-purple-mount"){{
|
||||
y = -7f;
|
||||
@@ -746,7 +752,7 @@ public class UnitTypes implements ContentList{
|
||||
shake = 3f;
|
||||
rotateSpeed = 2f;
|
||||
ejectEffect = Fx.casing1;
|
||||
shootSound = Sounds.shootBig;
|
||||
shootSound = Sounds.artillery;
|
||||
rotate = true;
|
||||
occlusion = 8f;
|
||||
recoil = 3f;
|
||||
@@ -844,7 +850,7 @@ public class UnitTypes implements ContentList{
|
||||
recoil = 10f;
|
||||
rotateSpeed = 1f;
|
||||
ejectEffect = Fx.casing3;
|
||||
shootSound = Sounds.shootBig;
|
||||
shootSound = Sounds.artillery;
|
||||
rotate = true;
|
||||
occlusion = 30f;
|
||||
|
||||
@@ -1663,6 +1669,7 @@ public class UnitTypes implements ContentList{
|
||||
shake = 6f;
|
||||
recoil = 10.5f;
|
||||
occlusion = 50f;
|
||||
shootSound = Sounds.railgun;
|
||||
|
||||
shots = 1;
|
||||
ejectEffect = Fx.none;
|
||||
|
||||
@@ -24,6 +24,12 @@ public class Weathers implements ContentList{
|
||||
sizeMin = 2.6f;
|
||||
density = 1200f;
|
||||
attrs.set(Attribute.light, -0.15f);
|
||||
|
||||
sound = Sounds.windhowl;
|
||||
soundVol = 0f;
|
||||
soundVolOscMag = 1.5f;
|
||||
soundVolOscScl = 1100f;
|
||||
soundVolMin = 0.02f;
|
||||
}};
|
||||
|
||||
rain = new RainWeather("rain"){{
|
||||
@@ -31,7 +37,7 @@ public class Weathers implements ContentList{
|
||||
attrs.set(Attribute.water, 0.2f);
|
||||
status = StatusEffects.wet;
|
||||
sound = Sounds.rain;
|
||||
soundVolume = 0.25f;
|
||||
soundVol = 0.25f;
|
||||
}};
|
||||
|
||||
sandstorm = new ParticleWeather("sandstorm"){{
|
||||
@@ -50,7 +56,7 @@ public class Weathers implements ContentList{
|
||||
opacityMultiplier = 0.8f;
|
||||
force = 0.1f;
|
||||
sound = Sounds.wind;
|
||||
soundVolume = 0.3f;
|
||||
soundVol = 0.3f;
|
||||
}};
|
||||
|
||||
sporestorm = new ParticleWeather("sporestorm"){{
|
||||
@@ -71,7 +77,7 @@ public class Weathers implements ContentList{
|
||||
opacityMultiplier = 0.85f;
|
||||
force = 0.1f;
|
||||
sound = Sounds.wind;
|
||||
soundVolume = 0.3f;
|
||||
soundVol = 0.3f;
|
||||
}};
|
||||
|
||||
fog = new ParticleWeather("fog"){{
|
||||
|
||||
@@ -476,10 +476,6 @@ public class Control implements ApplicationListener, Loadable{
|
||||
dialog.show();
|
||||
}));
|
||||
}
|
||||
|
||||
if(android){
|
||||
Sounds.empty.loop(0f, 1f, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -207,7 +207,7 @@ public abstract class BulletType extends Content{
|
||||
Damage.createIncend(x, y, incendSpread, incendAmount);
|
||||
}
|
||||
|
||||
if(splashDamageRadius > 0){
|
||||
if(splashDamageRadius > 0 && !b.absorbed){
|
||||
Damage.damage(b.team, x, y, splashDamageRadius, splashDamage * b.damageMultiplier(), collidesAir, collidesGround);
|
||||
|
||||
if(status != StatusEffects.none){
|
||||
|
||||
@@ -781,7 +781,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
}
|
||||
|
||||
/** @return whether this block should play its idle sound.*/
|
||||
public boolean shouldIdleSound(){
|
||||
public boolean shouldAmbientSound(){
|
||||
return shouldConsume();
|
||||
}
|
||||
|
||||
@@ -1226,6 +1226,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
}
|
||||
|
||||
/** @return ambient sound volume scale. */
|
||||
public float ambientVolume(){
|
||||
return efficiency();
|
||||
}
|
||||
|
||||
//endregion
|
||||
//region overrides
|
||||
|
||||
@@ -1367,8 +1372,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
sound.update(x, y, shouldActiveSound());
|
||||
}
|
||||
|
||||
if(block.ambientSound != Sounds.none && shouldIdleSound()){
|
||||
loops.play(block.ambientSound, self(), block.ambientSoundVolume);
|
||||
if(block.ambientSound != Sounds.none && shouldAmbientSound()){
|
||||
loops.play(block.ambientSound, self(), block.ambientSoundVolume * ambientVolume());
|
||||
}
|
||||
|
||||
if(enabled || !block.noUpdateDisabled){
|
||||
|
||||
@@ -30,6 +30,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
|
||||
Object data;
|
||||
BulletType type;
|
||||
float fdata;
|
||||
transient boolean absorbed;
|
||||
|
||||
@Override
|
||||
public void getCollisions(Cons<QuadTree> consumer){
|
||||
@@ -67,6 +68,7 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw
|
||||
|
||||
@Override
|
||||
public void absorb(){
|
||||
absorbed = true;
|
||||
remove();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@ import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
import static mindustry.game.EventType.*;
|
||||
|
||||
@@ -450,111 +448,11 @@ public class Administration{
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void load(){
|
||||
if(!loadLegacy()){
|
||||
//load default data
|
||||
playerInfo = Core.settings.getJson("player-data", ObjectMap.class, ObjectMap::new);
|
||||
bannedIPs = Core.settings.getJson("ip-bans", Seq.class, Seq::new);
|
||||
whitelist = Core.settings.getJson("whitelist-ids", Seq.class, Seq::new);
|
||||
subnetBans = Core.settings.getJson("banned-subnets", Seq.class, Seq::new);
|
||||
}else{
|
||||
//save over loaded legacy data
|
||||
save();
|
||||
Log.info("Loaded legacy (5.0) server data.");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadLegacy(){
|
||||
try{
|
||||
byte[] info = Core.settings.getBytes("player-info");
|
||||
byte[] ips = Core.settings.getBytes("banned-ips");
|
||||
byte[] whitelist = Core.settings.getBytes("whitelisted");
|
||||
byte[] subnet = Core.settings.getBytes("subnet-bans");
|
||||
|
||||
if(info != null){
|
||||
DataInputStream d = new DataInputStream(new ByteArrayInputStream(info));
|
||||
int size = d.readInt();
|
||||
if(size != 0){
|
||||
d.readUTF();
|
||||
d.readUTF();
|
||||
|
||||
for(int i = 0; i < size; i++){
|
||||
String mapKey = d.readUTF();
|
||||
|
||||
PlayerInfo data = new PlayerInfo();
|
||||
|
||||
data.id = d.readUTF();
|
||||
data.lastName = d.readUTF();
|
||||
data.lastIP = d.readUTF();
|
||||
int ipsize = d.readInt();
|
||||
if(ipsize != 0){
|
||||
d.readUTF();
|
||||
for(int j = 0; j < ipsize; j++){
|
||||
data.ips.add(d.readUTF());
|
||||
}
|
||||
}
|
||||
|
||||
int namesize = d.readInt();
|
||||
if(namesize != 0){
|
||||
d.readUTF();
|
||||
for(int j = 0; j < ipsize; j++){
|
||||
data.names.add(d.readUTF());
|
||||
}
|
||||
}
|
||||
//ips, names...
|
||||
data.adminUsid = d.readUTF();
|
||||
data.timesKicked = d.readInt();
|
||||
data.timesJoined = d.readInt();
|
||||
data.banned = d.readBoolean();
|
||||
data.admin = d.readBoolean();
|
||||
data.lastKicked = d.readLong();
|
||||
|
||||
playerInfo.put(mapKey, data);
|
||||
}
|
||||
}
|
||||
Core.settings.remove("player-info");
|
||||
}
|
||||
|
||||
if(ips != null){
|
||||
DataInputStream d = new DataInputStream(new ByteArrayInputStream(ips));
|
||||
int size = d.readInt();
|
||||
if(size != 0){
|
||||
d.readUTF();
|
||||
for(int i = 0; i < size; i++){
|
||||
bannedIPs.add(d.readUTF());
|
||||
}
|
||||
}
|
||||
Core.settings.remove("banned-ips");
|
||||
}
|
||||
|
||||
if(whitelist != null){
|
||||
DataInputStream d = new DataInputStream(new ByteArrayInputStream(whitelist));
|
||||
int size = d.readInt();
|
||||
if(size != 0){
|
||||
d.readUTF();
|
||||
for(int i = 0; i < size; i++){
|
||||
this.whitelist.add(d.readUTF());
|
||||
}
|
||||
}
|
||||
Core.settings.remove("whitelisted");
|
||||
}
|
||||
|
||||
if(subnet != null){
|
||||
DataInputStream d = new DataInputStream(new ByteArrayInputStream(subnet));
|
||||
int size = d.readInt();
|
||||
if(size != 0){
|
||||
d.readUTF();
|
||||
for(int i = 0; i < size; i++){
|
||||
subnetBans.add(d.readUTF());
|
||||
}
|
||||
}
|
||||
Core.settings.remove("subnet-bans");
|
||||
}
|
||||
|
||||
return info != null || ips != null || whitelist != null || subnet != null;
|
||||
}catch(Throwable e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
//load default data
|
||||
playerInfo = Core.settings.getJson("player-data", ObjectMap.class, ObjectMap::new);
|
||||
bannedIPs = Core.settings.getJson("ip-bans", Seq.class, Seq::new);
|
||||
whitelist = Core.settings.getJson("whitelist-ids", Seq.class, Seq::new);
|
||||
subnetBans = Core.settings.getJson("banned-subnets", Seq.class, Seq::new);
|
||||
}
|
||||
|
||||
/** Server configuration definition. Each config value can be a string, boolean or number. */
|
||||
@@ -585,8 +483,7 @@ public class Administration{
|
||||
autosaveAmount("The maximum amount of autosaves. Older ones get replaced.", 10),
|
||||
autosaveSpacing("Spacing between autosaves in seconds.", 60 * 5),
|
||||
debug("Enable debug logging", false, () -> {
|
||||
LogLevel level = debug() ? LogLevel.debug : LogLevel.info;
|
||||
Log.level = level;
|
||||
Log.level = debug() ? LogLevel.debug : LogLevel.info;
|
||||
});
|
||||
|
||||
public static final Config[] all = values();
|
||||
|
||||
@@ -25,8 +25,8 @@ public abstract class Weather extends UnlockableContent{
|
||||
public float opacityMultiplier = 1f;
|
||||
public Attributes attrs = new Attributes();
|
||||
public Sound sound = Sounds.none;
|
||||
public float soundVolume = 0.1f;
|
||||
public float soundVolumeOscMag = 0f, soundVolumeOscScl = 20f;
|
||||
public float soundVol = 0.1f, soundVolMin = 0f;
|
||||
public float soundVolOscMag = 0f, soundVolOscScl = 20f;
|
||||
|
||||
//internals
|
||||
public Rand rand = new Rand();
|
||||
@@ -90,8 +90,8 @@ public abstract class Weather extends UnlockableContent{
|
||||
}
|
||||
|
||||
if(sound != Sounds.none){
|
||||
float noise = soundVolumeOscMag > 0 ? (float)Math.abs(Noise.rawNoise(Time.time() / soundVolumeOscScl)) * soundVolumeOscMag : 0;
|
||||
loops.play(sound, Core.camera.position, (soundVolume + noise) * state.opacity);
|
||||
float noise = soundVolOscMag > 0 ? (float)Math.abs(Noise.rawNoise(Time.time() / soundVolOscScl)) * soundVolOscMag : 0;
|
||||
loops.play(sound, Core.camera.position, Math.max((soundVol + noise) * state.opacity, soundVolMin));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ public class ForceProjector extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
public boolean shouldAmbientSound(){
|
||||
return !broken && realRadius() > 1f;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.world.blocks.defense.turrets;
|
||||
|
||||
import arc.audio.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
@@ -24,6 +25,8 @@ public class PointDefenseTurret extends ReloadTurret{
|
||||
public Effect hitEffect = Fx.pointHit;
|
||||
public Effect shootEffect = Fx.sparkShoot;
|
||||
|
||||
public Sound shootSound = Sounds.lasershoot;
|
||||
|
||||
public float shootCone = 5f;
|
||||
public float bulletDamage = 10f;
|
||||
public float shootLength = 3f;
|
||||
@@ -90,6 +93,7 @@ public class PointDefenseTurret extends ReloadTurret{
|
||||
beamEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, color, new Vec2().set(target));
|
||||
shootEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, color);
|
||||
hitEffect.at(target.x, target.y, color);
|
||||
shootSound.at(x + Tmp.v1.x, y + Tmp.v1.y, Mathf.random(0.9f, 1.1f));
|
||||
reload = 0;
|
||||
}
|
||||
}else{
|
||||
|
||||
@@ -161,7 +161,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
public boolean shouldAmbientSound(){
|
||||
return clogHeat <= 0.5f;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ public class StackConveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
public boolean shouldAmbientSound(){
|
||||
return false; // has no moving parts;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,11 @@ public class ImpactReactor extends PowerGenerator{
|
||||
productionEfficiency = Mathf.pow(warmup, 5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float ambientVolume(){
|
||||
return warmup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
Draw.rect(bottomRegion, x, y);
|
||||
|
||||
@@ -67,7 +67,7 @@ public class Drill extends Block{
|
||||
liquidCapacity = 5f;
|
||||
hasItems = true;
|
||||
ambientSound = Sounds.drill;
|
||||
ambientSoundVolume = 0.003f;
|
||||
ambientSoundVolume = 0.016f;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -205,8 +205,8 @@ public class Drill extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
return efficiency() > 0.01f;
|
||||
public boolean shouldAmbientSound(){
|
||||
return efficiency() > 0.01f && items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -136,7 +136,7 @@ public class GenericCrafter extends Block{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
public boolean shouldAmbientSound(){
|
||||
return cons.valid();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
/** A GenericCrafter with a new glowing region drawn on top. */
|
||||
@@ -14,6 +15,8 @@ public class GenericSmelter extends GenericCrafter{
|
||||
|
||||
public GenericSmelter(String name){
|
||||
super(name);
|
||||
ambientSound = Sounds.smelter;
|
||||
ambientSoundVolume = 0.06f;
|
||||
}
|
||||
|
||||
public class SmelterBuild extends GenericCrafterBuild{
|
||||
|
||||
@@ -52,7 +52,7 @@ public class Separator extends Block{
|
||||
public float warmup;
|
||||
|
||||
@Override
|
||||
public boolean shouldIdleSound(){
|
||||
public boolean shouldAmbientSound(){
|
||||
return cons.valid();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user