Formatting
This commit is contained in:
@@ -49,237 +49,237 @@ import java.util.Locale;
|
|||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class AndroidLauncher extends AndroidApplication{
|
public class AndroidLauncher extends AndroidApplication{
|
||||||
public static final int PERMISSION_REQUEST_CODE = 1;
|
public static final int PERMISSION_REQUEST_CODE = 1;
|
||||||
|
|
||||||
boolean doubleScaleTablets = true;
|
boolean doubleScaleTablets = true;
|
||||||
FileChooser chooser;
|
FileChooser chooser;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState){
|
protected void onCreate(Bundle savedInstanceState){
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
|
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
|
||||||
config.useImmersiveMode = true;
|
config.useImmersiveMode = true;
|
||||||
|
|
||||||
Platform.instance = new Platform(){
|
Platform.instance = new Platform(){
|
||||||
DateFormat format = SimpleDateFormat.getDateTimeInstance();
|
DateFormat format = SimpleDateFormat.getDateTimeInstance();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasDiscord() {
|
public boolean hasDiscord(){
|
||||||
return isPackageInstalled("com.discord");
|
return isPackageInstalled("com.discord");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String format(Date date){
|
public String format(Date date){
|
||||||
return format.format(date);
|
return format.format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String format(int number){
|
public String format(int number){
|
||||||
return NumberFormat.getIntegerInstance().format(number);
|
return NumberFormat.getIntegerInstance().format(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addDialog(TextField field, int length){
|
public void addDialog(TextField field, int length){
|
||||||
TextFieldDialogListener.add(field, 0, length);
|
TextFieldDialogListener.add(field, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getLocaleName(Locale locale){
|
public String getLocaleName(Locale locale){
|
||||||
return locale.getDisplayName(locale);
|
return locale.getDisplayName(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void openDonations() {
|
public void openDonations(){
|
||||||
showDonations();
|
showDonations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ThreadProvider getThreadProvider() {
|
public ThreadProvider getThreadProvider(){
|
||||||
return new DefaultThreadImpl();
|
return new DefaultThreadImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDebug() {
|
public boolean isDebug(){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUUID() {
|
public String getUUID(){
|
||||||
try {
|
try{
|
||||||
String s = Secure.getString(getContext().getContentResolver(),
|
String s = Secure.getString(getContext().getContentResolver(),
|
||||||
Secure.ANDROID_ID);
|
Secure.ANDROID_ID);
|
||||||
|
|
||||||
int len = s.length();
|
int len = s.length();
|
||||||
byte[] data = new byte[len / 2];
|
byte[] data = new byte[len / 2];
|
||||||
for (int i = 0; i < len; i += 2) {
|
for(int i = 0; i < len; i += 2){
|
||||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
||||||
+ Character.digit(s.charAt(i + 1), 16));
|
+ Character.digit(s.charAt(i + 1), 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
String result = new String(Base64Coder.encode(data));
|
String result = new String(Base64Coder.encode(data));
|
||||||
|
|
||||||
if(result.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID.");
|
if(result.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID.");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}catch (Exception e){
|
}catch(Exception e){
|
||||||
return super.getUUID();
|
return super.getUUID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shareFile(FileHandle file){
|
public void shareFile(FileHandle file){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype) {
|
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){
|
||||||
chooser = new FileChooser(text, file -> file.extension().equalsIgnoreCase(filetype), open, cons);
|
chooser = new FileChooser(text, file -> file.extension().equalsIgnoreCase(filetype), open, cons);
|
||||||
|
|
||||||
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
||||||
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
|
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
|
||||||
chooser.show();
|
chooser.show();
|
||||||
chooser = null;
|
chooser = null;
|
||||||
}else {
|
}else{
|
||||||
ArrayList<String> perms = new ArrayList<>();
|
ArrayList<String> perms = new ArrayList<>();
|
||||||
|
|
||||||
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
|
||||||
perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
perms.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
|
||||||
perms.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
perms.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestPermissions(perms.toArray(new String[perms.size()]), PERMISSION_REQUEST_CODE);
|
requestPermissions(perms.toArray(new String[perms.size()]), PERMISSION_REQUEST_CODE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beginForceLandscape() {
|
public void beginForceLandscape(){
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endForceLandscape() {
|
public void endForceLandscape(){
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canDonate(){
|
public boolean canDonate(){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try{
|
||||||
ProviderInstaller.installIfNeeded(this);
|
ProviderInstaller.installIfNeeded(this);
|
||||||
} catch (GooglePlayServicesRepairableException e) {
|
}catch(GooglePlayServicesRepairableException e){
|
||||||
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
|
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
|
||||||
apiAvailability.getErrorDialog(this, e.getConnectionStatusCode(), 0).show();
|
apiAvailability.getErrorDialog(this, e.getConnectionStatusCode(), 0).show();
|
||||||
} catch (GooglePlayServicesNotAvailableException e) {
|
}catch(GooglePlayServicesNotAvailableException e){
|
||||||
Log.e("SecurityException", "Google Play Services not available.");
|
Log.e("SecurityException", "Google Play Services not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doubleScaleTablets && isTablet(this.getContext())){
|
if(doubleScaleTablets && isTablet(this.getContext())){
|
||||||
Unit.dp.addition = 0.5f;
|
Unit.dp.addition = 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
config.hideStatusBar = true;
|
config.hideStatusBar = true;
|
||||||
|
|
||||||
Net.setClientProvider(new KryoClient());
|
Net.setClientProvider(new KryoClient());
|
||||||
Net.setServerProvider(new KryoServer());
|
Net.setServerProvider(new KryoServer());
|
||||||
|
|
||||||
initialize(new Mindustry(), config);
|
initialize(new Mindustry(), config);
|
||||||
|
|
||||||
checkFiles(getIntent());
|
checkFiles(getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){
|
||||||
if(requestCode == PERMISSION_REQUEST_CODE){
|
if(requestCode == PERMISSION_REQUEST_CODE){
|
||||||
for(int i : grantResults){
|
for(int i : grantResults){
|
||||||
if(i != PackageManager.PERMISSION_GRANTED) return;
|
if(i != PackageManager.PERMISSION_GRANTED) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(chooser != null){
|
if(chooser != null){
|
||||||
chooser.show();
|
chooser.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkFiles(Intent intent){
|
private void checkFiles(Intent intent){
|
||||||
try {
|
try{
|
||||||
Uri uri = intent.getData();
|
Uri uri = intent.getData();
|
||||||
if (uri != null) {
|
if(uri != null){
|
||||||
File myFile = null;
|
File myFile = null;
|
||||||
String scheme = uri.getScheme();
|
String scheme = uri.getScheme();
|
||||||
if (scheme.equals("file")) {
|
if(scheme.equals("file")){
|
||||||
String fileName = uri.getEncodedPath();
|
String fileName = uri.getEncodedPath();
|
||||||
myFile = new File(fileName);
|
myFile = new File(fileName);
|
||||||
} else if (!scheme.equals("content")) {
|
}else if(!scheme.equals("content")){
|
||||||
//error
|
//error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean save = uri.getPath().endsWith(saveExtension);
|
boolean save = uri.getPath().endsWith(saveExtension);
|
||||||
boolean map = uri.getPath().endsWith(mapExtension);
|
boolean map = uri.getPath().endsWith(mapExtension);
|
||||||
|
|
||||||
InputStream inStream;
|
InputStream inStream;
|
||||||
if (myFile != null) inStream = new FileInputStream(myFile);
|
if(myFile != null) inStream = new FileInputStream(myFile);
|
||||||
else inStream = getContentResolver().openInputStream(uri);
|
else inStream = getContentResolver().openInputStream(uri);
|
||||||
|
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
|
|
||||||
if(save){ //open save
|
if(save){ //open save
|
||||||
System.out.println("Opening save.");
|
System.out.println("Opening save.");
|
||||||
FileHandle file = Gdx.files.local("temp-save." + saveExtension);
|
FileHandle file = Gdx.files.local("temp-save." + saveExtension);
|
||||||
file.write(inStream, false);
|
file.write(inStream, false);
|
||||||
|
|
||||||
if(SaveIO.isSaveValid(file)){
|
if(SaveIO.isSaveValid(file)){
|
||||||
try{
|
try{
|
||||||
SaveSlot slot = control.getSaves().importSave(file);
|
SaveSlot slot = control.getSaves().importSave(file);
|
||||||
ui.load.runLoadSave(slot);
|
ui.load.runLoadSave(slot);
|
||||||
}catch (IOException e){
|
}catch(IOException e){
|
||||||
ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false)));
|
ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false)));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ui.showError("$text.save.import.invalid");
|
ui.showError("$text.save.import.invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if(map){ //open map
|
}else if(map){ //open map
|
||||||
Gdx.app.postRunnable(() -> {
|
Gdx.app.postRunnable(() -> {
|
||||||
System.out.println("Opening map.");
|
System.out.println("Opening map.");
|
||||||
if (!ui.editor.isShown()) {
|
if(!ui.editor.isShown()){
|
||||||
ui.editor.show();
|
ui.editor.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.editor.beginEditMap(inStream);
|
ui.editor.beginEditMap(inStream);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch (IOException e){
|
}catch(IOException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPackageInstalled(String packagename) {
|
private boolean isPackageInstalled(String packagename){
|
||||||
try {
|
try{
|
||||||
getPackageManager().getPackageInfo(packagename, 0);
|
getPackageManager().getPackageInfo(packagename, 0);
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception e) {
|
}catch(Exception e){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTablet(Context context) {
|
private boolean isTablet(Context context){
|
||||||
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
|
TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
return manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE;
|
return manager.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDonations(){
|
private void showDonations(){
|
||||||
Intent intent = new Intent(this, DonationsActivity.class);
|
Intent intent = new Intent(this, DonationsActivity.class);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,20 +11,20 @@ import android.widget.EditText;
|
|||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
|
||||||
public class AndroidTextFieldDialog{
|
public class AndroidTextFieldDialog{
|
||||||
private Activity activity;
|
private Activity activity;
|
||||||
private EditText userInput;
|
private EditText userInput;
|
||||||
private AlertDialog.Builder builder;
|
private AlertDialog.Builder builder;
|
||||||
private TextPromptListener listener;
|
private TextPromptListener listener;
|
||||||
private boolean isBuild;
|
private boolean isBuild;
|
||||||
|
|
||||||
public AndroidTextFieldDialog() {
|
public AndroidTextFieldDialog(){
|
||||||
this.activity = (Activity)Gdx.app;
|
this.activity = (Activity) Gdx.app;
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog show() {
|
public AndroidTextFieldDialog show(){
|
||||||
|
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
|
|
||||||
dialog.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
dialog.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||||
@@ -33,12 +33,12 @@ public class AndroidTextFieldDialog{
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AndroidTextFieldDialog load() {
|
private AndroidTextFieldDialog load(){
|
||||||
|
|
||||||
activity.runOnUiThread(() -> {
|
activity.runOnUiThread(() -> {
|
||||||
|
|
||||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);
|
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);
|
||||||
LayoutInflater li = LayoutInflater.from(activity);
|
LayoutInflater li = LayoutInflater.from(activity);
|
||||||
@@ -55,64 +55,65 @@ public class AndroidTextFieldDialog{
|
|||||||
isBuild = true;
|
isBuild = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Wait till TextPrompt is built.
|
// Wait till TextPrompt is built.
|
||||||
while (!isBuild) {
|
while(!isBuild){
|
||||||
try {
|
try{
|
||||||
Thread.sleep(10);
|
Thread.sleep(10);
|
||||||
} catch (InterruptedException e) { }
|
}catch(InterruptedException e){
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getResourceId(String pVariableName, String pVariableType) {
|
public int getResourceId(String pVariableName, String pVariableType){
|
||||||
try {
|
try{
|
||||||
return activity.getResources().getIdentifier(pVariableName, pVariableType, activity.getPackageName());
|
return activity.getResources().getIdentifier(pVariableName, pVariableType, activity.getPackageName());
|
||||||
} catch (Exception e) {
|
}catch(Exception e){
|
||||||
Gdx.app.error("Android Dialogs", "Cannot find resouce with name: " + pVariableName
|
Gdx.app.error("Android Dialogs", "Cannot find resouce with name: " + pVariableName
|
||||||
+ " Did you copy the layouts to /res/layouts and /res/layouts_v14 ?");
|
+ " Did you copy the layouts to /res/layouts and /res/layouts_v14 ?");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setText(CharSequence value) {
|
public AndroidTextFieldDialog setText(CharSequence value){
|
||||||
userInput.append(value);
|
userInput.append(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setCancelButtonLabel(CharSequence label) {
|
public AndroidTextFieldDialog setCancelButtonLabel(CharSequence label){
|
||||||
builder.setNegativeButton(label, (dialog, id) -> dialog.cancel());
|
builder.setNegativeButton(label, (dialog, id) -> dialog.cancel());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setConfirmButtonLabel(CharSequence label) {
|
public AndroidTextFieldDialog setConfirmButtonLabel(CharSequence label){
|
||||||
builder.setPositiveButton(label, (dialog, id) -> {
|
builder.setPositiveButton(label, (dialog, id) -> {
|
||||||
if (listener != null && !userInput.getText().toString().isEmpty()) {
|
if(listener != null && !userInput.getText().toString().isEmpty()){
|
||||||
listener.confirm(userInput.getText().toString());
|
listener.confirm(userInput.getText().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setTextPromptListener(TextPromptListener listener) {
|
public AndroidTextFieldDialog setTextPromptListener(TextPromptListener listener){
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setInputType(int type) {
|
public AndroidTextFieldDialog setInputType(int type){
|
||||||
userInput.setInputType(type);
|
userInput.setInputType(type);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidTextFieldDialog setMaxLength(int length) {
|
public AndroidTextFieldDialog setMaxLength(int length){
|
||||||
userInput.setFilters(new InputFilter[] { new InputFilter.LengthFilter(length) });
|
userInput.setFilters(new InputFilter[]{new InputFilter.LengthFilter(length)});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface TextPromptListener{
|
public interface TextPromptListener{
|
||||||
void confirm(String text);
|
void confirm(String text);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,9 @@ import android.support.v4.app.FragmentManager;
|
|||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
import org.sufficientlysecure.donations.DonationsFragment;
|
import org.sufficientlysecure.donations.DonationsFragment;
|
||||||
|
|
||||||
public class DonationsActivity extends FragmentActivity {
|
public class DonationsActivity extends FragmentActivity{
|
||||||
DonationsFragment donationsFragment;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Google
|
* Google
|
||||||
*/
|
*/
|
||||||
@@ -21,13 +18,14 @@ public class DonationsActivity extends FragmentActivity {
|
|||||||
private static final String[] GOOGLE_CATALOG = new String[]{
|
private static final String[] GOOGLE_CATALOG = new String[]{
|
||||||
"mindustry.donation.1", "mindustry.donation.2", "mindustry.donation.5",
|
"mindustry.donation.1", "mindustry.donation.2", "mindustry.donation.5",
|
||||||
"mindustry.donation.10", "mindustry.donation.15",
|
"mindustry.donation.10", "mindustry.donation.15",
|
||||||
"mindustry.donation.25", "mindustry.donation.50" };
|
"mindustry.donation.25", "mindustry.donation.50"};
|
||||||
|
DonationsFragment donationsFragment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the activity is first created.
|
* Called when the activity is first created.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState){
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setTheme(R.style.GdxTheme);
|
setTheme(R.style.GdxTheme);
|
||||||
@@ -35,7 +33,7 @@ public class DonationsActivity extends FragmentActivity {
|
|||||||
setContentView(R.layout.donations_activity);
|
setContentView(R.layout.donations_activity);
|
||||||
|
|
||||||
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
|
||||||
if (BuildConfig.DONATIONS_GOOGLE) {
|
if(BuildConfig.DONATIONS_GOOGLE){
|
||||||
donationsFragment = DonationsFragment.newInstance(BuildConfig.DEBUG, true, GOOGLE_PUBKEY, GOOGLE_CATALOG,
|
donationsFragment = DonationsFragment.newInstance(BuildConfig.DEBUG, true, GOOGLE_PUBKEY, GOOGLE_CATALOG,
|
||||||
getResources().getStringArray(R.array.donation_google_catalog_values), false, null, null,
|
getResources().getStringArray(R.array.donation_google_catalog_values), false, null, null,
|
||||||
null, false, null, null, false, null);
|
null, false, null, null, false, null);
|
||||||
@@ -48,9 +46,10 @@ public class DonationsActivity extends FragmentActivity {
|
|||||||
|
|
||||||
public void onStart(){
|
public void onStart(){
|
||||||
super.onStart();
|
super.onStart();
|
||||||
Button b = ((Button)findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button));
|
Button b = ((Button) findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button));
|
||||||
b.setOnClickListener(new View.OnClickListener() {
|
b.setOnClickListener(new View.OnClickListener(){
|
||||||
@Override public void onClick(View view) {
|
@Override
|
||||||
|
public void onClick(View view){
|
||||||
donationsFragment.donateGoogleOnClick(donationsFragment.getView());
|
donationsFragment.donateGoogleOnClick(donationsFragment.getView());
|
||||||
b.setEnabled(false);
|
b.setEnabled(false);
|
||||||
}
|
}
|
||||||
@@ -58,20 +57,19 @@ public class DonationsActivity extends FragmentActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needed for Google Play In-app Billing. It uses startIntentSenderForResult(). The result is not propagated to
|
* Needed for Google Play In-app Billing. It uses startIntentSenderForResult(). The result is not propagated to
|
||||||
* the Fragment like in startActivityForResult(). Thus we need to propagate manually to our Fragment.
|
* the Fragment like in startActivityForResult(). Thus we need to propagate manually to our Fragment.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data){
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
Button b = ((Button)findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button));
|
Button b = ((Button) findViewById(org.sufficientlysecure.donations.R.id.donations__google_android_market_donate_button));
|
||||||
b.setEnabled(true);
|
b.setEnabled(true);
|
||||||
|
|
||||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
Fragment fragment = fragmentManager.findFragmentByTag("donationsFragment");
|
Fragment fragment = fragmentManager.findFragmentByTag("donationsFragment");
|
||||||
if (fragment != null) {
|
if(fragment != null){
|
||||||
fragment.onActivityResult(requestCode, resultCode, data);
|
fragment.onActivityResult(requestCode, resultCode, data);
|
||||||
//TODO donation event, set settings?
|
//TODO donation event, set settings?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,57 +11,57 @@ import io.anuke.ucore.scene.event.InputListener;
|
|||||||
import io.anuke.ucore.scene.ui.TextField;
|
import io.anuke.ucore.scene.ui.TextField;
|
||||||
|
|
||||||
public class TextFieldDialogListener extends ClickListener{
|
public class TextFieldDialogListener extends ClickListener{
|
||||||
private TextField field;
|
private TextField field;
|
||||||
private int type;
|
private int type;
|
||||||
private int max;
|
private int max;
|
||||||
|
|
||||||
public static void add(TextField field, int type, int max){
|
//type - 0 is text, 1 is numbers, 2 is decimals
|
||||||
field.addListener(new TextFieldDialogListener(field, type, max));
|
public TextFieldDialogListener(TextField field, int type, int max){
|
||||||
field.addListener(new InputListener(){
|
this.field = field;
|
||||||
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
|
this.type = type;
|
||||||
Gdx.input.setOnscreenKeyboardVisible(false);
|
this.max = max;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void add(TextField field){
|
public static void add(TextField field, int type, int max){
|
||||||
add(field, 0, 16);
|
field.addListener(new TextFieldDialogListener(field, type, max));
|
||||||
}
|
field.addListener(new InputListener(){
|
||||||
|
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
|
||||||
|
Gdx.input.setOnscreenKeyboardVisible(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//type - 0 is text, 1 is numbers, 2 is decimals
|
public static void add(TextField field){
|
||||||
public TextFieldDialogListener(TextField field, int type, int max){
|
add(field, 0, 16);
|
||||||
this.field = field;
|
}
|
||||||
this.type = type;
|
|
||||||
this.max = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clicked(final InputEvent event, float x, float y){
|
public void clicked(final InputEvent event, float x, float y){
|
||||||
|
|
||||||
if(Gdx.app.getType() == ApplicationType.Desktop) return;
|
|
||||||
|
|
||||||
AndroidTextFieldDialog dialog = new AndroidTextFieldDialog();
|
|
||||||
|
|
||||||
dialog.setTextPromptListener(text -> {
|
if(Gdx.app.getType() == ApplicationType.Desktop) return;
|
||||||
|
|
||||||
|
AndroidTextFieldDialog dialog = new AndroidTextFieldDialog();
|
||||||
|
|
||||||
|
dialog.setTextPromptListener(text -> {
|
||||||
field.clearText();
|
field.clearText();
|
||||||
field.appendText(text);
|
field.appendText(text);
|
||||||
field.fire(new ChangeListener.ChangeEvent());
|
field.fire(new ChangeListener.ChangeEvent());
|
||||||
Gdx.graphics.requestRendering();
|
Gdx.graphics.requestRendering();
|
||||||
});
|
});
|
||||||
|
|
||||||
if(type == 0){
|
if(type == 0){
|
||||||
dialog.setInputType(InputType.TYPE_CLASS_TEXT);
|
dialog.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||||
}else if(type == 1){
|
}else if(type == 1){
|
||||||
dialog.setInputType(InputType.TYPE_CLASS_NUMBER);
|
dialog.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||||
}else if(type == 2){
|
}else if(type == 2){
|
||||||
dialog.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
dialog.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.setConfirmButtonLabel("OK").setText(field.getText());
|
dialog.setConfirmButtonLabel("OK").setText(field.getText());
|
||||||
dialog.setCancelButtonLabel("Cancel");
|
dialog.setCancelButtonLabel("Cancel");
|
||||||
dialog.setMaxLength(max);
|
dialog.setMaxLength(max);
|
||||||
dialog.show();
|
dialog.show();
|
||||||
event.cancel();
|
event.cancel();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,70 +9,31 @@ import java.lang.annotation.Target;
|
|||||||
* Goal: To create a system to send events to the server from the client and vice versa, without creating a new packet type each time.<br>
|
* Goal: To create a system to send events to the server from the client and vice versa, without creating a new packet type each time.<br>
|
||||||
* These events may optionally also trigger on the caller client/server as well.<br>
|
* These events may optionally also trigger on the caller client/server as well.<br>
|
||||||
*/
|
*/
|
||||||
public class Annotations {
|
public class Annotations{
|
||||||
|
|
||||||
/**Marks a method as invokable remotely across a server/client connection.*/
|
public enum PacketPriority{
|
||||||
@Target(ElementType.METHOD)
|
/** Gets put in a queue and processed if not connected. */
|
||||||
@Retention(RetentionPolicy.CLASS)
|
|
||||||
public @interface Remote {
|
|
||||||
/**Specifies the locations from which this method can be invoked.*/
|
|
||||||
Loc targets() default Loc.server;
|
|
||||||
/**Specifies which methods are generated. Only affects server-to-client methods.*/
|
|
||||||
Variant variants() default Variant.all;
|
|
||||||
/**The local locations where this method is called locally, when invoked.*/
|
|
||||||
Loc called() default Loc.none;
|
|
||||||
/**Whether to forward this packet to all other clients upon recieval. Client only.*/
|
|
||||||
boolean forward() default false;
|
|
||||||
/**Whether the packet for this method is sent with UDP instead of TCP.
|
|
||||||
* UDP is faster, but is prone to packet loss and duplication.*/
|
|
||||||
boolean unreliable() default false;
|
|
||||||
/**The simple class name where this method is placed.*/
|
|
||||||
String in() default "Call";
|
|
||||||
/**Priority of this event.*/
|
|
||||||
PacketPriority priority() default PacketPriority.normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Specifies that this method will be used to write classes of the type returned by {@link #value()}.<br>
|
|
||||||
* This method must return void and have two parameters, the first being of type {@link java.nio.ByteBuffer} and the second
|
|
||||||
* being the type returned by {@link #value()}.*/
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.CLASS)
|
|
||||||
public @interface WriteClass {
|
|
||||||
Class<?> value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Specifies that this method will be used to read classes of the type returned by {@link #value()}. <br>
|
|
||||||
* This method must return the type returned by {@link #value()},
|
|
||||||
* and have one parameter, being of type {@link java.nio.ByteBuffer}.*/
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.CLASS)
|
|
||||||
public @interface ReadClass {
|
|
||||||
Class<?> value();
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PacketPriority {
|
|
||||||
/**Gets put in a queue and processed if not connected.*/
|
|
||||||
normal,
|
normal,
|
||||||
/**Gets handled immediately, regardless of connection status.*/
|
/** Gets handled immediately, regardless of connection status. */
|
||||||
high,
|
high,
|
||||||
/**Does not get handled unless client is connected.*/
|
/** Does not get handled unless client is connected. */
|
||||||
low
|
low
|
||||||
}
|
}
|
||||||
|
|
||||||
/**A set of two booleans, one specifying server and one specifying client.*/
|
/** A set of two booleans, one specifying server and one specifying client. */
|
||||||
public enum Loc {
|
public enum Loc{
|
||||||
/**Method can only be invoked on the client from the server.*/
|
/** Method can only be invoked on the client from the server. */
|
||||||
server(true, false),
|
server(true, false),
|
||||||
/**Method can only be invoked on the server from the client.*/
|
/** Method can only be invoked on the server from the client. */
|
||||||
client(false, true),
|
client(false, true),
|
||||||
/**Method can be invoked from anywhere*/
|
/** Method can be invoked from anywhere */
|
||||||
both(true, true),
|
both(true, true),
|
||||||
/**Neither server nor client.*/
|
/** Neither server nor client. */
|
||||||
none(false, false);
|
none(false, false);
|
||||||
|
|
||||||
/**If true, this method can be invoked ON clients FROM servers.*/
|
/** If true, this method can be invoked ON clients FROM servers. */
|
||||||
public final boolean isServer;
|
public final boolean isServer;
|
||||||
/**If true, this method can be invoked ON servers FROM clients.*/
|
/** If true, this method can be invoked ON servers FROM clients. */
|
||||||
public final boolean isClient;
|
public final boolean isClient;
|
||||||
|
|
||||||
Loc(boolean server, boolean client){
|
Loc(boolean server, boolean client){
|
||||||
@@ -81,12 +42,12 @@ public class Annotations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Variant {
|
public enum Variant{
|
||||||
/**Method can only be invoked targeting one player.*/
|
/** Method can only be invoked targeting one player. */
|
||||||
one(true, false),
|
one(true, false),
|
||||||
/**Method can only be invoked targeting all players.*/
|
/** Method can only be invoked targeting all players. */
|
||||||
all(false, true),
|
all(false, true),
|
||||||
/**Method targets both one player and all players.*/
|
/** Method targets both one player and all players. */
|
||||||
both(true, true);
|
both(true, true);
|
||||||
|
|
||||||
public final boolean isOne, isAll;
|
public final boolean isOne, isAll;
|
||||||
@@ -96,4 +57,55 @@ public class Annotations {
|
|||||||
this.isAll = isAll;
|
this.isAll = isAll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Marks a method as invokable remotely across a server/client connection. */
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
public @interface Remote{
|
||||||
|
/** Specifies the locations from which this method can be invoked. */
|
||||||
|
Loc targets() default Loc.server;
|
||||||
|
|
||||||
|
/** Specifies which methods are generated. Only affects server-to-client methods. */
|
||||||
|
Variant variants() default Variant.all;
|
||||||
|
|
||||||
|
/** The local locations where this method is called locally, when invoked. */
|
||||||
|
Loc called() default Loc.none;
|
||||||
|
|
||||||
|
/** Whether to forward this packet to all other clients upon recieval. Client only. */
|
||||||
|
boolean forward() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the packet for this method is sent with UDP instead of TCP.
|
||||||
|
* UDP is faster, but is prone to packet loss and duplication.
|
||||||
|
*/
|
||||||
|
boolean unreliable() default false;
|
||||||
|
|
||||||
|
/** The simple class name where this method is placed. */
|
||||||
|
String in() default "Call";
|
||||||
|
|
||||||
|
/** Priority of this event. */
|
||||||
|
PacketPriority priority() default PacketPriority.normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that this method will be used to write classes of the type returned by {@link #value()}.<br>
|
||||||
|
* This method must return void and have two parameters, the first being of type {@link java.nio.ByteBuffer} and the second
|
||||||
|
* being the type returned by {@link #value()}.
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
public @interface WriteClass{
|
||||||
|
Class<?> value();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies that this method will be used to read classes of the type returned by {@link #value()}. <br>
|
||||||
|
* This method must return the type returned by {@link #value()},
|
||||||
|
* and have one parameter, being of type {@link java.nio.ByteBuffer}.
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
public @interface ReadClass{
|
||||||
|
Class<?> value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ package io.anuke.annotations;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**Represents a class witha list method entries to include in it.*/
|
/** Represents a class witha list method entries to include in it. */
|
||||||
public class ClassEntry {
|
public class ClassEntry{
|
||||||
/**All methods in this generated class.*/
|
/** All methods in this generated class. */
|
||||||
public final ArrayList<MethodEntry> methods = new ArrayList<>();
|
public final ArrayList<MethodEntry> methods = new ArrayList<>();
|
||||||
/**Simple class name.*/
|
/** Simple class name. */
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
public ClassEntry(String name) {
|
public ClassEntry(String name){
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ import javax.tools.Diagnostic.Kind;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**This class finds reader and writer methods annotated by the {@link io.anuke.annotations.Annotations.WriteClass}
|
/**
|
||||||
* and {@link io.anuke.annotations.Annotations.ReadClass} annotations.*/
|
* This class finds reader and writer methods annotated by the {@link io.anuke.annotations.Annotations.WriteClass}
|
||||||
public class IOFinder {
|
* and {@link io.anuke.annotations.Annotations.ReadClass} annotations.
|
||||||
|
*/
|
||||||
|
public class IOFinder{
|
||||||
|
|
||||||
/**Finds all class serializers for all types and returns them. Logs errors when necessary.
|
/**
|
||||||
* Maps fully qualified class names to their serializers.*/
|
* Finds all class serializers for all types and returns them. Logs errors when necessary.
|
||||||
|
* Maps fully qualified class names to their serializers.
|
||||||
|
*/
|
||||||
public HashMap<String, ClassSerializer> findSerializers(RoundEnvironment env){
|
public HashMap<String, ClassSerializer> findSerializers(RoundEnvironment env){
|
||||||
HashMap<String, ClassSerializer> result = new HashMap<>();
|
HashMap<String, ClassSerializer> result = new HashMap<>();
|
||||||
|
|
||||||
@@ -51,33 +55,33 @@ public class IOFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getValue(WriteClass write){
|
private String getValue(WriteClass write){
|
||||||
try {
|
try{
|
||||||
Class<?> type = write.value();
|
Class<?> type = write.value();
|
||||||
return type.getName();
|
return type.getName();
|
||||||
}catch (MirroredTypeException e){
|
}catch(MirroredTypeException e){
|
||||||
return e.getTypeMirror().toString();
|
return e.getTypeMirror().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getValue(ReadClass read){
|
private String getValue(ReadClass read){
|
||||||
try {
|
try{
|
||||||
Class<?> type = read.value();
|
Class<?> type = read.value();
|
||||||
return type.getName();
|
return type.getName();
|
||||||
}catch (MirroredTypeException e){
|
}catch(MirroredTypeException e){
|
||||||
return e.getTypeMirror().toString();
|
return e.getTypeMirror().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Information about read/write methods for a specific class type.*/
|
/** Information about read/write methods for a specific class type. */
|
||||||
public static class ClassSerializer{
|
public static class ClassSerializer{
|
||||||
/**Fully qualified method name of the reader.*/
|
/** Fully qualified method name of the reader. */
|
||||||
public final String readMethod;
|
public final String readMethod;
|
||||||
/**Fully qualified method name of the writer.*/
|
/** Fully qualified method name of the writer. */
|
||||||
public final String writeMethod;
|
public final String writeMethod;
|
||||||
/**Fully qualified class type name.*/
|
/** Fully qualified class type name. */
|
||||||
public final String classType;
|
public final String classType;
|
||||||
|
|
||||||
public ClassSerializer(String readMethod, String writeMethod, String classType) {
|
public ClassSerializer(String readMethod, String writeMethod, String classType){
|
||||||
this.readMethod = readMethod;
|
this.readMethod = readMethod;
|
||||||
this.writeMethod = writeMethod;
|
this.writeMethod = writeMethod;
|
||||||
this.classType = classType;
|
this.classType = classType;
|
||||||
|
|||||||
@@ -6,32 +6,34 @@ import io.anuke.annotations.Annotations.Variant;
|
|||||||
|
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
|
||||||
/**Class that repesents a remote method to be constructed and put into a class.*/
|
/** Class that repesents a remote method to be constructed and put into a class. */
|
||||||
public class MethodEntry {
|
public class MethodEntry{
|
||||||
/**Simple target class name.*/
|
/** Simple target class name. */
|
||||||
public final String className;
|
public final String className;
|
||||||
/**Fully qualified target method to call.*/
|
/** Fully qualified target method to call. */
|
||||||
public final String targetMethod;
|
public final String targetMethod;
|
||||||
/**Whether this method can be called on a client/server.*/
|
/** Whether this method can be called on a client/server. */
|
||||||
public final Loc where;
|
public final Loc where;
|
||||||
/**Whether an additional 'one' and 'all' method variant is generated. At least one of these must be true.
|
/**
|
||||||
* Only applicable to client (server-invoked) methods.*/
|
* Whether an additional 'one' and 'all' method variant is generated. At least one of these must be true.
|
||||||
|
* Only applicable to client (server-invoked) methods.
|
||||||
|
*/
|
||||||
public final Variant target;
|
public final Variant target;
|
||||||
/**Whether this method is called locally as well as remotely.*/
|
/** Whether this method is called locally as well as remotely. */
|
||||||
public final Loc local;
|
public final Loc local;
|
||||||
/**Whether this method is unreliable and uses UDP.*/
|
/** Whether this method is unreliable and uses UDP. */
|
||||||
public final boolean unreliable;
|
public final boolean unreliable;
|
||||||
/**Whether to forward this method call to all other clients when a client invokes it. Server only.*/
|
/** Whether to forward this method call to all other clients when a client invokes it. Server only. */
|
||||||
public final boolean forward;
|
public final boolean forward;
|
||||||
/**Unique method ID.*/
|
/** Unique method ID. */
|
||||||
public final int id;
|
public final int id;
|
||||||
/**The element method associated with this entry.*/
|
/** The element method associated with this entry. */
|
||||||
public final ExecutableElement element;
|
public final ExecutableElement element;
|
||||||
/**The assigned packet priority. Only used in clients.*/
|
/** The assigned packet priority. Only used in clients. */
|
||||||
public final PacketPriority priority;
|
public final PacketPriority priority;
|
||||||
|
|
||||||
public MethodEntry(String className, String targetMethod, Loc where, Variant target,
|
public MethodEntry(String className, String targetMethod, Loc where, Variant target,
|
||||||
Loc local, boolean unreliable, boolean forward, int id, ExecutableElement element, PacketPriority priority) {
|
Loc local, boolean unreliable, boolean forward, int id, ExecutableElement element, PacketPriority priority){
|
||||||
this.className = className;
|
this.className = className;
|
||||||
this.forward = forward;
|
this.forward = forward;
|
||||||
this.targetMethod = targetMethod;
|
this.targetMethod = targetMethod;
|
||||||
@@ -45,7 +47,7 @@ public class MethodEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode(){
|
||||||
return targetMethod.hashCode();
|
return targetMethod.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,25 +18,25 @@ import java.util.*;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
/**The annotation processor for generating remote method call code.*/
|
/** The annotation processor for generating remote method call code. */
|
||||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
@SupportedAnnotationTypes({
|
@SupportedAnnotationTypes({
|
||||||
"io.anuke.annotations.Annotations.Remote",
|
"io.anuke.annotations.Annotations.Remote",
|
||||||
"io.anuke.annotations.Annotations.WriteClass",
|
"io.anuke.annotations.Annotations.WriteClass",
|
||||||
"io.anuke.annotations.Annotations.ReadClass",
|
"io.anuke.annotations.Annotations.ReadClass",
|
||||||
})
|
})
|
||||||
public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
public class RemoteMethodAnnotationProcessor extends AbstractProcessor{
|
||||||
/**Maximum size of each event packet.*/
|
/** Maximum size of each event packet. */
|
||||||
public static final int maxPacketSize = 4096;
|
public static final int maxPacketSize = 4096;
|
||||||
/**Name of the base package to put all the generated classes.*/
|
/** Name of the base package to put all the generated classes. */
|
||||||
private static final String packageName = "io.anuke.mindustry.gen";
|
private static final String packageName = "io.anuke.mindustry.gen";
|
||||||
|
|
||||||
/**Name of class that handles reading and invoking packets on the server.*/
|
/** Name of class that handles reading and invoking packets on the server. */
|
||||||
private static final String readServerName = "RemoteReadServer";
|
private static final String readServerName = "RemoteReadServer";
|
||||||
/**Name of class that handles reading and invoking packets on the client.*/
|
/** Name of class that handles reading and invoking packets on the client. */
|
||||||
private static final String readClientName = "RemoteReadClient";
|
private static final String readClientName = "RemoteReadClient";
|
||||||
|
|
||||||
/**Processing round number.*/
|
/** Processing round number. */
|
||||||
private int round;
|
private int round;
|
||||||
|
|
||||||
//class serializers
|
//class serializers
|
||||||
@@ -51,7 +51,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
private ArrayList<ClassEntry> classes;
|
private ArrayList<ClassEntry> classes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
public synchronized void init(ProcessingEnvironment processingEnv){
|
||||||
super.init(processingEnv);
|
super.init(processingEnv);
|
||||||
//put all relevant utils into utils class
|
//put all relevant utils into utils class
|
||||||
Utils.typeUtils = processingEnv.getTypeUtils();
|
Utils.typeUtils = processingEnv.getTypeUtils();
|
||||||
@@ -61,15 +61,15 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
|
||||||
if(round > 1) return false; //only process 2 rounds
|
if(round > 1) return false; //only process 2 rounds
|
||||||
|
|
||||||
round ++;
|
round++;
|
||||||
|
|
||||||
try {
|
try{
|
||||||
|
|
||||||
//round 1: find all annotations, generate *writers*
|
//round 1: find all annotations, generate *writers*
|
||||||
if(round == 1) {
|
if(round == 1){
|
||||||
//get serializers
|
//get serializers
|
||||||
serializers = new IOFinder().findSerializers(roundEnv);
|
serializers = new IOFinder().findSerializers(roundEnv);
|
||||||
|
|
||||||
@@ -88,21 +88,21 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
orderedElements.sort(Comparator.comparing(Object::toString));
|
orderedElements.sort(Comparator.comparing(Object::toString));
|
||||||
|
|
||||||
//create methods
|
//create methods
|
||||||
for (Element element : orderedElements) {
|
for(Element element : orderedElements){
|
||||||
Remote annotation = element.getAnnotation(Remote.class);
|
Remote annotation = element.getAnnotation(Remote.class);
|
||||||
|
|
||||||
//check for static
|
//check for static
|
||||||
if (!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)) {
|
if(!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "All @Remote methods must be public and static: ", element);
|
Utils.messager.printMessage(Kind.ERROR, "All @Remote methods must be public and static: ", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//can't generate none methods
|
//can't generate none methods
|
||||||
if (annotation.targets() == Loc.none) {
|
if(annotation.targets() == Loc.none){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "A @Remote method's targets() cannot be equal to 'none':", element);
|
Utils.messager.printMessage(Kind.ERROR, "A @Remote method's targets() cannot be equal to 'none':", element);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get and create class entry if needed
|
//get and create class entry if needed
|
||||||
if (!classMap.containsKey(annotation.in())) {
|
if(!classMap.containsKey(annotation.in())){
|
||||||
ClassEntry clas = new ClassEntry(annotation.in());
|
ClassEntry clas = new ClassEntry(annotation.in());
|
||||||
classMap.put(annotation.in(), clas);
|
classMap.put(annotation.in(), clas);
|
||||||
classes.add(clas);
|
classes.add(clas);
|
||||||
@@ -127,7 +127,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
writegen.generateFor(classes, packageName);
|
writegen.generateFor(classes, packageName);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}else if(round == 2) { //round 2: generate all *readers*
|
}else if(round == 2){ //round 2: generate all *readers*
|
||||||
RemoteReadGenerator readgen = new RemoteReadGenerator(serializers);
|
RemoteReadGenerator readgen = new RemoteReadGenerator(serializers);
|
||||||
|
|
||||||
//generate server readers
|
//generate server readers
|
||||||
@@ -147,7 +147,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch (Exception e){
|
}catch(Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,22 +14,25 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**Generates code for reading remote invoke packets on the client and server.*/
|
/** Generates code for reading remote invoke packets on the client and server. */
|
||||||
public class RemoteReadGenerator {
|
public class RemoteReadGenerator{
|
||||||
private final HashMap<String, ClassSerializer> serializers;
|
private final HashMap<String, ClassSerializer> serializers;
|
||||||
|
|
||||||
/**Creates a read generator that uses the supplied serializer setup.*/
|
/** Creates a read generator that uses the supplied serializer setup. */
|
||||||
public RemoteReadGenerator(HashMap<String, ClassSerializer> serializers) {
|
public RemoteReadGenerator(HashMap<String, ClassSerializer> serializers){
|
||||||
this.serializers = serializers;
|
this.serializers = serializers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Generates a class for reading remote invoke packets.
|
/**
|
||||||
|
* Generates a class for reading remote invoke packets.
|
||||||
|
*
|
||||||
* @param entries List of methods to use/
|
* @param entries List of methods to use/
|
||||||
* @param className Simple target class name.
|
* @param className Simple target class name.
|
||||||
* @param packageName Full target package name.
|
* @param packageName Full target package name.
|
||||||
* @param needsPlayer Whether this read method requires a reference to the player sender.*/
|
* @param needsPlayer Whether this read method requires a reference to the player sender.
|
||||||
|
*/
|
||||||
public void generateFor(List<MethodEntry> entries, String className, String packageName, boolean needsPlayer)
|
public void generateFor(List<MethodEntry> entries, String className, String packageName, boolean needsPlayer)
|
||||||
throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException {
|
throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException{
|
||||||
|
|
||||||
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
|
||||||
|
|
||||||
@@ -69,10 +72,10 @@ public class RemoteReadGenerator {
|
|||||||
StringBuilder varResult = new StringBuilder();
|
StringBuilder varResult = new StringBuilder();
|
||||||
|
|
||||||
//go through each parameter
|
//go through each parameter
|
||||||
for(int i = 0; i < entry.element.getParameters().size(); i ++){
|
for(int i = 0; i < entry.element.getParameters().size(); i++){
|
||||||
VariableElement var = entry.element.getParameters().get(i);
|
VariableElement var = entry.element.getParameters().get(i);
|
||||||
|
|
||||||
if(!needsPlayer || i != 0) { //if client, skip first parameter since it's always of type player and doesn't need to be read
|
if(!needsPlayer || i != 0){ //if client, skip first parameter since it's always of type player and doesn't need to be read
|
||||||
//full type name of parameter
|
//full type name of parameter
|
||||||
String typeName = var.asType().toString();
|
String typeName = var.asType().toString();
|
||||||
//name of parameter
|
//name of parameter
|
||||||
@@ -81,17 +84,17 @@ public class RemoteReadGenerator {
|
|||||||
String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
||||||
|
|
||||||
//write primitives automatically
|
//write primitives automatically
|
||||||
if (Utils.isPrimitive(typeName)) {
|
if(Utils.isPrimitive(typeName)){
|
||||||
if (typeName.equals("boolean")) {
|
if(typeName.equals("boolean")){
|
||||||
readBlock.addStatement("boolean " + varName + " = buffer.get() == 1");
|
readBlock.addStatement("boolean " + varName + " = buffer.get() == 1");
|
||||||
} else {
|
}else{
|
||||||
readBlock.addStatement(typeName + " " + varName + " = buffer.get" + capName + "()");
|
readBlock.addStatement(typeName + " " + varName + " = buffer.get" + capName + "()");
|
||||||
}
|
}
|
||||||
} else {
|
}else{
|
||||||
//else, try and find a serializer
|
//else, try and find a serializer
|
||||||
ClassSerializer ser = serializers.get(typeName);
|
ClassSerializer ser = serializers.get(typeName);
|
||||||
|
|
||||||
if (ser == null) { //make sure a serializer exists!
|
if(ser == null){ //make sure a serializer exists!
|
||||||
Utils.messager.printMessage(Kind.ERROR, "No @ReadClass method to read class type: '" + typeName + "'", var);
|
Utils.messager.printMessage(Kind.ERROR, "No @ReadClass method to read class type: '" + typeName + "'", var);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -121,7 +124,7 @@ public class RemoteReadGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readBlock.nextControlFlow("catch (java.lang.Exception e)");
|
readBlock.nextControlFlow("catch (java.lang.Exception e)");
|
||||||
readBlock.addStatement("throw new java.lang.RuntimeException(\"Failed to to read remote method '"+entry.element.getSimpleName() +"'!\", e)");
|
readBlock.addStatement("throw new java.lang.RuntimeException(\"Failed to to read remote method '" + entry.element.getSimpleName() + "'!\", e)");
|
||||||
readBlock.endControlFlow();
|
readBlock.endControlFlow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ import java.nio.ByteBuffer;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**Generates code for writing remote invoke packets on the client and server.*/
|
/** Generates code for writing remote invoke packets on the client and server. */
|
||||||
public class RemoteWriteGenerator {
|
public class RemoteWriteGenerator{
|
||||||
private final HashMap<String, ClassSerializer> serializers;
|
private final HashMap<String, ClassSerializer> serializers;
|
||||||
|
|
||||||
/**Creates a write generator that uses the supplied serializer setup.*/
|
/** Creates a write generator that uses the supplied serializer setup. */
|
||||||
public RemoteWriteGenerator(HashMap<String, ClassSerializer> serializers) {
|
public RemoteWriteGenerator(HashMap<String, ClassSerializer> serializers){
|
||||||
this.serializers = serializers;
|
this.serializers = serializers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Generates all classes in this list.*/
|
/** Generates all classes in this list. */
|
||||||
public void generateFor(List<ClassEntry> entries, String packageName) throws IOException {
|
public void generateFor(List<ClassEntry> entries, String packageName) throws IOException{
|
||||||
|
|
||||||
for(ClassEntry entry : entries){
|
for(ClassEntry entry : entries){
|
||||||
//create builder
|
//create builder
|
||||||
@@ -58,7 +58,7 @@ public class RemoteWriteGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Creates a specific variant for a method entry.*/
|
/** Creates a specific variant for a method entry. */
|
||||||
private void writeMethodVariant(TypeSpec.Builder classBuilder, MethodEntry methodEntry, boolean toAll, boolean forwarded){
|
private void writeMethodVariant(TypeSpec.Builder classBuilder, MethodEntry methodEntry, boolean toAll, boolean forwarded){
|
||||||
ExecutableElement elem = methodEntry.element;
|
ExecutableElement elem = methodEntry.element;
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ public class RemoteWriteGenerator {
|
|||||||
if(!forwarded && methodEntry.local != Loc.none){
|
if(!forwarded && methodEntry.local != Loc.none){
|
||||||
//add in local checks
|
//add in local checks
|
||||||
if(methodEntry.local != Loc.both){
|
if(methodEntry.local != Loc.both){
|
||||||
method.beginControlFlow("if("+getCheckString(methodEntry.local) + " || !io.anuke.mindustry.net.Net.active())");
|
method.beginControlFlow("if(" + getCheckString(methodEntry.local) + " || !io.anuke.mindustry.net.Net.active())");
|
||||||
}
|
}
|
||||||
|
|
||||||
//concatenate parameters
|
//concatenate parameters
|
||||||
@@ -109,16 +109,16 @@ public class RemoteWriteGenerator {
|
|||||||
//special case: calling local-only methods uses the local player
|
//special case: calling local-only methods uses the local player
|
||||||
if(index == 0 && methodEntry.where == Loc.client){
|
if(index == 0 && methodEntry.where == Loc.client){
|
||||||
results.append("io.anuke.mindustry.Vars.players[0]");
|
results.append("io.anuke.mindustry.Vars.players[0]");
|
||||||
}else {
|
}else{
|
||||||
results.append(var.getSimpleName());
|
results.append(var.getSimpleName());
|
||||||
}
|
}
|
||||||
if(index != elem.getParameters().size() - 1) results.append(", ");
|
if(index != elem.getParameters().size() - 1) results.append(", ");
|
||||||
index ++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//add the statement to call it
|
//add the statement to call it
|
||||||
method.addStatement("$N." + elem.getSimpleName() + "(" + results.toString() + ")",
|
method.addStatement("$N." + elem.getSimpleName() + "(" + results.toString() + ")",
|
||||||
((TypeElement)elem.getEnclosingElement()).getQualifiedName().toString());
|
((TypeElement) elem.getEnclosingElement()).getQualifiedName().toString());
|
||||||
|
|
||||||
if(methodEntry.local != Loc.both){
|
if(methodEntry.local != Loc.both){
|
||||||
method.endControlFlow();
|
method.endControlFlow();
|
||||||
@@ -126,7 +126,7 @@ public class RemoteWriteGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//start control flow to check if it's actually client/server so no netcode is called
|
//start control flow to check if it's actually client/server so no netcode is called
|
||||||
method.beginControlFlow("if("+getCheckString(methodEntry.where)+")");
|
method.beginControlFlow("if(" + getCheckString(methodEntry.where) + ")");
|
||||||
|
|
||||||
//add statement to create packet from pool
|
//add statement to create packet from pool
|
||||||
method.addStatement("$1N packet = $2N.obtain($1N.class)", "io.anuke.mindustry.net.Packets.InvokePacket", "io.anuke.ucore.util.Pooling");
|
method.addStatement("$1N packet = $2N.obtain($1N.class)", "io.anuke.mindustry.net.Packets.InvokePacket", "io.anuke.ucore.util.Pooling");
|
||||||
@@ -139,7 +139,7 @@ public class RemoteWriteGenerator {
|
|||||||
//rewind buffer
|
//rewind buffer
|
||||||
method.addStatement("TEMP_BUFFER.position(0)");
|
method.addStatement("TEMP_BUFFER.position(0)");
|
||||||
|
|
||||||
for(int i = 0; i < elem.getParameters().size(); i ++){
|
for(int i = 0; i < elem.getParameters().size(); i++){
|
||||||
//first argument is skipped as it is always the player caller
|
//first argument is skipped as it is always the player caller
|
||||||
if((!methodEntry.where.isServer/* || methodEntry.mode == Loc.both*/) && i == 0){
|
if((!methodEntry.where.isServer/* || methodEntry.mode == Loc.both*/) && i == 0){
|
||||||
continue;
|
continue;
|
||||||
@@ -164,7 +164,7 @@ public class RemoteWriteGenerator {
|
|||||||
method.beginControlFlow("if(io.anuke.mindustry.net.Net.server())");
|
method.beginControlFlow("if(io.anuke.mindustry.net.Net.server())");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Utils.isPrimitive(typeName)) { //check if it's a primitive, and if so write it
|
if(Utils.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
|
||||||
if(typeName.equals("boolean")){ //booleans are special
|
if(typeName.equals("boolean")){ //booleans are special
|
||||||
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
|
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
|
||||||
}else{
|
}else{
|
||||||
@@ -181,7 +181,7 @@ public class RemoteWriteGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//add statement for writing it
|
//add statement for writing it
|
||||||
method.addStatement(ser.writeMethod + "(TEMP_BUFFER, " + varName +")");
|
method.addStatement(ser.writeMethod + "(TEMP_BUFFER, " + varName + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(writePlayerSkipCheck){ //write end check
|
if(writePlayerSkipCheck){ //write end check
|
||||||
@@ -197,7 +197,7 @@ public class RemoteWriteGenerator {
|
|||||||
if(forwarded){ //forward packet
|
if(forwarded){ //forward packet
|
||||||
if(!methodEntry.local.isClient){ //if the client doesn't get it called locally, forward it back after validation
|
if(!methodEntry.local.isClient){ //if the client doesn't get it called locally, forward it back after validation
|
||||||
sendString = "send(";
|
sendString = "send(";
|
||||||
}else {
|
}else{
|
||||||
sendString = "sendExcept(exceptSenderID, ";
|
sendString = "sendExcept(exceptSenderID, ";
|
||||||
}
|
}
|
||||||
}else if(toAll){ //send to all players / to server
|
}else if(toAll){ //send to all players / to server
|
||||||
@@ -207,8 +207,8 @@ public class RemoteWriteGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//send the actual packet
|
//send the actual packet
|
||||||
method.addStatement("io.anuke.mindustry.net.Net." + sendString + "packet, "+
|
method.addStatement("io.anuke.mindustry.net.Net." + sendString + "packet, " +
|
||||||
(methodEntry.unreliable ? "io.anuke.mindustry.net.Net.SendMode.udp" : "io.anuke.mindustry.net.Net.SendMode.tcp")+")");
|
(methodEntry.unreliable ? "io.anuke.mindustry.net.Net.SendMode.udp" : "io.anuke.mindustry.net.Net.SendMode.tcp") + ")");
|
||||||
|
|
||||||
|
|
||||||
//end check for server/client
|
//end check for server/client
|
||||||
@@ -220,7 +220,7 @@ public class RemoteWriteGenerator {
|
|||||||
|
|
||||||
private String getCheckString(Loc loc){
|
private String getCheckString(Loc loc){
|
||||||
return loc.isClient && loc.isServer ? "io.anuke.mindustry.net.Net.server() || io.anuke.mindustry.net.Net.client()" :
|
return loc.isClient && loc.isServer ? "io.anuke.mindustry.net.Net.server() || io.anuke.mindustry.net.Net.client()" :
|
||||||
loc.isClient ? "io.anuke.mindustry.net.Net.client()" :
|
loc.isClient ? "io.anuke.mindustry.net.Net.client()" :
|
||||||
loc.isServer ? "io.anuke.mindustry.net.Net.server()" : "false";
|
loc.isServer ? "io.anuke.mindustry.net.Net.server()" : "false";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ import javax.lang.model.element.TypeElement;
|
|||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
import javax.lang.model.util.Types;
|
import javax.lang.model.util.Types;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils{
|
||||||
public static Types typeUtils;
|
public static Types typeUtils;
|
||||||
public static Elements elementUtils;
|
public static Elements elementUtils;
|
||||||
public static Filer filer;
|
public static Filer filer;
|
||||||
public static Messager messager;
|
public static Messager messager;
|
||||||
|
|
||||||
public static String getMethodName(Element element){
|
public static String getMethodName(Element element){
|
||||||
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
return ((TypeElement) element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isPrimitive(String type){
|
public static boolean isPrimitive(String type){
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module>
|
<module>
|
||||||
<source path="io/anuke/mindustry" />
|
<source path="io/anuke/mindustry"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Tile" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Tile"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.Content" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.Content"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.Maps" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.Maps"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Map" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.Map"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.SpawnGroup" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.SpawnGroup"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.core.GameState" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.core.GameState"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.EventType" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.EventType"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.SaveFileVersion" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.io.SaveFileVersion"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.ucore.entities.impl.EffectEntity" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.ucore.entities.impl.EffectEntity"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Packets" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Packets"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Packet" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Packet"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.effect" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.effect"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.bullet.Bullet" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.entities.bullet.Bullet"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.Team" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.game.Team"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Streamable" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.net.Streamable"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.meta.BlockBar" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.meta.BlockBar"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.mapgen.WorldGenerator" />
|
<extend-configuration-property name="gdx.reflect.include" value="io.anuke.mindustry.world.mapgen.WorldGenerator"/>
|
||||||
<extend-configuration-property name="gdx.reflect.include" value="com.badlogic.gdx.utils.Predicate" />
|
<extend-configuration-property name="gdx.reflect.include" value="com.badlogic.gdx.utils.Predicate"/>
|
||||||
</module>
|
</module>
|
||||||
@@ -8,35 +8,35 @@ import io.anuke.ucore.util.Log;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class Mindustry extends ModuleCore {
|
public class Mindustry extends ModuleCore{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
Timers.mark();
|
Timers.mark();
|
||||||
|
|
||||||
Vars.init();
|
Vars.init();
|
||||||
|
|
||||||
debug = Platform.instance.isDebug();
|
debug = Platform.instance.isDebug();
|
||||||
|
|
||||||
Log.setUseColors(false);
|
Log.setUseColors(false);
|
||||||
BundleLoader.load();
|
BundleLoader.load();
|
||||||
ContentLoader.load();
|
ContentLoader.load();
|
||||||
|
|
||||||
module(logic = new Logic());
|
module(logic = new Logic());
|
||||||
module(world = new World());
|
module(world = new World());
|
||||||
module(control = new Control());
|
module(control = new Control());
|
||||||
module(renderer = new Renderer());
|
module(renderer = new Renderer());
|
||||||
module(ui = new UI());
|
module(ui = new UI());
|
||||||
module(netServer = new NetServer());
|
module(netServer = new NetServer());
|
||||||
module(netClient = new NetClient());
|
module(netClient = new NetClient());
|
||||||
|
|
||||||
Log.info("Time to load [total]: {0}", Timers.elapsed());
|
Log.info("Time to load [total]: {0}", Timers.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(){
|
public void render(){
|
||||||
super.render();
|
super.render();
|
||||||
threads.handleRender();
|
threads.handleRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,173 +19,156 @@ import io.anuke.mindustry.io.Version;
|
|||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
import io.anuke.ucore.entities.EntityGroup;
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
import io.anuke.ucore.entities.trait.DrawTrait;
|
|
||||||
import io.anuke.ucore.entities.impl.EffectEntity;
|
import io.anuke.ucore.entities.impl.EffectEntity;
|
||||||
|
import io.anuke.ucore.entities.trait.DrawTrait;
|
||||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||||
import io.anuke.ucore.util.OS;
|
import io.anuke.ucore.util.OS;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class Vars{
|
public class Vars{
|
||||||
public static boolean testMobile;
|
//respawn time in frames
|
||||||
//shorthand for whether or not this is running on android or ios
|
public static final float respawnduration = 60 * 4;
|
||||||
public static boolean mobile;
|
//time between waves in frames (on normal mode)
|
||||||
public static boolean ios;
|
public static final float wavespace = 60 * 60 * 2f;
|
||||||
public static boolean android;
|
//waves can last no longer than 3 minutes, otherwise the next one spawns
|
||||||
//shorthand for whether or not this is running on GWT
|
public static final float maxwavespace = 60 * 60 * 4f;
|
||||||
public static boolean gwt;
|
//set ridiculously high for now
|
||||||
|
public static final float coreBuildRange = 800999f;
|
||||||
//respawn time in frames
|
//discord group URL
|
||||||
public static final float respawnduration = 60*4;
|
public static final String discordURL = "https://discord.gg/BKADYds";
|
||||||
//time between waves in frames (on normal mode)
|
public static final String releasesURL = "https://api.github.com/repos/Anuken/Mindustry/releases";
|
||||||
public static final float wavespace = 60*60*2f;
|
|
||||||
//waves can last no longer than 3 minutes, otherwise the next one spawns
|
|
||||||
public static final float maxwavespace = 60*60*4f;
|
|
||||||
|
|
||||||
//set ridiculously high for now
|
|
||||||
public static final float coreBuildRange = 800999f;
|
|
||||||
//discord group URL
|
|
||||||
public static final String discordURL = "https://discord.gg/BKADYds";
|
|
||||||
|
|
||||||
public static final String releasesURL = "https://api.github.com/repos/Anuken/Mindustry/releases";
|
|
||||||
|
|
||||||
//directory for user-created map data
|
|
||||||
public static FileHandle customMapDirectory;
|
|
||||||
//save file directory
|
|
||||||
public static FileHandle saveDirectory;
|
|
||||||
public static String mapExtension = "mmap";
|
|
||||||
public static String saveExtension = "msav";
|
|
||||||
//scale of the font
|
|
||||||
public static float fontScale;
|
|
||||||
//camera zoom displayed on startup
|
|
||||||
public static int baseCameraScale;
|
|
||||||
//if true, player speed will be increased, massive amounts of resources will be given on start, and other debug options will be available
|
|
||||||
public static boolean debug = false;
|
|
||||||
public static boolean console = false;
|
|
||||||
//whether the player can clip through walls
|
|
||||||
public static boolean noclip = false;
|
|
||||||
//whether turrets have infinite ammo (only with debug)
|
|
||||||
public static boolean infiniteAmmo = true;
|
|
||||||
//whether to show paths of enemies
|
|
||||||
public static boolean showPaths = false;
|
|
||||||
//if false, player is always hidden
|
|
||||||
public static boolean showPlayer = true;
|
|
||||||
//whether to hide ui, only on debug
|
|
||||||
public static boolean showUI = true;
|
|
||||||
//whether to show block debug
|
|
||||||
public static boolean showBlockDebug = false;
|
|
||||||
|
|
||||||
public static boolean showFog = true;
|
|
||||||
|
|
||||||
public static final int maxTextLength = 150;
|
public static final int maxTextLength = 150;
|
||||||
public static final int maxNameLength = 40;
|
public static final int maxNameLength = 40;
|
||||||
public static final int maxCharNameLength = 20;
|
public static final int maxCharNameLength = 20;
|
||||||
|
public static final int saveSlots = 64;
|
||||||
|
public static final float itemSize = 5f;
|
||||||
|
public static final int tilesize = 8;
|
||||||
|
public static final Locale[] locales = {new Locale("en"), new Locale("fr"), new Locale("ru"), new Locale("uk", "UA"), new Locale("pl"),
|
||||||
|
new Locale("de"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID"), new Locale("ita"), new Locale("es")};
|
||||||
|
public static final Color[] playerColors = {
|
||||||
|
Color.valueOf("82759a"),
|
||||||
|
Color.valueOf("c0c1c5"),
|
||||||
|
Color.valueOf("fff0e7"),
|
||||||
|
Color.valueOf("7d2953"),
|
||||||
|
Color.valueOf("ff074e"),
|
||||||
|
Color.valueOf("ff072a"),
|
||||||
|
Color.valueOf("ff76a6"),
|
||||||
|
Color.valueOf("a95238"),
|
||||||
|
Color.valueOf("ffa108"),
|
||||||
|
Color.valueOf("feeb2c"),
|
||||||
|
Color.valueOf("ffcaa8"),
|
||||||
|
Color.valueOf("008551"),
|
||||||
|
Color.valueOf("00e339"),
|
||||||
|
Color.valueOf("423c7b"),
|
||||||
|
Color.valueOf("4b5ef1"),
|
||||||
|
Color.valueOf("2cabfe"),
|
||||||
|
};
|
||||||
|
//server port
|
||||||
|
public static final int port = 6567;
|
||||||
|
public static final int webPort = 6568;
|
||||||
|
public static boolean testMobile;
|
||||||
|
//shorthand for whether or not this is running on android or ios
|
||||||
|
public static boolean mobile;
|
||||||
|
public static boolean ios;
|
||||||
|
public static boolean android;
|
||||||
|
//shorthand for whether or not this is running on GWT
|
||||||
|
public static boolean gwt;
|
||||||
|
//directory for user-created map data
|
||||||
|
public static FileHandle customMapDirectory;
|
||||||
|
//save file directory
|
||||||
|
public static FileHandle saveDirectory;
|
||||||
|
public static String mapExtension = "mmap";
|
||||||
|
public static String saveExtension = "msav";
|
||||||
|
//scale of the font
|
||||||
|
public static float fontScale;
|
||||||
|
//camera zoom displayed on startup
|
||||||
|
public static int baseCameraScale;
|
||||||
|
//if true, player speed will be increased, massive amounts of resources will be given on start, and other debug options will be available
|
||||||
|
public static boolean debug = false;
|
||||||
|
public static boolean console = false;
|
||||||
|
//whether the player can clip through walls
|
||||||
|
public static boolean noclip = false;
|
||||||
|
//whether turrets have infinite ammo (only with debug)
|
||||||
|
public static boolean infiniteAmmo = true;
|
||||||
|
//whether to show paths of enemies
|
||||||
|
public static boolean showPaths = false;
|
||||||
|
//if false, player is always hidden
|
||||||
|
public static boolean showPlayer = true;
|
||||||
|
//whether to hide ui, only on debug
|
||||||
|
public static boolean showUI = true;
|
||||||
|
//whether to show block debug
|
||||||
|
public static boolean showBlockDebug = false;
|
||||||
|
public static boolean showFog = true;
|
||||||
|
public static boolean headless = false;
|
||||||
|
public static float controllerMin = 0.25f;
|
||||||
|
public static float baseControllerSpeed = 11f;
|
||||||
|
//only if smoothCamera
|
||||||
|
public static boolean snapCamera = true;
|
||||||
|
public static GameState state;
|
||||||
|
public static ThreadHandler threads;
|
||||||
|
|
||||||
public static boolean headless = false;
|
public static Control control;
|
||||||
|
public static Logic logic;
|
||||||
|
public static Renderer renderer;
|
||||||
|
public static UI ui;
|
||||||
|
public static World world;
|
||||||
|
public static NetServer netServer;
|
||||||
|
public static NetClient netClient;
|
||||||
|
|
||||||
public static float controllerMin = 0.25f;
|
public static Player[] players = {};
|
||||||
|
|
||||||
public static float baseControllerSpeed = 11f;
|
public static EntityGroup<Player> playerGroup;
|
||||||
|
public static EntityGroup<TileEntity> tileGroup;
|
||||||
|
public static EntityGroup<Bullet> bulletGroup;
|
||||||
|
public static EntityGroup<Shield> shieldGroup;
|
||||||
|
public static EntityGroup<EffectEntity> effectGroup;
|
||||||
|
public static EntityGroup<DrawTrait> groundEffectGroup;
|
||||||
|
public static EntityGroup<ItemDrop> itemGroup;
|
||||||
|
|
||||||
public static final int saveSlots = 64;
|
public static EntityGroup<Puddle> puddleGroup;
|
||||||
|
public static EntityGroup<Fire> fireGroup;
|
||||||
|
public static EntityGroup<BaseUnit>[] unitGroups;
|
||||||
|
|
||||||
public static final float itemSize = 5f;
|
public static void init(){
|
||||||
|
Version.init();
|
||||||
|
|
||||||
//only if smoothCamera
|
playerGroup = Entities.addGroup(Player.class).enableMapping();
|
||||||
public static boolean snapCamera = true;
|
tileGroup = Entities.addGroup(TileEntity.class, false);
|
||||||
|
bulletGroup = Entities.addGroup(Bullet.class).enableMapping();
|
||||||
public static final int tilesize = 8;
|
shieldGroup = Entities.addGroup(Shield.class, false);
|
||||||
|
effectGroup = Entities.addGroup(EffectEntity.class, false);
|
||||||
|
groundEffectGroup = Entities.addGroup(DrawTrait.class, false);
|
||||||
|
puddleGroup = Entities.addGroup(Puddle.class, false).enableMapping();
|
||||||
|
itemGroup = Entities.addGroup(ItemDrop.class).enableMapping();
|
||||||
|
fireGroup = Entities.addGroup(Fire.class, false).enableMapping();
|
||||||
|
unitGroups = new EntityGroup[Team.all.length];
|
||||||
|
|
||||||
public static final Locale[] locales = {new Locale("en"), new Locale("fr"), new Locale("ru"), new Locale("uk", "UA"), new Locale("pl"),
|
for(Team team : Team.all){
|
||||||
new Locale("de"), new Locale("pt", "BR"), new Locale("ko"), new Locale("in", "ID"), new Locale("ita"), new Locale("es")};
|
unitGroups[team.ordinal()] = Entities.addGroup(BaseUnit.class).enableMapping();
|
||||||
|
}
|
||||||
|
|
||||||
public static final Color[] playerColors = {
|
for(EntityGroup<?> group : Entities.getAllGroups()){
|
||||||
Color.valueOf("82759a"),
|
group.setRemoveListener(entity -> {
|
||||||
Color.valueOf("c0c1c5"),
|
if(entity instanceof SyncTrait && Net.client()){
|
||||||
Color.valueOf("fff0e7"),
|
netClient.addRemovedEntity((entity).getID());
|
||||||
Color.valueOf("7d2953"),
|
}
|
||||||
Color.valueOf("ff074e"),
|
});
|
||||||
Color.valueOf("ff072a"),
|
}
|
||||||
Color.valueOf("ff76a6"),
|
|
||||||
Color.valueOf("a95238"),
|
|
||||||
Color.valueOf("ffa108"),
|
|
||||||
Color.valueOf("feeb2c"),
|
|
||||||
Color.valueOf("ffcaa8"),
|
|
||||||
Color.valueOf("008551"),
|
|
||||||
Color.valueOf("00e339"),
|
|
||||||
Color.valueOf("423c7b"),
|
|
||||||
Color.valueOf("4b5ef1"),
|
|
||||||
Color.valueOf("2cabfe"),
|
|
||||||
};
|
|
||||||
|
|
||||||
//server port
|
threads = new ThreadHandler(Platform.instance.getThreadProvider());
|
||||||
public static final int port = 6567;
|
|
||||||
public static final int webPort = 6568;
|
|
||||||
|
|
||||||
public static GameState state;
|
mobile = Gdx.app.getType() == ApplicationType.Android || Gdx.app.getType() == ApplicationType.iOS || testMobile;
|
||||||
public static ThreadHandler threads;
|
ios = Gdx.app.getType() == ApplicationType.iOS;
|
||||||
|
android = Gdx.app.getType() == ApplicationType.Android;
|
||||||
|
gwt = Gdx.app.getType() == ApplicationType.WebGL;
|
||||||
|
|
||||||
public static Control control;
|
if(!gwt){
|
||||||
public static Logic logic;
|
customMapDirectory = OS.getAppDataDirectory("Mindustry").child("maps/");
|
||||||
public static Renderer renderer;
|
saveDirectory = OS.getAppDataDirectory("Mindustry").child("saves/");
|
||||||
public static UI ui;
|
}
|
||||||
public static World world;
|
|
||||||
public static NetServer netServer;
|
|
||||||
public static NetClient netClient;
|
|
||||||
|
|
||||||
public static Player[] players = {};
|
|
||||||
|
|
||||||
public static EntityGroup<Player> playerGroup;
|
fontScale = Math.max(Unit.dp.scl(1f) / 2f, 0.5f);
|
||||||
public static EntityGroup<TileEntity> tileGroup;
|
baseCameraScale = Math.round(Unit.dp.scl(4));
|
||||||
public static EntityGroup<Bullet> bulletGroup;
|
}
|
||||||
public static EntityGroup<Shield> shieldGroup;
|
|
||||||
public static EntityGroup<EffectEntity> effectGroup;
|
|
||||||
public static EntityGroup<DrawTrait> groundEffectGroup;
|
|
||||||
public static EntityGroup<ItemDrop> itemGroup;
|
|
||||||
|
|
||||||
public static EntityGroup<Puddle> puddleGroup;
|
|
||||||
public static EntityGroup<Fire> fireGroup;
|
|
||||||
public static EntityGroup<BaseUnit>[] unitGroups;
|
|
||||||
|
|
||||||
public static void init(){
|
|
||||||
Version.init();
|
|
||||||
|
|
||||||
playerGroup = Entities.addGroup(Player.class).enableMapping();
|
|
||||||
tileGroup = Entities.addGroup(TileEntity.class, false);
|
|
||||||
bulletGroup = Entities.addGroup(Bullet.class).enableMapping();
|
|
||||||
shieldGroup = Entities.addGroup(Shield.class, false);
|
|
||||||
effectGroup = Entities.addGroup(EffectEntity.class, false);
|
|
||||||
groundEffectGroup = Entities.addGroup(DrawTrait.class, false);
|
|
||||||
puddleGroup = Entities.addGroup(Puddle.class, false).enableMapping();
|
|
||||||
itemGroup = Entities.addGroup(ItemDrop.class).enableMapping();
|
|
||||||
fireGroup = Entities.addGroup(Fire.class, false).enableMapping();
|
|
||||||
unitGroups = new EntityGroup[Team.all.length];
|
|
||||||
|
|
||||||
for(Team team : Team.all){
|
|
||||||
unitGroups[team.ordinal()] = Entities.addGroup(BaseUnit.class).enableMapping();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(EntityGroup<?> group : Entities.getAllGroups()){
|
|
||||||
group.setRemoveListener(entity -> {
|
|
||||||
if(entity instanceof SyncTrait && Net.client()){
|
|
||||||
netClient.addRemovedEntity((entity).getID());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
threads = new ThreadHandler(Platform.instance.getThreadProvider());
|
|
||||||
|
|
||||||
mobile = Gdx.app.getType() == ApplicationType.Android || Gdx.app.getType() == ApplicationType.iOS || testMobile;
|
|
||||||
ios = Gdx.app.getType() == ApplicationType.iOS;
|
|
||||||
android = Gdx.app.getType() == ApplicationType.Android;
|
|
||||||
gwt = Gdx.app.getType() == ApplicationType.WebGL;
|
|
||||||
|
|
||||||
if(!gwt) {
|
|
||||||
customMapDirectory = OS.getAppDataDirectory("Mindustry").child("maps/");
|
|
||||||
saveDirectory = OS.getAppDataDirectory("Mindustry").child("saves/");
|
|
||||||
}
|
|
||||||
|
|
||||||
fontScale = Math.max(Unit.dp.scl(1f)/2f, 0.5f);
|
|
||||||
baseCameraScale = Math.round(Unit.dp.scl(4));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,32 +26,53 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
|
|
||||||
//TODO consider using quadtrees for finding specific types of blocks within an area
|
//TODO consider using quadtrees for finding specific types of blocks within an area
|
||||||
//TODO maybe use Arrays instead of ObjectSets?
|
//TODO maybe use Arrays instead of ObjectSets?
|
||||||
/**Class used for indexing special target blocks for AI.*/
|
|
||||||
public class BlockIndexer {
|
/**
|
||||||
/**Size of one ore quadrant.*/
|
* Class used for indexing special target blocks for AI.
|
||||||
|
*/
|
||||||
|
public class BlockIndexer{
|
||||||
|
/**
|
||||||
|
* Size of one ore quadrant.
|
||||||
|
*/
|
||||||
private final static int oreQuadrantSize = 20;
|
private final static int oreQuadrantSize = 20;
|
||||||
/**Size of one structure quadrant.*/
|
/**
|
||||||
|
* Size of one structure quadrant.
|
||||||
|
*/
|
||||||
private final static int structQuadrantSize = 12;
|
private final static int structQuadrantSize = 12;
|
||||||
|
|
||||||
/**Set of all ores that are being scanned.*/
|
/**
|
||||||
|
* Set of all ores that are being scanned.
|
||||||
|
*/
|
||||||
private final ObjectSet<Item> scanOres = ObjectSet.with(Items.tungsten, Items.coal, Items.lead, Items.thorium, Items.titanium);
|
private final ObjectSet<Item> scanOres = ObjectSet.with(Items.tungsten, Items.coal, Items.lead, Items.thorium, Items.titanium);
|
||||||
/**Stores all ore quadtrants on the map.*/
|
|
||||||
private ObjectMap<Item, ObjectSet<Tile>> ores;
|
|
||||||
|
|
||||||
private final ObjectSet<Item> itemSet = new ObjectSet<>();
|
private final ObjectSet<Item> itemSet = new ObjectSet<>();
|
||||||
|
/**
|
||||||
/**Tags all quadrants.*/
|
* Stores all ore quadtrants on the map.
|
||||||
|
*/
|
||||||
|
private ObjectMap<Item, ObjectSet<Tile>> ores;
|
||||||
|
/**
|
||||||
|
* Tags all quadrants.
|
||||||
|
*/
|
||||||
private Bits[] structQuadrants;
|
private Bits[] structQuadrants;
|
||||||
|
|
||||||
/**Maps teams to a map of flagged tiles by type.*/
|
/**
|
||||||
|
* Maps teams to a map of flagged tiles by type.
|
||||||
|
*/
|
||||||
private ObjectMap<BlockFlag, ObjectSet<Tile>> enemyMap = new ObjectMap<>();
|
private ObjectMap<BlockFlag, ObjectSet<Tile>> enemyMap = new ObjectMap<>();
|
||||||
/**Maps teams to a map of flagged tiles by type.*/
|
/**
|
||||||
|
* Maps teams to a map of flagged tiles by type.
|
||||||
|
*/
|
||||||
private ObjectMap<BlockFlag, ObjectSet<Tile>> allyMap = new ObjectMap<>();
|
private ObjectMap<BlockFlag, ObjectSet<Tile>> allyMap = new ObjectMap<>();
|
||||||
/**Empty map for invalid teams.*/
|
/**
|
||||||
|
* Empty map for invalid teams.
|
||||||
|
*/
|
||||||
private ObjectMap<BlockFlag, ObjectSet<Tile>> emptyMap = new ObjectMap<>();
|
private ObjectMap<BlockFlag, ObjectSet<Tile>> emptyMap = new ObjectMap<>();
|
||||||
/**Maps tile positions to their last known tile index data.*/
|
/**
|
||||||
|
* Maps tile positions to their last known tile index data.
|
||||||
|
*/
|
||||||
private IntMap<TileIndex> typeMap = new IntMap<>();
|
private IntMap<TileIndex> typeMap = new IntMap<>();
|
||||||
/**Empty array used for returning.*/
|
/**
|
||||||
|
* Empty array used for returning.
|
||||||
|
*/
|
||||||
private ObjectSet<Tile> emptyArray = new ObjectSet<>();
|
private ObjectSet<Tile> emptyArray = new ObjectSet<>();
|
||||||
|
|
||||||
public BlockIndexer(){
|
public BlockIndexer(){
|
||||||
@@ -74,18 +95,18 @@ public class BlockIndexer {
|
|||||||
|
|
||||||
//create bitset for each team type that contains each quadrant
|
//create bitset for each team type that contains each quadrant
|
||||||
structQuadrants = new Bits[Team.all.length];
|
structQuadrants = new Bits[Team.all.length];
|
||||||
for(int i = 0; i < Team.all.length; i ++){
|
for(int i = 0; i < Team.all.length; i++){
|
||||||
structQuadrants[i] = new Bits(Mathf.ceil(world.width() / (float)structQuadrantSize) * Mathf.ceil(world.height() / (float)structQuadrantSize));
|
structQuadrants[i] = new Bits(Mathf.ceil(world.width() / (float) structQuadrantSize) * Mathf.ceil(world.height() / (float) structQuadrantSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < world.width(); x ++){
|
for(int x = 0; x < world.width(); x++){
|
||||||
for (int y = 0; y < world.height(); y++) {
|
for(int y = 0; y < world.height(); y++){
|
||||||
process(world.tile(x, y));
|
process(world.tile(x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int x = 0; x < quadWidth(); x++) {
|
for(int x = 0; x < quadWidth(); x++){
|
||||||
for (int y = 0; y < quadHeight(); y++) {
|
for(int y = 0; y < quadHeight(); y++){
|
||||||
updateQuadrant(world.tile(x * structQuadrantSize, y * structQuadrantSize));
|
updateQuadrant(world.tile(x * structQuadrantSize, y * structQuadrantSize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,12 +115,16 @@ public class BlockIndexer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Get all allied blocks with a flag.*/
|
/**
|
||||||
|
* Get all allied blocks with a flag.
|
||||||
|
*/
|
||||||
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
||||||
return (state.teams.get(team).ally ? allyMap : enemyMap).get(type, emptyArray);
|
return (state.teams.get(team).ally ? allyMap : enemyMap).get(type, emptyArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Get all enemy blocks with a flag.*/
|
/**
|
||||||
|
* Get all enemy blocks with a flag.
|
||||||
|
*/
|
||||||
public ObjectSet<Tile> getEnemy(Team team, BlockFlag type){
|
public ObjectSet<Tile> getEnemy(Team team, BlockFlag type){
|
||||||
return (!state.teams.get(team).ally ? allyMap : enemyMap).get(type, emptyArray);
|
return (!state.teams.get(team).ally ? allyMap : enemyMap).get(type, emptyArray);
|
||||||
}
|
}
|
||||||
@@ -108,13 +133,13 @@ public class BlockIndexer {
|
|||||||
Entity closest = null;
|
Entity closest = null;
|
||||||
float dst = 0;
|
float dst = 0;
|
||||||
|
|
||||||
for(int rx = Math.max((int)((x-range)/tilesize/structQuadrantSize), 0); rx <= (int)((x+range)/tilesize/structQuadrantSize) && rx < quadWidth(); rx ++){
|
for(int rx = Math.max((int) ((x - range) / tilesize / structQuadrantSize), 0); rx <= (int) ((x + range) / tilesize / structQuadrantSize) && rx < quadWidth(); rx++){
|
||||||
for(int ry = Math.max((int)((y-range)/tilesize/structQuadrantSize), 0); ry <= (int)((y+range)/tilesize/structQuadrantSize) && ry < quadHeight(); ry ++){
|
for(int ry = Math.max((int) ((y - range) / tilesize / structQuadrantSize), 0); ry <= (int) ((y + range) / tilesize / structQuadrantSize) && ry < quadHeight(); ry++){
|
||||||
|
|
||||||
if(!getQuad(team, rx, ry)) continue;
|
if(!getQuad(team, rx, ry)) continue;
|
||||||
|
|
||||||
for(int tx = rx * structQuadrantSize; tx < (rx + 1) * structQuadrantSize && tx < world.width(); tx ++){
|
for(int tx = rx * structQuadrantSize; tx < (rx + 1) * structQuadrantSize && tx < world.width(); tx++){
|
||||||
for(int ty = ry * structQuadrantSize; ty < (ry + 1) * structQuadrantSize && ty < world.height(); ty ++ ){
|
for(int ty = ry * structQuadrantSize; ty < (ry + 1) * structQuadrantSize && ty < world.height(); ty++){
|
||||||
Tile other = world.tile(tx, ty);
|
Tile other = world.tile(tx, ty);
|
||||||
|
|
||||||
if(other == null || other.entity == null || !pred.test(other)) continue;
|
if(other == null || other.entity == null || !pred.test(other)) continue;
|
||||||
@@ -134,22 +159,26 @@ public class BlockIndexer {
|
|||||||
return (TileEntity) closest;
|
return (TileEntity) closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns a set of tiles that have ores of the specified type nearby.
|
/**
|
||||||
|
* Returns a set of tiles that have ores of the specified type nearby.
|
||||||
* While each tile in the set is not guaranteed to have an ore directly on it,
|
* While each tile in the set is not guaranteed to have an ore directly on it,
|
||||||
* each tile will at least have an ore within {@link #oreQuadrantSize} / 2 blocks of it.
|
* each tile will at least have an ore within {@link #oreQuadrantSize} / 2 blocks of it.
|
||||||
* Only specific ore types are scanned. See {@link #scanOres}.*/
|
* Only specific ore types are scanned. See {@link #scanOres}.
|
||||||
|
*/
|
||||||
public ObjectSet<Tile> getOrePositions(Item item){
|
public ObjectSet<Tile> getOrePositions(Item item){
|
||||||
return ores.get(item, emptyArray);
|
return ores.get(item, emptyArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Find the closest ore block relative to a position.*/
|
/**
|
||||||
|
* Find the closest ore block relative to a position.
|
||||||
|
*/
|
||||||
public Tile findClosestOre(float xp, float yp, Item item){
|
public Tile findClosestOre(float xp, float yp, Item item){
|
||||||
Tile tile = Geometry.findClosest(xp, yp, world.indexer().getOrePositions(item));
|
Tile tile = Geometry.findClosest(xp, yp, world.indexer().getOrePositions(item));
|
||||||
|
|
||||||
if(tile == null) return null;
|
if(tile == null) return null;
|
||||||
|
|
||||||
for (int x = Math.max(0, tile.x - oreQuadrantSize/2); x < tile.x + oreQuadrantSize/2 && x < world.width(); x++) {
|
for(int x = Math.max(0, tile.x - oreQuadrantSize / 2); x < tile.x + oreQuadrantSize / 2 && x < world.width(); x++){
|
||||||
for (int y = Math.max(0, tile.y - oreQuadrantSize/2); y < tile.y + oreQuadrantSize/2 && y < world.height(); y++) {
|
for(int y = Math.max(0, tile.y - oreQuadrantSize / 2); y < tile.y + oreQuadrantSize / 2 && y < world.height(); y++){
|
||||||
Tile res = world.tile(x, y);
|
Tile res = world.tile(x, y);
|
||||||
if(res.block() == Blocks.air && res.floor().drops != null && res.floor().drops.item == item){
|
if(res.block() == Blocks.air && res.floor().drops != null && res.floor().drops.item == item){
|
||||||
return res;
|
return res;
|
||||||
@@ -186,12 +215,12 @@ public class BlockIndexer {
|
|||||||
int quadrantY = tile.y / oreQuadrantSize;
|
int quadrantY = tile.y / oreQuadrantSize;
|
||||||
itemSet.clear();
|
itemSet.clear();
|
||||||
|
|
||||||
Tile rounded = world.tile(Mathf.clamp(quadrantX * oreQuadrantSize + oreQuadrantSize /2, 0, world.width() - 1),
|
Tile rounded = world.tile(Mathf.clamp(quadrantX * oreQuadrantSize + oreQuadrantSize / 2, 0, world.width() - 1),
|
||||||
Mathf.clamp(quadrantY * oreQuadrantSize + oreQuadrantSize /2, 0, world.height() - 1));
|
Mathf.clamp(quadrantY * oreQuadrantSize + oreQuadrantSize / 2, 0, world.height() - 1));
|
||||||
|
|
||||||
//find all items that this quadrant contains
|
//find all items that this quadrant contains
|
||||||
for (int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++) {
|
for(int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++){
|
||||||
for (int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++) {
|
for(int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++){
|
||||||
Tile result = world.tile(x, y);
|
Tile result = world.tile(x, y);
|
||||||
if(result.block().drops == null || !scanOres.contains(result.block().drops.item)) continue;
|
if(result.block().drops == null || !scanOres.contains(result.block().drops.item)) continue;
|
||||||
|
|
||||||
@@ -200,7 +229,7 @@ public class BlockIndexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//update quadrant at this position
|
//update quadrant at this position
|
||||||
for (Item item : scanOres){
|
for(Item item : scanOres){
|
||||||
ObjectSet<Tile> set = ores.get(item);
|
ObjectSet<Tile> set = ores.get(item);
|
||||||
|
|
||||||
//update quadrant status depending on whether the item is in it
|
//update quadrant status depending on whether the item is in it
|
||||||
@@ -219,7 +248,7 @@ public class BlockIndexer {
|
|||||||
int index = quadrantX + quadrantY * quadWidth();
|
int index = quadrantX + quadrantY * quadWidth();
|
||||||
//Log.info("Updating quadrant: {0} {1}", quadrantX, quadrantY);
|
//Log.info("Updating quadrant: {0} {1}", quadrantX, quadrantY);
|
||||||
|
|
||||||
for(TeamData data : state.teams.getTeams()) {
|
for(TeamData data : state.teams.getTeams()){
|
||||||
|
|
||||||
//fast-set this quadrant to 'occupied' if the tile just placed is already of this team
|
//fast-set this quadrant to 'occupied' if the tile just placed is already of this team
|
||||||
if(tile.getTeam() == data.team && tile.entity != null){
|
if(tile.getTeam() == data.team && tile.entity != null){
|
||||||
@@ -230,8 +259,8 @@ public class BlockIndexer {
|
|||||||
structQuadrants[data.team.ordinal()].clear(index);
|
structQuadrants[data.team.ordinal()].clear(index);
|
||||||
|
|
||||||
outer:
|
outer:
|
||||||
for (int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++) {
|
for(int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++){
|
||||||
for (int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++) {
|
for(int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++){
|
||||||
Tile result = world.tile(x, y);
|
Tile result = world.tile(x, y);
|
||||||
//when a targetable block is found, mark this quadrant as occupied and stop searching
|
//when a targetable block is found, mark this quadrant as occupied and stop searching
|
||||||
if(result.entity != null && result.getTeam() == data.team){
|
if(result.entity != null && result.getTeam() == data.team){
|
||||||
@@ -244,16 +273,16 @@ public class BlockIndexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean getQuad(Team team, int quadrantX, int quadrantY){
|
private boolean getQuad(Team team, int quadrantX, int quadrantY){
|
||||||
int index = quadrantX + quadrantY * Mathf.ceil(world.width() / (float)structQuadrantSize);
|
int index = quadrantX + quadrantY * Mathf.ceil(world.width() / (float) structQuadrantSize);
|
||||||
return structQuadrants[team.ordinal()].get(index);
|
return structQuadrants[team.ordinal()].get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int quadWidth(){
|
private int quadWidth(){
|
||||||
return Mathf.ceil(world.width() / (float)structQuadrantSize);
|
return Mathf.ceil(world.width() / (float) structQuadrantSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int quadHeight(){
|
private int quadHeight(){
|
||||||
return Mathf.ceil(world.height() / (float)structQuadrantSize);
|
return Mathf.ceil(world.height() / (float) structQuadrantSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectMap<BlockFlag, ObjectSet<Tile>> getMap(Team team){
|
private ObjectMap<BlockFlag, ObjectSet<Tile>> getMap(Team team){
|
||||||
@@ -269,10 +298,10 @@ public class BlockIndexer {
|
|||||||
ores.put(item, new ObjectSet<>());
|
ores.put(item, new ObjectSet<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = 0; x < world.width(); x ++){
|
for(int x = 0; x < world.width(); x++){
|
||||||
for (int y = 0; y < world.height(); y++) {
|
for(int y = 0; y < world.height(); y++){
|
||||||
int qx = (x/ oreQuadrantSize);
|
int qx = (x / oreQuadrantSize);
|
||||||
int qy = (y/ oreQuadrantSize);
|
int qy = (y / oreQuadrantSize);
|
||||||
|
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
|
|
||||||
@@ -280,8 +309,8 @@ public class BlockIndexer {
|
|||||||
if(tile.floor().drops != null && scanOres.contains(tile.floor().drops.item) && tile.block() == Blocks.air){
|
if(tile.floor().drops != null && scanOres.contains(tile.floor().drops.item) && tile.block() == Blocks.air){
|
||||||
ores.get(tile.floor().drops.item).add(world.tile(
|
ores.get(tile.floor().drops.item).add(world.tile(
|
||||||
//make sure to clamp quadrant middle position, since it might go off bounds
|
//make sure to clamp quadrant middle position, since it might go off bounds
|
||||||
Mathf.clamp(qx * oreQuadrantSize + oreQuadrantSize /2, 0, world.width() - 1),
|
Mathf.clamp(qx * oreQuadrantSize + oreQuadrantSize / 2, 0, world.width() - 1),
|
||||||
Mathf.clamp(qy * oreQuadrantSize + oreQuadrantSize /2, 0, world.height() - 1)));
|
Mathf.clamp(qy * oreQuadrantSize + oreQuadrantSize / 2, 0, world.height() - 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,7 +320,7 @@ public class BlockIndexer {
|
|||||||
public final EnumSet<BlockFlag> flags;
|
public final EnumSet<BlockFlag> flags;
|
||||||
public final Team team;
|
public final Team team;
|
||||||
|
|
||||||
public TileIndex(EnumSet<BlockFlag> flags, Team team) {
|
public TileIndex(EnumSet<BlockFlag> flags, Team team){
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
this.team = team;
|
this.team = team;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import io.anuke.ucore.util.Log;
|
|||||||
import static io.anuke.mindustry.Vars.state;
|
import static io.anuke.mindustry.Vars.state;
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class Pathfinder {
|
public class Pathfinder{
|
||||||
private long maxUpdate = TimeUtils.millisToNanos(4);
|
private long maxUpdate = TimeUtils.millisToNanos(4);
|
||||||
private PathData[] paths;
|
private PathData[] paths;
|
||||||
private IntArray blocked = new IntArray();
|
private IntArray blocked = new IntArray();
|
||||||
@@ -56,7 +56,7 @@ public class Pathfinder {
|
|||||||
|
|
||||||
Tile target = null;
|
Tile target = null;
|
||||||
float tl = 0f;
|
float tl = 0f;
|
||||||
for(GridPoint2 point : Geometry.d8) {
|
for(GridPoint2 point : Geometry.d8){
|
||||||
int dx = tile.x + point.x, dy = tile.y + point.y;
|
int dx = tile.x + point.x, dy = tile.y + point.y;
|
||||||
|
|
||||||
Tile other = world.tile(dx, dy);
|
Tile other = world.tile(dx, dy);
|
||||||
@@ -89,16 +89,16 @@ public class Pathfinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void update(Tile tile, Team team){
|
private void update(Tile tile, Team team){
|
||||||
if(paths[team.ordinal()] != null) {
|
if(paths[team.ordinal()] != null){
|
||||||
PathData path = paths[team.ordinal()];
|
PathData path = paths[team.ordinal()];
|
||||||
|
|
||||||
if(!passable(tile, team)){
|
if(!passable(tile, team)){
|
||||||
path.weights[tile.x][tile.y] = Float.MAX_VALUE;
|
path.weights[tile.x][tile.y] = Float.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
path.search ++;
|
path.search++;
|
||||||
|
|
||||||
if(path.lastSearchTime + 1000/60*3 > TimeUtils.millis()){
|
if(path.lastSearchTime + 1000 / 60 * 3 > TimeUtils.millis()){
|
||||||
path.frontier.clear();
|
path.frontier.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,17 +115,17 @@ public class Pathfinder {
|
|||||||
|
|
||||||
private void createFor(Team team){
|
private void createFor(Team team){
|
||||||
PathData path = new PathData();
|
PathData path = new PathData();
|
||||||
path.search ++;
|
path.search++;
|
||||||
path.frontier.ensureCapacity((world.width() + world.height()) * 3);
|
path.frontier.ensureCapacity((world.width() + world.height()) * 3);
|
||||||
|
|
||||||
paths[team.ordinal()] = path;
|
paths[team.ordinal()] = path;
|
||||||
|
|
||||||
for (int x = 0; x < world.width(); x++) {
|
for(int x = 0; x < world.width(); x++){
|
||||||
for (int y = 0; y < world.height(); y++) {
|
for(int y = 0; y < world.height(); y++){
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
|
|
||||||
if (tile.block().flags != null && state.teams.areEnemies(tile.getTeam(), team)
|
if(tile.block().flags != null && state.teams.areEnemies(tile.getTeam(), team)
|
||||||
&& tile.block().flags.contains(BlockFlag.target)) {
|
&& tile.block().flags.contains(BlockFlag.target)){
|
||||||
path.frontier.addFirst(tile);
|
path.frontier.addFirst(tile);
|
||||||
path.weights[x][y] = 0;
|
path.weights[x][y] = 0;
|
||||||
path.searches[x][y] = path.search;
|
path.searches[x][y] = path.search;
|
||||||
@@ -143,20 +143,20 @@ public class Pathfinder {
|
|||||||
|
|
||||||
long start = TimeUtils.nanoTime();
|
long start = TimeUtils.nanoTime();
|
||||||
|
|
||||||
while (path.frontier.size > 0 && (nsToRun < 0 || TimeUtils.timeSinceNanos(start) <= nsToRun)) {
|
while(path.frontier.size > 0 && (nsToRun < 0 || TimeUtils.timeSinceNanos(start) <= nsToRun)){
|
||||||
Tile tile = path.frontier.removeLast();
|
Tile tile = path.frontier.removeLast();
|
||||||
float cost = path.weights[tile.x][tile.y];
|
float cost = path.weights[tile.x][tile.y];
|
||||||
|
|
||||||
if (cost < Float.MAX_VALUE) {
|
if(cost < Float.MAX_VALUE){
|
||||||
for (GridPoint2 point : Geometry.d4) {
|
for(GridPoint2 point : Geometry.d4){
|
||||||
|
|
||||||
int dx = tile.x + point.x, dy = tile.y + point.y;
|
int dx = tile.x + point.x, dy = tile.y + point.y;
|
||||||
Tile other = world.tile(dx, dy);
|
Tile other = world.tile(dx, dy);
|
||||||
|
|
||||||
if (other != null && (path.weights[dx][dy] > cost + 1 || path.searches[dx][dy] < path.search)
|
if(other != null && (path.weights[dx][dy] > cost + 1 || path.searches[dx][dy] < path.search)
|
||||||
&& passable(other, team)){
|
&& passable(other, team)){
|
||||||
path.frontier.addFirst(world.tile(dx, dy));
|
path.frontier.addFirst(world.tile(dx, dy));
|
||||||
path.weights[dx][dy] = cost + other.cost/2f;
|
path.weights[dx][dy] = cost + other.cost / 2f;
|
||||||
path.searches[dx][dy] = path.search;
|
path.searches[dx][dy] = path.search;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class WaveSpawner {
|
public class WaveSpawner{
|
||||||
private static final int quadsize = 4;
|
private static final int quadsize = 4;
|
||||||
|
|
||||||
private Bits quadrants;
|
private Bits quadrants;
|
||||||
@@ -34,28 +34,28 @@ public class WaveSpawner {
|
|||||||
|
|
||||||
public void write(DataOutput output) throws IOException{
|
public void write(DataOutput output) throws IOException{
|
||||||
output.writeShort(flySpawns.size);
|
output.writeShort(flySpawns.size);
|
||||||
for (FlyerSpawn spawn : flySpawns){
|
for(FlyerSpawn spawn : flySpawns){
|
||||||
output.writeFloat(spawn.angle);
|
output.writeFloat(spawn.angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
output.writeShort(groundSpawns.size);
|
output.writeShort(groundSpawns.size);
|
||||||
for (GroundSpawn spawn : groundSpawns){
|
for(GroundSpawn spawn : groundSpawns){
|
||||||
output.writeShort((short)spawn.x);
|
output.writeShort((short) spawn.x);
|
||||||
output.writeShort((short)spawn.y);
|
output.writeShort((short) spawn.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void read(DataInput input) throws IOException{
|
public void read(DataInput input) throws IOException{
|
||||||
short flya = input.readShort();
|
short flya = input.readShort();
|
||||||
|
|
||||||
for (int i = 0; i < flya; i++) {
|
for(int i = 0; i < flya; i++){
|
||||||
FlyerSpawn spawn = new FlyerSpawn();
|
FlyerSpawn spawn = new FlyerSpawn();
|
||||||
spawn.angle = input.readFloat();
|
spawn.angle = input.readFloat();
|
||||||
flySpawns.add(spawn);
|
flySpawns.add(spawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
short grounda = input.readShort();
|
short grounda = input.readShort();
|
||||||
for (int i = 0; i < grounda; i++) {
|
for(int i = 0; i < grounda; i++){
|
||||||
GroundSpawn spawn = new GroundSpawn();
|
GroundSpawn spawn = new GroundSpawn();
|
||||||
spawn.x = input.readShort();
|
spawn.x = input.readShort();
|
||||||
spawn.y = input.readShort();
|
spawn.y = input.readShort();
|
||||||
@@ -80,13 +80,13 @@ public class WaveSpawner {
|
|||||||
int addGround = groundGroups - groundSpawns.size, addFly = flyGroups - flySpawns.size;
|
int addGround = groundGroups - groundSpawns.size, addFly = flyGroups - flySpawns.size;
|
||||||
|
|
||||||
//add extra groups if the total exceeds it
|
//add extra groups if the total exceeds it
|
||||||
for (int i = 0; i < addGround; i++) {
|
for(int i = 0; i < addGround; i++){
|
||||||
GroundSpawn spawn = new GroundSpawn();
|
GroundSpawn spawn = new GroundSpawn();
|
||||||
findLocation(spawn);
|
findLocation(spawn);
|
||||||
groundSpawns.add(spawn);
|
groundSpawns.add(spawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < addFly; i++) {
|
for(int i = 0; i < addFly; i++){
|
||||||
FlyerSpawn spawn = new FlyerSpawn();
|
FlyerSpawn spawn = new FlyerSpawn();
|
||||||
findLocation(spawn);
|
findLocation(spawn);
|
||||||
flySpawns.add(spawn);
|
flySpawns.add(spawn);
|
||||||
@@ -99,7 +99,7 @@ public class WaveSpawner {
|
|||||||
int groups = group.getGroupsSpawned(state.wave);
|
int groups = group.getGroupsSpawned(state.wave);
|
||||||
int spawned = group.getUnitsSpawned(state.wave);
|
int spawned = group.getUnitsSpawned(state.wave);
|
||||||
|
|
||||||
for (int i = 0; i < groups; i++) {
|
for(int i = 0; i < groups; i++){
|
||||||
Squad squad = new Squad();
|
Squad squad = new Squad();
|
||||||
float spawnX, spawnY;
|
float spawnX, spawnY;
|
||||||
float spread;
|
float spread;
|
||||||
@@ -109,11 +109,11 @@ public class WaveSpawner {
|
|||||||
//TODO verify flyer spawn
|
//TODO verify flyer spawn
|
||||||
|
|
||||||
float margin = 40f; //how far away from the edge flying units spawn
|
float margin = 40f; //how far away from the edge flying units spawn
|
||||||
spawnX = world.width() *tilesize/2f + Mathf.sqrwavex(spawn.angle) * (world.width()/2f*tilesize + margin);
|
spawnX = world.width() * tilesize / 2f + Mathf.sqrwavex(spawn.angle) * (world.width() / 2f * tilesize + margin);
|
||||||
spawnY = world.height() * tilesize/2f + Mathf.sqrwavey(spawn.angle) * (world.height()/2f*tilesize + margin);
|
spawnY = world.height() * tilesize / 2f + Mathf.sqrwavey(spawn.angle) * (world.height() / 2f * tilesize + margin);
|
||||||
spread = margin / 1.5f;
|
spread = margin / 1.5f;
|
||||||
|
|
||||||
flyCount ++;
|
flyCount++;
|
||||||
}else{
|
}else{
|
||||||
GroundSpawn spawn = groundSpawns.get(groundCount);
|
GroundSpawn spawn = groundSpawns.get(groundCount);
|
||||||
checkQuadrant(spawn.x, spawn.y);
|
checkQuadrant(spawn.x, spawn.y);
|
||||||
@@ -121,14 +121,14 @@ public class WaveSpawner {
|
|||||||
findLocation(spawn);
|
findLocation(spawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
spawnX = spawn.x * quadsize * tilesize + quadsize * tilesize/2f;
|
spawnX = spawn.x * quadsize * tilesize + quadsize * tilesize / 2f;
|
||||||
spawnY = spawn.y * quadsize * tilesize + quadsize * tilesize/2f;
|
spawnY = spawn.y * quadsize * tilesize + quadsize * tilesize / 2f;
|
||||||
spread = quadsize*tilesize/3f;
|
spread = quadsize * tilesize / 3f;
|
||||||
|
|
||||||
groundCount ++;
|
groundCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < spawned; j++) {
|
for(int j = 0; j < spawned; j++){
|
||||||
BaseUnit unit = group.createUnit(Team.red);
|
BaseUnit unit = group.createUnit(Team.red);
|
||||||
unit.setWave();
|
unit.setWave();
|
||||||
unit.setSquad(squad);
|
unit.setSquad(squad);
|
||||||
@@ -140,19 +140,19 @@ public class WaveSpawner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void checkAllQuadrants(){
|
public void checkAllQuadrants(){
|
||||||
for(int x = 0; x < quadWidth(); x ++){
|
for(int x = 0; x < quadWidth(); x++){
|
||||||
for(int y = 0; y < quadHeight(); y ++){
|
for(int y = 0; y < quadHeight(); y++){
|
||||||
checkQuadrant(x, y);
|
checkQuadrant(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkQuadrant(int quadx, int quady){
|
private void checkQuadrant(int quadx, int quady){
|
||||||
setQuad(quadx, quady, true);
|
setQuad(quadx, quady, true);
|
||||||
|
|
||||||
outer:
|
outer:
|
||||||
for (int x = quadx * quadsize; x < world.width() && x < (quadx + 1)*quadsize; x++) {
|
for(int x = quadx * quadsize; x < world.width() && x < (quadx + 1) * quadsize; x++){
|
||||||
for (int y = quady * quadsize; y < world.height() && y < (quady + 1)*quadsize; y++) {
|
for(int y = quady * quadsize; y < world.height() && y < (quady + 1) * quadsize; y++){
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
|
|
||||||
if(tile == null || tile.solid() || world.pathfinder().getValueforTeam(Team.red, x, y) == Float.MAX_VALUE){
|
if(tile == null || tile.solid() || world.pathfinder().getValueforTeam(Team.red, x, y) == Float.MAX_VALUE){
|
||||||
@@ -190,7 +190,7 @@ public class WaveSpawner {
|
|||||||
spawn.x = -1;
|
spawn.x = -1;
|
||||||
spawn.y = -1;
|
spawn.y = -1;
|
||||||
|
|
||||||
int shellWidth = quadWidth()*2 + quadHeight() * 2 * 6;
|
int shellWidth = quadWidth() * 2 + quadHeight() * 2 * 6;
|
||||||
shellWidth = Math.min(quadWidth() * quadHeight() / 4, shellWidth);
|
shellWidth = Math.min(quadWidth() * quadHeight() / 4, shellWidth);
|
||||||
|
|
||||||
Mathf.traverseSpiral(quadWidth(), quadHeight(), Mathf.random(shellWidth), (x, y) -> {
|
Mathf.traverseSpiral(quadWidth(), quadHeight(), Mathf.random(shellWidth), (x, y) -> {
|
||||||
@@ -210,11 +210,11 @@ public class WaveSpawner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int quadWidth(){
|
private int quadWidth(){
|
||||||
return Mathf.ceil(world.width() / (float)quadsize);
|
return Mathf.ceil(world.width() / (float) quadsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int quadHeight(){
|
private int quadHeight(){
|
||||||
return Mathf.ceil(world.height() / (float)quadsize);
|
return Mathf.ceil(world.height() / (float) quadsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FlyerSpawn{
|
private class FlyerSpawn{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import io.anuke.mindustry.game.Content;
|
|||||||
import io.anuke.mindustry.type.AmmoType;
|
import io.anuke.mindustry.type.AmmoType;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
|
|
||||||
public class AmmoTypes implements ContentList {
|
public class AmmoTypes implements ContentList{
|
||||||
public static AmmoType bulletTungsten, bulletLead, bulletCarbide, bulletThorium, bulletSilicon, bulletPyratite,
|
public static AmmoType bulletTungsten, bulletLead, bulletCarbide, bulletThorium, bulletSilicon, bulletPyratite,
|
||||||
shotgunTungsten, bombExplosive, bombIncendiary, bombOil, shellCarbide, flamerThermite, weaponMissile,
|
shotgunTungsten, bombExplosive, bombIncendiary, bombOil, shellCarbide, flamerThermite, weaponMissile,
|
||||||
flakLead, flakExplosive, flakPlastic, flakSurge, missileExplosive, missileIncindiary, missileSurge,
|
flakLead, flakExplosive, flakPlastic, flakSurge, missileExplosive, missileIncindiary, missileSurge,
|
||||||
@@ -17,41 +17,41 @@ public class AmmoTypes implements ContentList {
|
|||||||
basicFlame, lancerLaser, lightning, spectreLaser, meltdownLaser, fuseShotgun, oil, water, lava, cryofluid;
|
basicFlame, lancerLaser, lightning, spectreLaser, meltdownLaser, fuseShotgun, oil, water, lava, cryofluid;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
//weapon specific
|
//weapon specific
|
||||||
|
|
||||||
shotgunTungsten = new AmmoType(Items.tungsten, WeaponBullets.tungstenShotgun, 2) {{
|
shotgunTungsten = new AmmoType(Items.tungsten, WeaponBullets.tungstenShotgun, 2){{
|
||||||
shootEffect = ShootFx.shootBig;
|
shootEffect = ShootFx.shootBig;
|
||||||
smokeEffect = ShootFx.shootBigSmoke;
|
smokeEffect = ShootFx.shootBigSmoke;
|
||||||
recoil = 1f;
|
recoil = 1f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
shellCarbide = new AmmoType(Items.carbide, WeaponBullets.shellCarbide, 2) {{
|
shellCarbide = new AmmoType(Items.carbide, WeaponBullets.shellCarbide, 2){{
|
||||||
shootEffect = ShootFx.shootBig;
|
shootEffect = ShootFx.shootBig;
|
||||||
smokeEffect = ShootFx.shootBigSmoke;
|
smokeEffect = ShootFx.shootBigSmoke;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bombExplosive = new AmmoType(Items.blastCompound, WeaponBullets.bombExplosive, 3) {{
|
bombExplosive = new AmmoType(Items.blastCompound, WeaponBullets.bombExplosive, 3){{
|
||||||
shootEffect = Fx.none;
|
shootEffect = Fx.none;
|
||||||
smokeEffect = Fx.none;
|
smokeEffect = Fx.none;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bombIncendiary = new AmmoType(Items.pyratite, WeaponBullets.bombIncendiary, 3) {{
|
bombIncendiary = new AmmoType(Items.pyratite, WeaponBullets.bombIncendiary, 3){{
|
||||||
shootEffect = Fx.none;
|
shootEffect = Fx.none;
|
||||||
smokeEffect = Fx.none;
|
smokeEffect = Fx.none;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bombOil = new AmmoType(Items.coal, WeaponBullets.bombOil, 3) {{
|
bombOil = new AmmoType(Items.coal, WeaponBullets.bombOil, 3){{
|
||||||
shootEffect = Fx.none;
|
shootEffect = Fx.none;
|
||||||
smokeEffect = Fx.none;
|
smokeEffect = Fx.none;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
flamerThermite = new AmmoType(Items.pyratite, TurretBullets.basicFlame, 3) {{
|
flamerThermite = new AmmoType(Items.pyratite, TurretBullets.basicFlame, 3){{
|
||||||
shootEffect = ShootFx.shootSmallFlame;
|
shootEffect = ShootFx.shootSmallFlame;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
weaponMissile = new AmmoType(Items.carbide, MissileBullets.javelin, 2) {{
|
weaponMissile = new AmmoType(Items.carbide, MissileBullets.javelin, 2){{
|
||||||
shootEffect = BulletFx.hitBulletSmall;
|
shootEffect = BulletFx.hitBulletSmall;
|
||||||
smokeEffect = Fx.none;
|
smokeEffect = Fx.none;
|
||||||
reloadMultiplier = 1.2f;
|
reloadMultiplier = 1.2f;
|
||||||
@@ -59,37 +59,37 @@ public class AmmoTypes implements ContentList {
|
|||||||
|
|
||||||
//bullets
|
//bullets
|
||||||
|
|
||||||
bulletLead = new AmmoType(Items.lead, StandardBullets.lead, 5) {{
|
bulletLead = new AmmoType(Items.lead, StandardBullets.lead, 5){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
reloadMultiplier = 1.6f;
|
reloadMultiplier = 1.6f;
|
||||||
inaccuracy = 5f;
|
inaccuracy = 5f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bulletTungsten = new AmmoType(Items.tungsten, StandardBullets.tungsten, 2) {{
|
bulletTungsten = new AmmoType(Items.tungsten, StandardBullets.tungsten, 2){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
reloadMultiplier = 0.8f;
|
reloadMultiplier = 0.8f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bulletCarbide = new AmmoType(Items.carbide, StandardBullets.carbide, 2) {{
|
bulletCarbide = new AmmoType(Items.carbide, StandardBullets.carbide, 2){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
reloadMultiplier = 0.6f;
|
reloadMultiplier = 0.6f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bulletThorium = new AmmoType(Items.thorium, StandardBullets.thorium, 2) {{
|
bulletThorium = new AmmoType(Items.thorium, StandardBullets.thorium, 2){{
|
||||||
shootEffect = ShootFx.shootBig;
|
shootEffect = ShootFx.shootBig;
|
||||||
smokeEffect = ShootFx.shootBigSmoke;
|
smokeEffect = ShootFx.shootBigSmoke;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bulletSilicon = new AmmoType(Items.silicon, StandardBullets.homing, 5) {{
|
bulletSilicon = new AmmoType(Items.silicon, StandardBullets.homing, 5){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
reloadMultiplier = 1.4f;
|
reloadMultiplier = 1.4f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bulletPyratite = new AmmoType(Items.pyratite, StandardBullets.tracer, 3) {{
|
bulletPyratite = new AmmoType(Items.pyratite, StandardBullets.tracer, 3){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
inaccuracy = 3f;
|
inaccuracy = 3f;
|
||||||
@@ -97,71 +97,71 @@ public class AmmoTypes implements ContentList {
|
|||||||
|
|
||||||
//flak
|
//flak
|
||||||
|
|
||||||
flakLead = new AmmoType(Items.lead, FlakBullets.lead, 5) {{
|
flakLead = new AmmoType(Items.lead, FlakBullets.lead, 5){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
flakExplosive = new AmmoType(Items.blastCompound, FlakBullets.explosive, 5) {{
|
flakExplosive = new AmmoType(Items.blastCompound, FlakBullets.explosive, 5){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
flakPlastic = new AmmoType(Items.plastanium, FlakBullets.plastic, 5) {{
|
flakPlastic = new AmmoType(Items.plastanium, FlakBullets.plastic, 5){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
flakSurge = new AmmoType(Items.surgealloy, FlakBullets.surge, 5) {{
|
flakSurge = new AmmoType(Items.surgealloy, FlakBullets.surge, 5){{
|
||||||
shootEffect = ShootFx.shootSmall;
|
shootEffect = ShootFx.shootSmall;
|
||||||
smokeEffect = ShootFx.shootSmallSmoke;
|
smokeEffect = ShootFx.shootSmallSmoke;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//missiles
|
//missiles
|
||||||
|
|
||||||
missileExplosive = new AmmoType(Items.blastCompound, MissileBullets.explosive, 1) {{
|
missileExplosive = new AmmoType(Items.blastCompound, MissileBullets.explosive, 1){{
|
||||||
shootEffect = ShootFx.shootBig2;
|
shootEffect = ShootFx.shootBig2;
|
||||||
smokeEffect = ShootFx.shootBigSmoke2;
|
smokeEffect = ShootFx.shootBigSmoke2;
|
||||||
reloadMultiplier = 1.2f;
|
reloadMultiplier = 1.2f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
missileIncindiary = new AmmoType(Items.pyratite, MissileBullets.incindiary, 1) {{
|
missileIncindiary = new AmmoType(Items.pyratite, MissileBullets.incindiary, 1){{
|
||||||
shootEffect = ShootFx.shootBig2;
|
shootEffect = ShootFx.shootBig2;
|
||||||
smokeEffect = ShootFx.shootBigSmoke2;
|
smokeEffect = ShootFx.shootBigSmoke2;
|
||||||
reloadMultiplier = 1.0f;
|
reloadMultiplier = 1.0f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
missileSurge = new AmmoType(Items.surgealloy, MissileBullets.surge, 1) {{
|
missileSurge = new AmmoType(Items.surgealloy, MissileBullets.surge, 1){{
|
||||||
shootEffect = ShootFx.shootBig2;
|
shootEffect = ShootFx.shootBig2;
|
||||||
smokeEffect = ShootFx.shootBigSmoke2;
|
smokeEffect = ShootFx.shootBigSmoke2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//artillery
|
//artillery
|
||||||
|
|
||||||
artilleryCarbide = new AmmoType(Items.carbide, ArtilleryBullets.carbide, 2) {{
|
artilleryCarbide = new AmmoType(Items.carbide, ArtilleryBullets.carbide, 2){{
|
||||||
shootEffect = ShootFx.shootBig2;
|
shootEffect = ShootFx.shootBig2;
|
||||||
smokeEffect = ShootFx.shootBigSmoke2;
|
smokeEffect = ShootFx.shootBigSmoke2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
artilleryPlastic = new AmmoType(Items.plastanium, ArtilleryBullets.plastic, 2) {{
|
artilleryPlastic = new AmmoType(Items.plastanium, ArtilleryBullets.plastic, 2){{
|
||||||
shootEffect = ShootFx.shootBig2;
|
shootEffect = ShootFx.shootBig2;
|
||||||
smokeEffect = ShootFx.shootBigSmoke2;
|
smokeEffect = ShootFx.shootBigSmoke2;
|
||||||
reloadMultiplier = 1.4f;
|
reloadMultiplier = 1.4f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
artilleryHoming = new AmmoType(Items.silicon, ArtilleryBullets.homing, 1) {{
|
artilleryHoming = new AmmoType(Items.silicon, ArtilleryBullets.homing, 1){{
|
||||||
shootEffect = ShootFx.shootBig2;
|
shootEffect = ShootFx.shootBig2;
|
||||||
smokeEffect = ShootFx.shootBigSmoke2;
|
smokeEffect = ShootFx.shootBigSmoke2;
|
||||||
reloadMultiplier = 0.9f;
|
reloadMultiplier = 0.9f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
artilleryIncindiary = new AmmoType(Items.pyratite, ArtilleryBullets.incindiary, 2) {{
|
artilleryIncindiary = new AmmoType(Items.pyratite, ArtilleryBullets.incindiary, 2){{
|
||||||
shootEffect = ShootFx.shootBig2;
|
shootEffect = ShootFx.shootBig2;
|
||||||
smokeEffect = ShootFx.shootBigSmoke2;
|
smokeEffect = ShootFx.shootBigSmoke2;
|
||||||
reloadMultiplier = 1.2f;
|
reloadMultiplier = 1.2f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
artilleryExplosive = new AmmoType(Items.blastCompound, ArtilleryBullets.explosive, 1) {{
|
artilleryExplosive = new AmmoType(Items.blastCompound, ArtilleryBullets.explosive, 1){{
|
||||||
shootEffect = ShootFx.shootBig2;
|
shootEffect = ShootFx.shootBig2;
|
||||||
smokeEffect = ShootFx.shootBigSmoke2;
|
smokeEffect = ShootFx.shootBigSmoke2;
|
||||||
reloadMultiplier = 1.6f;
|
reloadMultiplier = 1.6f;
|
||||||
@@ -169,7 +169,7 @@ public class AmmoTypes implements ContentList {
|
|||||||
|
|
||||||
//flame
|
//flame
|
||||||
|
|
||||||
basicFlame = new AmmoType(Liquids.oil, TurretBullets.basicFlame, 0.3f) {{
|
basicFlame = new AmmoType(Liquids.oil, TurretBullets.basicFlame, 0.3f){{
|
||||||
shootEffect = ShootFx.shootSmallFlame;
|
shootEffect = ShootFx.shootSmallFlame;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ public class AmmoTypes implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return AmmoType.all();
|
return AmmoType.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,41 +12,41 @@ public class Items implements ContentList{
|
|||||||
biomatter, sand, blastCompound, pyratite;
|
biomatter, sand, blastCompound, pyratite;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
stone = new Item("stone", Color.valueOf("777777")) {{
|
stone = new Item("stone", Color.valueOf("777777")){{
|
||||||
hardness = 3;
|
hardness = 3;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
tungsten = new Item("tungsten", Color.valueOf("a0b0c8")) {{
|
tungsten = new Item("tungsten", Color.valueOf("a0b0c8")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
hardness = 1;
|
hardness = 1;
|
||||||
cost = 0.75f;
|
cost = 0.75f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
lead = new Item("lead", Color.valueOf("8e85a2")) {{
|
lead = new Item("lead", Color.valueOf("8e85a2")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
hardness = 1;
|
hardness = 1;
|
||||||
cost = 0.6f;
|
cost = 0.6f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
coal = new Item("coal", Color.valueOf("272727")) {{
|
coal = new Item("coal", Color.valueOf("272727")){{
|
||||||
explosiveness = 0.2f;
|
explosiveness = 0.2f;
|
||||||
flammability = 0.5f;
|
flammability = 0.5f;
|
||||||
hardness = 2;
|
hardness = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
carbide = new Item("carbide", Color.valueOf("e2e2e2")) {{
|
carbide = new Item("carbide", Color.valueOf("e2e2e2")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
titanium = new Item("titanium", Color.valueOf("8da1e3")) {{
|
titanium = new Item("titanium", Color.valueOf("8da1e3")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
hardness = 3;
|
hardness = 3;
|
||||||
cost = 1.1f;
|
cost = 1.1f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
thorium = new Item("thorium", Color.valueOf("f9a3c7")) {{
|
thorium = new Item("thorium", Color.valueOf("f9a3c7")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
explosiveness = 0.1f;
|
explosiveness = 0.1f;
|
||||||
hardness = 4;
|
hardness = 4;
|
||||||
@@ -54,49 +54,49 @@ public class Items implements ContentList{
|
|||||||
cost = 1.2f;
|
cost = 1.2f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
silicon = new Item("silicon", Color.valueOf("53565c")) {{
|
silicon = new Item("silicon", Color.valueOf("53565c")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
cost = 0.9f;
|
cost = 0.9f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
plastanium = new Item("plastanium", Color.valueOf("e9ead3")) {{
|
plastanium = new Item("plastanium", Color.valueOf("e9ead3")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
flammability = 0.1f;
|
flammability = 0.1f;
|
||||||
explosiveness = 0.1f;
|
explosiveness = 0.1f;
|
||||||
cost = 1.5f;
|
cost = 1.5f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
phasematter = new Item("phase-matter", Color.valueOf("f4ba6e")) {{
|
phasematter = new Item("phase-matter", Color.valueOf("f4ba6e")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
cost = 1.5f;
|
cost = 1.5f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
surgealloy = new Item("surge-alloy", Color.valueOf("b4d5c7")) {{
|
surgealloy = new Item("surge-alloy", Color.valueOf("b4d5c7")){{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
biomatter = new Item("biomatter", Color.valueOf("648b55")) {{
|
biomatter = new Item("biomatter", Color.valueOf("648b55")){{
|
||||||
flammability = 0.4f;
|
flammability = 0.4f;
|
||||||
fluxiness = 0.2f;
|
fluxiness = 0.2f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
sand = new Item("sand", Color.valueOf("e3d39e")) {{
|
sand = new Item("sand", Color.valueOf("e3d39e")){{
|
||||||
fluxiness = 0.5f;
|
fluxiness = 0.5f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
blastCompound = new Item("blast-compound", Color.valueOf("ff795e")) {{
|
blastCompound = new Item("blast-compound", Color.valueOf("ff795e")){{
|
||||||
flammability = 0.2f;
|
flammability = 0.2f;
|
||||||
explosiveness = 0.6f;
|
explosiveness = 0.6f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
pyratite = new Item("pyratite", Color.valueOf("ffaa5f")) {{
|
pyratite = new Item("pyratite", Color.valueOf("ffaa5f")){{
|
||||||
flammability = 0.7f;
|
flammability = 0.7f;
|
||||||
explosiveness = 0.2f;
|
explosiveness = 0.2f;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return Item.all();
|
return Item.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import io.anuke.mindustry.game.Content;
|
|||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
import io.anuke.mindustry.type.Liquid;
|
import io.anuke.mindustry.type.Liquid;
|
||||||
|
|
||||||
public class Liquids implements ContentList {
|
public class Liquids implements ContentList{
|
||||||
public static Liquid water, lava, oil, cryofluid;
|
public static Liquid water, lava, oil, cryofluid;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
water = new Liquid("water", Color.valueOf("486acd")) {
|
water = new Liquid("water", Color.valueOf("486acd")){
|
||||||
{
|
{
|
||||||
heatCapacity = 0.4f;
|
heatCapacity = 0.4f;
|
||||||
tier = 0;
|
tier = 0;
|
||||||
@@ -20,7 +20,7 @@ public class Liquids implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
lava = new Liquid("lava", Color.valueOf("e37341")) {
|
lava = new Liquid("lava", Color.valueOf("e37341")){
|
||||||
{
|
{
|
||||||
temperature = 0.8f;
|
temperature = 0.8f;
|
||||||
viscosity = 0.8f;
|
viscosity = 0.8f;
|
||||||
@@ -29,7 +29,7 @@ public class Liquids implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
oil = new Liquid("oil", Color.valueOf("313131")) {
|
oil = new Liquid("oil", Color.valueOf("313131")){
|
||||||
{
|
{
|
||||||
viscosity = 0.7f;
|
viscosity = 0.7f;
|
||||||
flammability = 0.6f;
|
flammability = 0.6f;
|
||||||
@@ -39,7 +39,7 @@ public class Liquids implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cryofluid = new Liquid("cryofluid", Color.SKY) {
|
cryofluid = new Liquid("cryofluid", Color.SKY){
|
||||||
{
|
{
|
||||||
heatCapacity = 0.9f;
|
heatCapacity = 0.9f;
|
||||||
temperature = 0.25f;
|
temperature = 0.25f;
|
||||||
@@ -50,7 +50,7 @@ public class Liquids implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return Liquid.all();
|
return Liquid.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,14 +8,16 @@ import io.anuke.mindustry.type.ContentList;
|
|||||||
import io.anuke.mindustry.type.Mech;
|
import io.anuke.mindustry.type.Mech;
|
||||||
import io.anuke.mindustry.type.Upgrade;
|
import io.anuke.mindustry.type.Upgrade;
|
||||||
|
|
||||||
public class Mechs implements ContentList {
|
public class Mechs implements ContentList{
|
||||||
public static Mech alpha, delta, tau, omega, dart, javelin, trident, halberd;
|
public static Mech alpha, delta, tau, omega, dart, javelin, trident, halberd;
|
||||||
|
|
||||||
/**These are not new mechs, just re-assignments for convenience.*/
|
/**
|
||||||
|
* These are not new mechs, just re-assignments for convenience.
|
||||||
|
*/
|
||||||
public static Mech starterDesktop, starterMobile;
|
public static Mech starterDesktop, starterMobile;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
alpha = new Mech("alpha-mech", false){{
|
alpha = new Mech("alpha-mech", false){{
|
||||||
drillPower = 1;
|
drillPower = 1;
|
||||||
@@ -85,7 +87,7 @@ public class Mechs implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return Upgrade.all();
|
return Upgrade.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ import static io.anuke.mindustry.type.Category.*;
|
|||||||
public class Recipes implements ContentList{
|
public class Recipes implements ContentList{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load (){
|
public void load(){
|
||||||
//WALLS
|
//WALLS
|
||||||
new Recipe(defense, DefenseBlocks.tungstenWall, new ItemStack(Items.tungsten, 12));
|
new Recipe(defense, DefenseBlocks.tungstenWall, new ItemStack(Items.tungsten, 12));
|
||||||
new Recipe(defense, DefenseBlocks.tungstenWallLarge, new ItemStack(Items.tungsten, 12*4));
|
new Recipe(defense, DefenseBlocks.tungstenWallLarge, new ItemStack(Items.tungsten, 12 * 4));
|
||||||
|
|
||||||
new Recipe(defense, DefenseBlocks.carbideWall, new ItemStack(Items.carbide, 12));
|
new Recipe(defense, DefenseBlocks.carbideWall, new ItemStack(Items.carbide, 12));
|
||||||
new Recipe(defense, DefenseBlocks.carbideWallLarge, new ItemStack(Items.carbide, 12*4));
|
new Recipe(defense, DefenseBlocks.carbideWallLarge, new ItemStack(Items.carbide, 12 * 4));
|
||||||
|
|
||||||
new Recipe(defense, DefenseBlocks.thoriumWall, new ItemStack(Items.thorium, 12));
|
new Recipe(defense, DefenseBlocks.thoriumWall, new ItemStack(Items.thorium, 12));
|
||||||
new Recipe(defense, DefenseBlocks.thoriumWallLarge, new ItemStack(Items.thorium, 12*4));
|
new Recipe(defense, DefenseBlocks.thoriumWallLarge, new ItemStack(Items.thorium, 12 * 4));
|
||||||
|
|
||||||
new Recipe(defense, DefenseBlocks.door, new ItemStack(Items.carbide, 12), new ItemStack(Items.silicon, 8));
|
new Recipe(defense, DefenseBlocks.door, new ItemStack(Items.carbide, 12), new ItemStack(Items.silicon, 8));
|
||||||
new Recipe(defense, DefenseBlocks.doorLarge, new ItemStack(Items.carbide, 12*4), new ItemStack(Items.silicon, 8*4));
|
new Recipe(defense, DefenseBlocks.doorLarge, new ItemStack(Items.carbide, 12 * 4), new ItemStack(Items.silicon, 8 * 4));
|
||||||
|
|
||||||
//TURRETS
|
//TURRETS
|
||||||
new Recipe(weapon, TurretBlocks.duo, new ItemStack(Items.tungsten, 40));
|
new Recipe(weapon, TurretBlocks.duo, new ItemStack(Items.tungsten, 40));
|
||||||
@@ -171,7 +171,6 @@ public class Recipes implements ContentList{
|
|||||||
new Recipe(production, ProductionBlocks.oilextractor, new ItemStack(Items.titanium, 40), new ItemStack(Items.surgealloy, 40));*/
|
new Recipe(production, ProductionBlocks.oilextractor, new ItemStack(Items.titanium, 40), new ItemStack(Items.surgealloy, 40));*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.carbide, 1));
|
//new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.carbide, 1));
|
||||||
|
|
||||||
|
|
||||||
@@ -282,7 +281,7 @@ public class Recipes implements ContentList{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return Recipe.all();
|
return Recipe.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,30 +3,30 @@ package io.anuke.mindustry.content;
|
|||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import io.anuke.mindustry.content.fx.EnvironmentFx;
|
import io.anuke.mindustry.content.fx.EnvironmentFx;
|
||||||
import io.anuke.mindustry.entities.StatusController.StatusEntry;
|
import io.anuke.mindustry.entities.StatusController.StatusEntry;
|
||||||
import io.anuke.mindustry.game.Content;
|
|
||||||
import io.anuke.mindustry.type.StatusEffect;
|
|
||||||
import io.anuke.mindustry.entities.Unit;
|
import io.anuke.mindustry.entities.Unit;
|
||||||
|
import io.anuke.mindustry.game.Content;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
|
import io.anuke.mindustry.type.StatusEffect;
|
||||||
import io.anuke.ucore.core.Effects;
|
import io.anuke.ucore.core.Effects;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class StatusEffects implements ContentList {
|
public class StatusEffects implements ContentList{
|
||||||
public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded;
|
public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
none = new StatusEffect(0);
|
none = new StatusEffect(0);
|
||||||
|
|
||||||
burning = new StatusEffect(4 * 60f) {
|
burning = new StatusEffect(4 * 60f){
|
||||||
{
|
{
|
||||||
oppositeScale = 0.5f;
|
oppositeScale = 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result) {
|
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){
|
||||||
if (to == tarred) {
|
if(to == tarred){
|
||||||
unit.damage(1f);
|
unit.damage(1f);
|
||||||
Effects.effect(EnvironmentFx.burning, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
Effects.effect(EnvironmentFx.burning, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
||||||
return result.set(this, Math.min(time + newTime, baseDuration + tarred.baseDuration));
|
return result.set(this, Math.min(time + newTime, baseDuration + tarred.baseDuration));
|
||||||
@@ -36,45 +36,45 @@ public class StatusEffects implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Unit unit, float time) {
|
public void update(Unit unit, float time){
|
||||||
unit.damagePeriodic(0.04f);
|
unit.damagePeriodic(0.04f);
|
||||||
|
|
||||||
if (Mathf.chance(Timers.delta() * 0.2f)) {
|
if(Mathf.chance(Timers.delta() * 0.2f)){
|
||||||
Effects.effect(EnvironmentFx.burning, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
Effects.effect(EnvironmentFx.burning, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
freezing = new StatusEffect(5 * 60f) {
|
freezing = new StatusEffect(5 * 60f){
|
||||||
{
|
{
|
||||||
oppositeScale = 0.4f;
|
oppositeScale = 0.4f;
|
||||||
speedMultiplier = 0.7f;
|
speedMultiplier = 0.7f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Unit unit, float time) {
|
public void update(Unit unit, float time){
|
||||||
|
|
||||||
if (Mathf.chance(Timers.delta() * 0.15f)) {
|
if(Mathf.chance(Timers.delta() * 0.15f)){
|
||||||
Effects.effect(EnvironmentFx.freezing, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
Effects.effect(EnvironmentFx.freezing, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
wet = new StatusEffect(3 * 60f) {
|
wet = new StatusEffect(3 * 60f){
|
||||||
{
|
{
|
||||||
oppositeScale = 0.5f;
|
oppositeScale = 0.5f;
|
||||||
speedMultiplier = 0.999f;
|
speedMultiplier = 0.999f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Unit unit, float time) {
|
public void update(Unit unit, float time){
|
||||||
if (Mathf.chance(Timers.delta() * 0.15f)) {
|
if(Mathf.chance(Timers.delta() * 0.15f)){
|
||||||
Effects.effect(EnvironmentFx.wet, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
Effects.effect(EnvironmentFx.wet, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
melting = new StatusEffect(5 * 60f) {
|
melting = new StatusEffect(5 * 60f){
|
||||||
{
|
{
|
||||||
oppositeScale = 0.2f;
|
oppositeScale = 0.2f;
|
||||||
speedMultiplier = 0.8f;
|
speedMultiplier = 0.8f;
|
||||||
@@ -82,8 +82,8 @@ public class StatusEffects implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result) {
|
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){
|
||||||
if (to == tarred) {
|
if(to == tarred){
|
||||||
return result.set(this, Math.min(time + newTime / 2f, baseDuration));
|
return result.set(this, Math.min(time + newTime / 2f, baseDuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,30 +91,30 @@ public class StatusEffects implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Unit unit, float time) {
|
public void update(Unit unit, float time){
|
||||||
unit.damagePeriodic(0.3f);
|
unit.damagePeriodic(0.3f);
|
||||||
|
|
||||||
if (Mathf.chance(Timers.delta() * 0.2f)) {
|
if(Mathf.chance(Timers.delta() * 0.2f)){
|
||||||
Effects.effect(EnvironmentFx.melting, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
Effects.effect(EnvironmentFx.melting, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tarred = new StatusEffect(4 * 60f) {
|
tarred = new StatusEffect(4 * 60f){
|
||||||
{
|
{
|
||||||
speedMultiplier = 0.6f;
|
speedMultiplier = 0.6f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Unit unit, float time) {
|
public void update(Unit unit, float time){
|
||||||
if (Mathf.chance(Timers.delta() * 0.15f)) {
|
if(Mathf.chance(Timers.delta() * 0.15f)){
|
||||||
Effects.effect(EnvironmentFx.oily, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
Effects.effect(EnvironmentFx.oily, unit.x + Mathf.range(unit.getSize() / 2f), unit.y + Mathf.range(unit.getSize() / 2f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result) {
|
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){
|
||||||
if (to == melting || to == burning) {
|
if(to == melting || to == burning){
|
||||||
return result.set(to, newTime + time);
|
return result.set(to, newTime + time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ public class StatusEffects implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
overdrive = new StatusEffect(6f) {
|
overdrive = new StatusEffect(6f){
|
||||||
{
|
{
|
||||||
armorMultiplier = 0.95f;
|
armorMultiplier = 0.95f;
|
||||||
speedMultiplier = 1.05f;
|
speedMultiplier = 1.05f;
|
||||||
@@ -130,13 +130,13 @@ public class StatusEffects implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Unit unit, float time) {
|
public void update(Unit unit, float time){
|
||||||
//idle regen boosted
|
//idle regen boosted
|
||||||
unit.health += 0.01f * Timers.delta();
|
unit.health += 0.01f * Timers.delta();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
shielded = new StatusEffect(6f) {
|
shielded = new StatusEffect(6f){
|
||||||
{
|
{
|
||||||
armorMultiplier = 3f;
|
armorMultiplier = 3f;
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ public class StatusEffects implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return StatusEffect.all();
|
return StatusEffect.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import io.anuke.mindustry.entities.units.types.*;
|
|||||||
import io.anuke.mindustry.game.Content;
|
import io.anuke.mindustry.game.Content;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
|
|
||||||
public class UnitTypes implements ContentList {
|
public class UnitTypes implements ContentList{
|
||||||
public static UnitType drone, scout, vtol, monsoon, titan, fabricator;
|
public static UnitType drone, scout, vtol, monsoon, titan, fabricator;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
drone = new UnitType("drone", Drone.class, Drone::new){{
|
drone = new UnitType("drone", Drone.class, Drone::new){{
|
||||||
isFlying = true;
|
isFlying = true;
|
||||||
drag = 0.01f;
|
drag = 0.01f;
|
||||||
@@ -73,7 +73,7 @@ public class UnitTypes implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return UnitType.all();
|
return UnitType.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import io.anuke.mindustry.type.ContentList;
|
|||||||
import io.anuke.mindustry.type.Upgrade;
|
import io.anuke.mindustry.type.Upgrade;
|
||||||
import io.anuke.mindustry.type.Weapon;
|
import io.anuke.mindustry.type.Weapon;
|
||||||
|
|
||||||
public class Weapons implements ContentList {
|
public class Weapons implements ContentList{
|
||||||
public static Weapon blaster, chainBlaster, shockgun, sapper, swarmer, bomber, flakgun, flamethrower, missiles;
|
public static Weapon blaster, chainBlaster, shockgun, sapper, swarmer, bomber, flakgun, flamethrower, missiles;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
blaster = new Weapon("blaster") {{
|
blaster = new Weapon("blaster"){{
|
||||||
length = 1.5f;
|
length = 1.5f;
|
||||||
reload = 15f;
|
reload = 15f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
@@ -22,7 +22,7 @@ public class Weapons implements ContentList {
|
|||||||
setAmmo(AmmoTypes.bulletLead);
|
setAmmo(AmmoTypes.bulletLead);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
missiles = new Weapon("missiles") {{
|
missiles = new Weapon("missiles"){{
|
||||||
length = 1.5f;
|
length = 1.5f;
|
||||||
reload = 40f;
|
reload = 40f;
|
||||||
shots = 2;
|
shots = 2;
|
||||||
@@ -33,7 +33,7 @@ public class Weapons implements ContentList {
|
|||||||
setAmmo(AmmoTypes.weaponMissile);
|
setAmmo(AmmoTypes.weaponMissile);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
chainBlaster = new Weapon("chain-blaster") {{
|
chainBlaster = new Weapon("chain-blaster"){{
|
||||||
length = 1.5f;
|
length = 1.5f;
|
||||||
reload = 30f;
|
reload = 30f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
@@ -41,7 +41,7 @@ public class Weapons implements ContentList {
|
|||||||
setAmmo(AmmoTypes.bulletLead, AmmoTypes.bulletCarbide, AmmoTypes.bulletTungsten, AmmoTypes.bulletSilicon, AmmoTypes.bulletThorium);
|
setAmmo(AmmoTypes.bulletLead, AmmoTypes.bulletCarbide, AmmoTypes.bulletTungsten, AmmoTypes.bulletSilicon, AmmoTypes.bulletThorium);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
shockgun = new Weapon("shockgun") {{
|
shockgun = new Weapon("shockgun"){{
|
||||||
length = 1f;
|
length = 1f;
|
||||||
reload = 50f;
|
reload = 50f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
@@ -53,7 +53,7 @@ public class Weapons implements ContentList {
|
|||||||
setAmmo(AmmoTypes.shotgunTungsten);
|
setAmmo(AmmoTypes.shotgunTungsten);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
flakgun = new Weapon("flakgun") {{
|
flakgun = new Weapon("flakgun"){{
|
||||||
length = 1f;
|
length = 1f;
|
||||||
reload = 70f;
|
reload = 70f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
@@ -65,7 +65,7 @@ public class Weapons implements ContentList {
|
|||||||
setAmmo(AmmoTypes.shellCarbide);
|
setAmmo(AmmoTypes.shellCarbide);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
flamethrower = new Weapon("flamethrower") {{
|
flamethrower = new Weapon("flamethrower"){{
|
||||||
length = 1f;
|
length = 1f;
|
||||||
reload = 14f;
|
reload = 14f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
@@ -74,7 +74,7 @@ public class Weapons implements ContentList {
|
|||||||
setAmmo(AmmoTypes.flamerThermite);
|
setAmmo(AmmoTypes.flamerThermite);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
sapper = new Weapon("sapper") {{
|
sapper = new Weapon("sapper"){{
|
||||||
length = 1.5f;
|
length = 1.5f;
|
||||||
reload = 12f;
|
reload = 12f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
@@ -82,7 +82,7 @@ public class Weapons implements ContentList {
|
|||||||
setAmmo(AmmoTypes.bulletCarbide);
|
setAmmo(AmmoTypes.bulletCarbide);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
swarmer = new Weapon("swarmer") {{
|
swarmer = new Weapon("swarmer"){{
|
||||||
length = 1.5f;
|
length = 1.5f;
|
||||||
reload = 10f;
|
reload = 10f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
@@ -90,7 +90,7 @@ public class Weapons implements ContentList {
|
|||||||
setAmmo(AmmoTypes.bulletPyratite);
|
setAmmo(AmmoTypes.bulletPyratite);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bomber = new Weapon("bomber") {{
|
bomber = new Weapon("bomber"){{
|
||||||
length = 0f;
|
length = 0f;
|
||||||
width = 2f;
|
width = 2f;
|
||||||
reload = 5f;
|
reload = 5f;
|
||||||
@@ -103,7 +103,7 @@ public class Weapons implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return Upgrade.all();
|
return Upgrade.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import io.anuke.mindustry.game.Content;
|
|||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
|
|
||||||
public abstract class BlockList implements ContentList {
|
public abstract class BlockList implements ContentList{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return Block.all();
|
return Block.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,26 +15,31 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
public static Block air, spawn, blockpart, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock;
|
public static Block air, spawn, blockpart, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
air = new Floor("air") {
|
air = new Floor("air"){
|
||||||
{
|
{
|
||||||
blend = false;
|
blend = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//don't draw
|
//don't draw
|
||||||
public void draw(Tile tile) {}
|
public void draw(Tile tile){
|
||||||
public void load() {}
|
}
|
||||||
public void init() {}
|
|
||||||
|
public void load(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(){
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
blockpart = new BlockPart();
|
blockpart = new BlockPart();
|
||||||
|
|
||||||
for(int i = 1; i <= 6; i ++){
|
for(int i = 1; i <= 6; i++){
|
||||||
new BuildBlock("build" + i);
|
new BuildBlock("build" + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
space = new Floor("space") {{
|
space = new Floor("space"){{
|
||||||
placeableOn = false;
|
placeableOn = false;
|
||||||
variants = 0;
|
variants = 0;
|
||||||
cacheLayer = CacheLayer.space;
|
cacheLayer = CacheLayer.space;
|
||||||
@@ -43,11 +48,11 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
minimapColor = Color.valueOf("000001");
|
minimapColor = Color.valueOf("000001");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
metalfloor = new Floor("metalfloor") {{
|
metalfloor = new Floor("metalfloor"){{
|
||||||
variants = 6;
|
variants = 6;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
deepwater = new Floor("deepwater") {{
|
deepwater = new Floor("deepwater"){{
|
||||||
liquidColor = Color.valueOf("546bb3");
|
liquidColor = Color.valueOf("546bb3");
|
||||||
speedMultiplier = 0.2f;
|
speedMultiplier = 0.2f;
|
||||||
variants = 0;
|
variants = 0;
|
||||||
@@ -60,7 +65,7 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
minimapColor = Color.valueOf("465a96");
|
minimapColor = Color.valueOf("465a96");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
water = new Floor("water") {{
|
water = new Floor("water"){{
|
||||||
liquidColor = Color.valueOf("546bb3");
|
liquidColor = Color.valueOf("546bb3");
|
||||||
speedMultiplier = 0.5f;
|
speedMultiplier = 0.5f;
|
||||||
variants = 0;
|
variants = 0;
|
||||||
@@ -72,7 +77,7 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
minimapColor = Color.valueOf("506eb4");
|
minimapColor = Color.valueOf("506eb4");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
lava = new Floor("lava") {{
|
lava = new Floor("lava"){{
|
||||||
liquidColor = Color.valueOf("ed5334");
|
liquidColor = Color.valueOf("ed5334");
|
||||||
speedMultiplier = 0.2f;
|
speedMultiplier = 0.2f;
|
||||||
damageTaken = 0.5f;
|
damageTaken = 0.5f;
|
||||||
@@ -85,7 +90,7 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
minimapColor = Color.valueOf("ed5334");
|
minimapColor = Color.valueOf("ed5334");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
oil = new Floor("oil") {{
|
oil = new Floor("oil"){{
|
||||||
liquidColor = Color.valueOf("292929");
|
liquidColor = Color.valueOf("292929");
|
||||||
status = StatusEffects.tarred;
|
status = StatusEffects.tarred;
|
||||||
statusIntensity = 1f;
|
statusIntensity = 1f;
|
||||||
@@ -97,7 +102,7 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
minimapColor = Color.valueOf("292929");
|
minimapColor = Color.valueOf("292929");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
stone = new Floor("stone") {{
|
stone = new Floor("stone"){{
|
||||||
hasOres = true;
|
hasOres = true;
|
||||||
drops = new ItemStack(Items.stone, 1);
|
drops = new ItemStack(Items.stone, 1);
|
||||||
blends = block -> block != this && !(block instanceof Ore);
|
blends = block -> block != this && !(block instanceof Ore);
|
||||||
@@ -105,7 +110,7 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
playerUnmineable = true;
|
playerUnmineable = true;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
blackstone = new Floor("blackstone") {{
|
blackstone = new Floor("blackstone"){{
|
||||||
drops = new ItemStack(Items.stone, 1);
|
drops = new ItemStack(Items.stone, 1);
|
||||||
minimapColor = Color.valueOf("252525");
|
minimapColor = Color.valueOf("252525");
|
||||||
playerUnmineable = true;
|
playerUnmineable = true;
|
||||||
@@ -115,14 +120,14 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
minimapColor = Color.valueOf("6e501e");
|
minimapColor = Color.valueOf("6e501e");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
sand = new Floor("sand") {{
|
sand = new Floor("sand"){{
|
||||||
drops = new ItemStack(Items.sand, 1);
|
drops = new ItemStack(Items.sand, 1);
|
||||||
minimapColor = Color.valueOf("988a67");
|
minimapColor = Color.valueOf("988a67");
|
||||||
hasOres = true;
|
hasOres = true;
|
||||||
playerUnmineable = true;
|
playerUnmineable = true;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
ice = new Floor("ice") {{
|
ice = new Floor("ice"){{
|
||||||
dragMultiplier = 0.3f;
|
dragMultiplier = 0.3f;
|
||||||
speedMultiplier = 0.4f;
|
speedMultiplier = 0.4f;
|
||||||
minimapColor = Color.valueOf("c4e3e7");
|
minimapColor = Color.valueOf("c4e3e7");
|
||||||
@@ -143,15 +148,15 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
shadow = "shrubshadow";
|
shadow = "shrubshadow";
|
||||||
}};
|
}};
|
||||||
|
|
||||||
rock = new Rock("rock") {{
|
rock = new Rock("rock"){{
|
||||||
variants = 2;
|
variants = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
icerock = new Rock("icerock") {{
|
icerock = new Rock("icerock"){{
|
||||||
variants = 2;
|
variants = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
blackrock = new Rock("blackrock") {{
|
blackrock = new Rock("blackrock"){{
|
||||||
variants = 1;
|
variants = 1;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import io.anuke.mindustry.type.ItemStack;
|
|||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.blocks.production.*;
|
import io.anuke.mindustry.world.blocks.production.*;
|
||||||
|
|
||||||
public class CraftingBlocks extends BlockList implements ContentList {
|
public class CraftingBlocks extends BlockList implements ContentList{
|
||||||
public static Block smelter, arcsmelter, siliconsmelter, plastaniumCompressor, phaseWeaver, alloysmelter, alloyfuser,
|
public static Block smelter, arcsmelter, siliconsmelter, plastaniumCompressor, phaseWeaver, alloysmelter, alloyfuser,
|
||||||
pyratiteMixer, blastMixer,
|
pyratiteMixer, blastMixer,
|
||||||
cryofluidmixer, melter, separator, centrifuge, biomatterCompressor, pulverizer, solidifier, incinerator;
|
cryofluidmixer, melter, separator, centrifuge, biomatterCompressor, pulverizer, solidifier, incinerator;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
smelter = new Smelter("smelter") {{
|
smelter = new Smelter("smelter"){{
|
||||||
health = 70;
|
health = 70;
|
||||||
result = Items.carbide;
|
result = Items.carbide;
|
||||||
craftTime = 45f;
|
craftTime = 45f;
|
||||||
@@ -28,7 +28,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.item(Items.coal);
|
consumes.item(Items.coal);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
arcsmelter = new PowerSmelter("arc-smelter") {{
|
arcsmelter = new PowerSmelter("arc-smelter"){{
|
||||||
health = 90;
|
health = 90;
|
||||||
craftEffect = BlockFx.smeltsmoke;
|
craftEffect = BlockFx.smeltsmoke;
|
||||||
result = Items.carbide;
|
result = Items.carbide;
|
||||||
@@ -42,7 +42,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.1f);
|
consumes.power(0.1f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
siliconsmelter = new PowerSmelter("silicon-smelter") {{
|
siliconsmelter = new PowerSmelter("silicon-smelter"){{
|
||||||
health = 90;
|
health = 90;
|
||||||
craftEffect = BlockFx.smeltsmoke;
|
craftEffect = BlockFx.smeltsmoke;
|
||||||
result = Items.silicon;
|
result = Items.silicon;
|
||||||
@@ -55,7 +55,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.05f);
|
consumes.power(0.05f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
plastaniumCompressor = new PlastaniumCompressor("plastanium-compressor") {{
|
plastaniumCompressor = new PlastaniumCompressor("plastanium-compressor"){{
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
liquidCapacity = 60f;
|
liquidCapacity = 60f;
|
||||||
craftTime = 80f;
|
craftTime = 80f;
|
||||||
@@ -72,7 +72,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.item(Items.titanium, 2);
|
consumes.item(Items.titanium, 2);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
phaseWeaver = new PhaseWeaver("phase-weaver") {{
|
phaseWeaver = new PhaseWeaver("phase-weaver"){{
|
||||||
health = 90;
|
health = 90;
|
||||||
craftEffect = BlockFx.smeltsmoke;
|
craftEffect = BlockFx.smeltsmoke;
|
||||||
result = Items.phasematter;
|
result = Items.phasematter;
|
||||||
@@ -83,7 +83,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.5f);
|
consumes.power(0.5f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
alloysmelter = new PowerSmelter("alloy-smelter") {{
|
alloysmelter = new PowerSmelter("alloy-smelter"){{
|
||||||
health = 90;
|
health = 90;
|
||||||
craftEffect = BlockFx.smeltsmoke;
|
craftEffect = BlockFx.smeltsmoke;
|
||||||
result = Items.surgealloy;
|
result = Items.surgealloy;
|
||||||
@@ -97,7 +97,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.items(new ItemStack[]{new ItemStack(Items.titanium, 2), new ItemStack(Items.lead, 4), new ItemStack(Items.silicon, 3), new ItemStack(Items.plastanium, 2)});
|
consumes.items(new ItemStack[]{new ItemStack(Items.titanium, 2), new ItemStack(Items.lead, 4), new ItemStack(Items.silicon, 3), new ItemStack(Items.plastanium, 2)});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
alloyfuser = new PowerSmelter("alloy-fuser") {{
|
alloyfuser = new PowerSmelter("alloy-fuser"){{
|
||||||
health = 90;
|
health = 90;
|
||||||
craftEffect = BlockFx.smeltsmoke;
|
craftEffect = BlockFx.smeltsmoke;
|
||||||
result = Items.surgealloy;
|
result = Items.surgealloy;
|
||||||
@@ -111,7 +111,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.4f);
|
consumes.power(0.4f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
cryofluidmixer = new LiquidMixer("cryofluidmixer") {{
|
cryofluidmixer = new LiquidMixer("cryofluidmixer"){{
|
||||||
health = 200;
|
health = 200;
|
||||||
outputLiquid = Liquids.cryofluid;
|
outputLiquid = Liquids.cryofluid;
|
||||||
liquidPerItem = 50f;
|
liquidPerItem = 50f;
|
||||||
@@ -124,7 +124,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.liquid(Liquids.water, 0.3f);
|
consumes.liquid(Liquids.water, 0.3f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
blastMixer = new GenericCrafter("blast-mixer") {{
|
blastMixer = new GenericCrafter("blast-mixer"){{
|
||||||
itemCapacity = 20;
|
itemCapacity = 20;
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
@@ -137,7 +137,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.04f);
|
consumes.power(0.04f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
pyratiteMixer = new PowerSmelter("pyratite-mixer") {{
|
pyratiteMixer = new PowerSmelter("pyratite-mixer"){{
|
||||||
flameColor = Color.CLEAR;
|
flameColor = Color.CLEAR;
|
||||||
itemCapacity = 20;
|
itemCapacity = 20;
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
@@ -150,7 +150,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.items(new ItemStack[]{new ItemStack(Items.coal, 1), new ItemStack(Items.lead, 2), new ItemStack(Items.sand, 2)});
|
consumes.items(new ItemStack[]{new ItemStack(Items.coal, 1), new ItemStack(Items.lead, 2), new ItemStack(Items.sand, 2)});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
melter = new PowerCrafter("melter") {{
|
melter = new PowerCrafter("melter"){{
|
||||||
health = 200;
|
health = 200;
|
||||||
outputLiquid = Liquids.lava;
|
outputLiquid = Liquids.lava;
|
||||||
outputLiquidAmount = 0.75f;
|
outputLiquidAmount = 0.75f;
|
||||||
@@ -162,7 +162,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.item(Items.stone, 2);
|
consumes.item(Items.stone, 2);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
separator = new Separator("separator") {{
|
separator = new Separator("separator"){{
|
||||||
results = new Item[]{
|
results = new Item[]{
|
||||||
null, null, null, null, null, null, null, null, null, null,
|
null, null, null, null, null, null, null, null, null, null,
|
||||||
Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand,
|
Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand,
|
||||||
@@ -180,7 +180,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.liquid(Liquids.water, 0.3f);
|
consumes.liquid(Liquids.water, 0.3f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
centrifuge = new Separator("centrifuge") {{
|
centrifuge = new Separator("centrifuge"){{
|
||||||
results = new Item[]{
|
results = new Item[]{
|
||||||
null, null, null, null, null, null, null, null, null, null, null, null, null,
|
null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||||
Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand,
|
Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand, Items.sand,
|
||||||
@@ -207,7 +207,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.liquid(Liquids.water, 0.5f);
|
consumes.liquid(Liquids.water, 0.5f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
biomatterCompressor = new Compressor("biomattercompressor") {{
|
biomatterCompressor = new Compressor("biomattercompressor"){{
|
||||||
liquidCapacity = 60f;
|
liquidCapacity = 60f;
|
||||||
itemCapacity = 50;
|
itemCapacity = 50;
|
||||||
craftTime = 25f;
|
craftTime = 25f;
|
||||||
@@ -221,7 +221,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.06f);
|
consumes.power(0.06f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
pulverizer = new Pulverizer("pulverizer") {{
|
pulverizer = new Pulverizer("pulverizer"){{
|
||||||
itemCapacity = 40;
|
itemCapacity = 40;
|
||||||
output = Items.sand;
|
output = Items.sand;
|
||||||
health = 80;
|
health = 80;
|
||||||
@@ -234,7 +234,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.2f);
|
consumes.power(0.2f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
solidifier = new GenericCrafter("solidifer") {{
|
solidifier = new GenericCrafter("solidifer"){{
|
||||||
liquidCapacity = 21f;
|
liquidCapacity = 21f;
|
||||||
craftTime = 14;
|
craftTime = 14;
|
||||||
output = Items.stone;
|
output = Items.stone;
|
||||||
@@ -246,7 +246,7 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
consumes.liquid(Liquids.lava, 1f);
|
consumes.liquid(Liquids.lava, 1f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
incinerator = new Incinerator("incinerator") {{
|
incinerator = new Incinerator("incinerator"){{
|
||||||
health = 90;
|
health = 90;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,45 +28,52 @@ import java.io.IOException;
|
|||||||
public class DebugBlocks extends BlockList implements ContentList{
|
public class DebugBlocks extends BlockList implements ContentList{
|
||||||
public static Block powerVoid, powerInfinite, itemSource, liquidSource, itemVoid;
|
public static Block powerVoid, powerInfinite, itemSource, liquidSource, itemVoid;
|
||||||
|
|
||||||
|
@Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true)
|
||||||
|
public static void setLiquidSourceLiquid(Player player, Tile tile, Liquid liquid){
|
||||||
|
LiquidSourceEntity entity = tile.entity();
|
||||||
|
entity.source = liquid;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
powerVoid = new PowerBlock("powervoid") {
|
powerVoid = new PowerBlock("powervoid"){
|
||||||
{
|
{
|
||||||
powerCapacity = Float.MAX_VALUE;
|
powerCapacity = Float.MAX_VALUE;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
powerInfinite = new PowerNode("powerinfinite") {
|
powerInfinite = new PowerNode("powerinfinite"){
|
||||||
{
|
{
|
||||||
powerCapacity = 10000f;
|
powerCapacity = 10000f;
|
||||||
powerSpeed = 100f;
|
powerSpeed = 100f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Tile tile) {
|
public void update(Tile tile){
|
||||||
super.update(tile);
|
super.update(tile);
|
||||||
tile.entity.power.amount = powerCapacity;
|
tile.entity.power.amount = powerCapacity;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
itemSource = new Sorter("itemsource") {
|
itemSource = new Sorter("itemsource"){
|
||||||
{
|
{
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Tile tile) {
|
public void update(Tile tile){
|
||||||
SorterEntity entity = tile.entity();
|
SorterEntity entity = tile.entity();
|
||||||
entity.items.set(entity.sortItem, 1);
|
entity.items.set(entity.sortItem, 1);
|
||||||
tryDump(tile, entity.sortItem);
|
tryDump(tile, entity.sortItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Item item, Tile tile, Tile source) {
|
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
liquidSource = new Block("liquidsource") {
|
liquidSource = new Block("liquidsource"){
|
||||||
{
|
{
|
||||||
update = true;
|
update = true;
|
||||||
solid = true;
|
solid = true;
|
||||||
@@ -76,7 +83,7 @@ public class DebugBlocks extends BlockList implements ContentList{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Tile tile) {
|
public void update(Tile tile){
|
||||||
LiquidSourceEntity entity = tile.entity();
|
LiquidSourceEntity entity = tile.entity();
|
||||||
|
|
||||||
tile.entity.liquids.add(entity.source, liquidCapacity);
|
tile.entity.liquids.add(entity.source, liquidCapacity);
|
||||||
@@ -84,7 +91,7 @@ public class DebugBlocks extends BlockList implements ContentList{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Tile tile) {
|
public void draw(Tile tile){
|
||||||
super.draw(tile);
|
super.draw(tile);
|
||||||
|
|
||||||
LiquidSourceEntity entity = tile.entity();
|
LiquidSourceEntity entity = tile.entity();
|
||||||
@@ -95,7 +102,7 @@ public class DebugBlocks extends BlockList implements ContentList{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void buildTable(Tile tile, Table table) {
|
public void buildTable(Tile tile, Table table){
|
||||||
LiquidSourceEntity entity = tile.entity();
|
LiquidSourceEntity entity = tile.entity();
|
||||||
|
|
||||||
Array<Liquid> items = Liquid.all();
|
Array<Liquid> items = Liquid.all();
|
||||||
@@ -103,8 +110,8 @@ public class DebugBlocks extends BlockList implements ContentList{
|
|||||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||||
Table cont = new Table();
|
Table cont = new Table();
|
||||||
|
|
||||||
for (int i = 0; i < items.size; i++) {
|
for(int i = 0; i < items.size; i++){
|
||||||
if (i == 0) continue;
|
if(i == 0) continue;
|
||||||
final int f = i;
|
final int f = i;
|
||||||
ImageButton button = cont.addImageButton("white", "toggle", 24, () -> {
|
ImageButton button = cont.addImageButton("white", "toggle", 24, () -> {
|
||||||
CallBlocks.setLiquidSourceLiquid(null, tile, items.get(f));
|
CallBlocks.setLiquidSourceLiquid(null, tile, items.get(f));
|
||||||
@@ -112,7 +119,7 @@ public class DebugBlocks extends BlockList implements ContentList{
|
|||||||
button.getStyle().imageUpColor = items.get(i).color;
|
button.getStyle().imageUpColor = items.get(i).color;
|
||||||
button.setChecked(entity.source.id == f);
|
button.setChecked(entity.source.id == f);
|
||||||
|
|
||||||
if (i % 4 == 3) {
|
if(i % 4 == 3){
|
||||||
cont.row();
|
cont.row();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,43 +128,37 @@ public class DebugBlocks extends BlockList implements ContentList{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TileEntity getEntity() {
|
public TileEntity getEntity(){
|
||||||
return new LiquidSourceEntity();
|
return new LiquidSourceEntity();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
itemVoid = new Block("itemvoid") {
|
itemVoid = new Block("itemvoid"){
|
||||||
{
|
{
|
||||||
update = solid = true;
|
update = solid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleItem(Item item, Tile tile, Tile source) {
|
public void handleItem(Item item, Tile tile, Tile source){
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Item item, Tile tile, Tile source) {
|
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true)
|
class LiquidSourceEntity extends TileEntity{
|
||||||
public static void setLiquidSourceLiquid(Player player, Tile tile, Liquid liquid){
|
|
||||||
LiquidSourceEntity entity = tile.entity();
|
|
||||||
entity.source = liquid;
|
|
||||||
}
|
|
||||||
|
|
||||||
class LiquidSourceEntity extends TileEntity {
|
|
||||||
public Liquid source = Liquids.water;
|
public Liquid source = Liquids.water;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutputStream stream) throws IOException {
|
public void write(DataOutputStream stream) throws IOException{
|
||||||
stream.writeByte(source.id);
|
stream.writeByte(source.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInputStream stream) throws IOException {
|
public void read(DataInputStream stream) throws IOException{
|
||||||
source = Liquid.getByID(stream.readByte());
|
source = Liquid.getByID(stream.readByte());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,65 +8,65 @@ import io.anuke.mindustry.world.blocks.defense.DeflectorWall;
|
|||||||
import io.anuke.mindustry.world.blocks.defense.Door;
|
import io.anuke.mindustry.world.blocks.defense.Door;
|
||||||
import io.anuke.mindustry.world.blocks.defense.PhaseWall;
|
import io.anuke.mindustry.world.blocks.defense.PhaseWall;
|
||||||
|
|
||||||
public class DefenseBlocks extends BlockList implements ContentList {
|
public class DefenseBlocks extends BlockList implements ContentList{
|
||||||
public static Block tungstenWall, tungstenWallLarge, carbideWall, carbideWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge, deflectorwall, deflectorwalllarge,
|
public static Block tungstenWall, tungstenWallLarge, carbideWall, carbideWallLarge, thoriumWall, thoriumWallLarge, door, doorLarge, deflectorwall, deflectorwalllarge,
|
||||||
phasewall, phasewalllarge;
|
phasewall, phasewalllarge;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
int wallHealthMultiplier = 4;
|
int wallHealthMultiplier = 4;
|
||||||
|
|
||||||
tungstenWall = new Wall("tungsten-wall") {{
|
tungstenWall = new Wall("tungsten-wall"){{
|
||||||
health = 80 * wallHealthMultiplier;
|
health = 80 * wallHealthMultiplier;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
tungstenWallLarge = new Wall("tungsten-wall-large") {{
|
tungstenWallLarge = new Wall("tungsten-wall-large"){{
|
||||||
health = 80 * 4 * wallHealthMultiplier;
|
health = 80 * 4 * wallHealthMultiplier;
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
carbideWall = new Wall("carbide-wall") {{
|
carbideWall = new Wall("carbide-wall"){{
|
||||||
health = 110 * wallHealthMultiplier;
|
health = 110 * wallHealthMultiplier;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
carbideWallLarge = new Wall("carbide-wall-large") {{
|
carbideWallLarge = new Wall("carbide-wall-large"){{
|
||||||
health = 110 * wallHealthMultiplier*4;
|
health = 110 * wallHealthMultiplier * 4;
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
thoriumWall = new Wall("thorium-wall") {{
|
thoriumWall = new Wall("thorium-wall"){{
|
||||||
health = 200 * wallHealthMultiplier;
|
health = 200 * wallHealthMultiplier;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
thoriumWallLarge = new Wall("thorium-wall-large") {{
|
thoriumWallLarge = new Wall("thorium-wall-large"){{
|
||||||
health = 200 * wallHealthMultiplier*4;
|
health = 200 * wallHealthMultiplier * 4;
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
deflectorwall = new DeflectorWall("deflector-wall") {{
|
deflectorwall = new DeflectorWall("deflector-wall"){{
|
||||||
health = 150 * wallHealthMultiplier;
|
health = 150 * wallHealthMultiplier;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
deflectorwalllarge = new DeflectorWall("deflector-wall-large") {{
|
deflectorwalllarge = new DeflectorWall("deflector-wall-large"){{
|
||||||
health = 150 * 4 * wallHealthMultiplier;
|
health = 150 * 4 * wallHealthMultiplier;
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
phasewall = new PhaseWall("phase-wall") {{
|
phasewall = new PhaseWall("phase-wall"){{
|
||||||
health = 150 * wallHealthMultiplier;
|
health = 150 * wallHealthMultiplier;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
phasewalllarge = new PhaseWall("phase-wall-large") {{
|
phasewalllarge = new PhaseWall("phase-wall-large"){{
|
||||||
health = 150 * 4 * wallHealthMultiplier;
|
health = 150 * 4 * wallHealthMultiplier;
|
||||||
size = 2;
|
size = 2;
|
||||||
regenSpeed = 0.5f;
|
regenSpeed = 0.5f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
door = new Door("door") {{
|
door = new Door("door"){{
|
||||||
health = 100 * wallHealthMultiplier;
|
health = 100 * wallHealthMultiplier;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
doorLarge = new Door("door-large") {{
|
doorLarge = new Door("door-large"){{
|
||||||
openfx = BlockFx.dooropenlarge;
|
openfx = BlockFx.dooropenlarge;
|
||||||
closefx = BlockFx.doorcloselarge;
|
closefx = BlockFx.doorcloselarge;
|
||||||
health = 100 * 4 * wallHealthMultiplier;
|
health = 100 * 4 * wallHealthMultiplier;
|
||||||
|
|||||||
@@ -5,50 +5,50 @@ import io.anuke.mindustry.world.Block;
|
|||||||
import io.anuke.mindustry.world.blocks.distribution.*;
|
import io.anuke.mindustry.world.blocks.distribution.*;
|
||||||
|
|
||||||
public class DistributionBlocks extends BlockList implements ContentList{
|
public class DistributionBlocks extends BlockList implements ContentList{
|
||||||
public static Block conveyor, titaniumconveyor, distributor, junction,
|
public static Block conveyor, titaniumconveyor, distributor, junction,
|
||||||
bridgeConveyor, phaseConveyor, sorter, splitter, overflowGate, massDriver;
|
bridgeConveyor, phaseConveyor, sorter, splitter, overflowGate, massDriver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
conveyor = new Conveyor("conveyor") {{
|
conveyor = new Conveyor("conveyor"){{
|
||||||
health = 45;
|
health = 45;
|
||||||
speed = 0.03f;
|
speed = 0.03f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
titaniumconveyor = new Conveyor("titanium-conveyor") {{
|
titaniumconveyor = new Conveyor("titanium-conveyor"){{
|
||||||
health = 65;
|
health = 65;
|
||||||
speed = 0.07f;
|
speed = 0.07f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
junction = new Junction("junction") {{
|
junction = new Junction("junction"){{
|
||||||
speed = 26;
|
speed = 26;
|
||||||
capacity = 32;
|
capacity = 32;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
bridgeConveyor = new BufferedItemBridge("bridge-conveyor") {{
|
bridgeConveyor = new BufferedItemBridge("bridge-conveyor"){{
|
||||||
range = 3;
|
range = 3;
|
||||||
hasPower = false;
|
hasPower = false;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
phaseConveyor = new ItemBridge("phase-conveyor") {{
|
phaseConveyor = new ItemBridge("phase-conveyor"){{
|
||||||
range = 7;
|
range = 7;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
sorter = new Sorter("sorter");
|
sorter = new Sorter("sorter");
|
||||||
|
|
||||||
splitter = new Splitter("splitter");
|
splitter = new Splitter("splitter");
|
||||||
|
|
||||||
distributor = new Splitter("distributor") {{
|
distributor = new Splitter("distributor"){{
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
overflowGate = new OverflowGate("overflow-gate");
|
overflowGate = new OverflowGate("overflow-gate");
|
||||||
|
|
||||||
massDriver = new MassDriver("mass-driver"){{
|
massDriver = new MassDriver("mass-driver"){{
|
||||||
size = 3;
|
size = 3;
|
||||||
itemCapacity = 80;
|
itemCapacity = 80;
|
||||||
range = 300f;
|
range = 300f;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
|||||||
public static Block mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, liquidRouter, liquidtank, liquidJunction, bridgeConduit, phaseConduit;
|
public static Block mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, liquidRouter, liquidtank, liquidJunction, bridgeConduit, phaseConduit;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
mechanicalPump = new Pump("mechanical-pump") {{
|
mechanicalPump = new Pump("mechanical-pump"){{
|
||||||
shadow = "shadow-round-1";
|
shadow = "shadow-round-1";
|
||||||
pumpAmount = 0.1f;
|
pumpAmount = 0.1f;
|
||||||
tier = 0;
|
tier = 0;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
rotaryPump = new Pump("rotary-pump") {{
|
rotaryPump = new Pump("rotary-pump"){{
|
||||||
shadow = "shadow-rounded-2";
|
shadow = "shadow-rounded-2";
|
||||||
pumpAmount = 0.25f;
|
pumpAmount = 0.25f;
|
||||||
consumes.power(0.015f);
|
consumes.power(0.015f);
|
||||||
@@ -27,7 +27,7 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
|||||||
tier = 1;
|
tier = 1;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
thermalPump = new Pump("thermal-pump") {{
|
thermalPump = new Pump("thermal-pump"){{
|
||||||
pumpAmount = 0.3f;
|
pumpAmount = 0.3f;
|
||||||
consumes.power(0.05f);
|
consumes.power(0.05f);
|
||||||
liquidCapacity = 40f;
|
liquidCapacity = 40f;
|
||||||
@@ -35,21 +35,21 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
|||||||
tier = 2;
|
tier = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
conduit = new Conduit("conduit") {{
|
conduit = new Conduit("conduit"){{
|
||||||
health = 45;
|
health = 45;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
pulseConduit = new Conduit("pulse-conduit") {{
|
pulseConduit = new Conduit("pulse-conduit"){{
|
||||||
liquidCapacity = 16f;
|
liquidCapacity = 16f;
|
||||||
liquidFlowFactor = 4.9f;
|
liquidFlowFactor = 4.9f;
|
||||||
health = 90;
|
health = 90;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
liquidRouter = new LiquidRouter("liquid-router") {{
|
liquidRouter = new LiquidRouter("liquid-router"){{
|
||||||
liquidCapacity = 40f;
|
liquidCapacity = 40f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
liquidtank = new LiquidRouter("liquid-tank") {{
|
liquidtank = new LiquidRouter("liquid-tank"){{
|
||||||
size = 3;
|
size = 3;
|
||||||
liquidCapacity = 1500f;
|
liquidCapacity = 1500f;
|
||||||
health = 500;
|
health = 500;
|
||||||
@@ -57,12 +57,12 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
|||||||
|
|
||||||
liquidJunction = new LiquidJunction("liquid-junction");
|
liquidJunction = new LiquidJunction("liquid-junction");
|
||||||
|
|
||||||
bridgeConduit = new LiquidExtendingBridge("bridge-conduit") {{
|
bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{
|
||||||
range = 3;
|
range = 3;
|
||||||
hasPower = false;
|
hasPower = false;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
phaseConduit = new LiquidBridge("phase-conduit") {{
|
phaseConduit = new LiquidBridge("phase-conduit"){{
|
||||||
range = 7;
|
range = 7;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,18 @@ import io.anuke.mindustry.world.Block;
|
|||||||
import io.anuke.mindustry.world.blocks.Floor;
|
import io.anuke.mindustry.world.blocks.Floor;
|
||||||
import io.anuke.mindustry.world.blocks.OreBlock;
|
import io.anuke.mindustry.world.blocks.OreBlock;
|
||||||
|
|
||||||
public class OreBlocks extends BlockList {
|
public class OreBlocks extends BlockList{
|
||||||
private static final ObjectMap<Item, ObjectMap<Block, Block>> oreBlockMap = new ObjectMap<>();
|
private static final ObjectMap<Item, ObjectMap<Block, Block>> oreBlockMap = new ObjectMap<>();
|
||||||
|
|
||||||
|
public static Block get(Block floor, Item item){
|
||||||
|
if(!oreBlockMap.containsKey(item)) throw new IllegalArgumentException("Item '" + item + "' is not an ore!");
|
||||||
|
if(!oreBlockMap.get(item).containsKey(floor))
|
||||||
|
throw new IllegalArgumentException("Block '" + floor.name + "' does not support ores!");
|
||||||
|
return oreBlockMap.get(item).get(floor);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
Item[] ores = {Items.tungsten, Items.lead, Items.coal, Items.titanium, Items.thorium};
|
Item[] ores = {Items.tungsten, Items.lead, Items.coal, Items.titanium, Items.thorium};
|
||||||
|
|
||||||
for(Item item : ores){
|
for(Item item : ores){
|
||||||
@@ -25,10 +32,4 @@ public class OreBlocks extends BlockList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Block get(Block floor, Item item){
|
|
||||||
if(!oreBlockMap.containsKey(item)) throw new IllegalArgumentException("Item '" + item + "' is not an ore!");
|
|
||||||
if(!oreBlockMap.get(item).containsKey(floor)) throw new IllegalArgumentException("Block '" + floor.name + "' does not support ores!");
|
|
||||||
return oreBlockMap.get(item).get(floor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,19 @@ import io.anuke.mindustry.world.Block;
|
|||||||
import io.anuke.mindustry.world.blocks.distribution.WarpGate;
|
import io.anuke.mindustry.world.blocks.distribution.WarpGate;
|
||||||
import io.anuke.mindustry.world.blocks.power.*;
|
import io.anuke.mindustry.world.blocks.power.*;
|
||||||
|
|
||||||
public class PowerBlocks extends BlockList implements ContentList {
|
public class PowerBlocks extends BlockList implements ContentList{
|
||||||
public static Block combustionGenerator, thermalGenerator, turbineGenerator, rtgGenerator, solarPanel, largeSolarPanel,
|
public static Block combustionGenerator, thermalGenerator, turbineGenerator, rtgGenerator, solarPanel, largeSolarPanel,
|
||||||
nuclearReactor, fusionReactor, battery, batteryLarge, powerNode, powerNodeLarge, warpGate;
|
nuclearReactor, fusionReactor, battery, batteryLarge, powerNode, powerNodeLarge, warpGate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
combustionGenerator = new BurnerGenerator("combustion-generator") {{
|
combustionGenerator = new BurnerGenerator("combustion-generator"){{
|
||||||
powerOutput = 0.09f;
|
powerOutput = 0.09f;
|
||||||
powerCapacity = 40f;
|
powerCapacity = 40f;
|
||||||
itemDuration = 40f;
|
itemDuration = 40f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
thermalGenerator = new LiquidHeatGenerator("thermal-generator") {{
|
thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{
|
||||||
maxLiquidGenerate = 0.5f;
|
maxLiquidGenerate = 0.5f;
|
||||||
powerPerLiquid = 0.08f;
|
powerPerLiquid = 0.08f;
|
||||||
powerCapacity = 40f;
|
powerCapacity = 40f;
|
||||||
@@ -28,7 +28,7 @@ public class PowerBlocks extends BlockList implements ContentList {
|
|||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
turbineGenerator = new TurbineGenerator("turbine-generator") {{
|
turbineGenerator = new TurbineGenerator("turbine-generator"){{
|
||||||
powerOutput = 0.28f;
|
powerOutput = 0.28f;
|
||||||
powerCapacity = 40f;
|
powerCapacity = 40f;
|
||||||
itemDuration = 30f;
|
itemDuration = 30f;
|
||||||
@@ -37,46 +37,46 @@ public class PowerBlocks extends BlockList implements ContentList {
|
|||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
rtgGenerator = new DecayGenerator("rtg-generator") {{
|
rtgGenerator = new DecayGenerator("rtg-generator"){{
|
||||||
powerCapacity = 40f;
|
powerCapacity = 40f;
|
||||||
powerOutput = 0.02f;
|
powerOutput = 0.02f;
|
||||||
itemDuration = 500f;
|
itemDuration = 500f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
solarPanel = new SolarGenerator("solar-panel") {{
|
solarPanel = new SolarGenerator("solar-panel"){{
|
||||||
generation = 0.0045f;
|
generation = 0.0045f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
largeSolarPanel = new SolarGenerator("solar-panel-large") {{
|
largeSolarPanel = new SolarGenerator("solar-panel-large"){{
|
||||||
size = 3;
|
size = 3;
|
||||||
generation = 0.055f;
|
generation = 0.055f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
nuclearReactor = new NuclearReactor("nuclear-reactor") {{
|
nuclearReactor = new NuclearReactor("nuclear-reactor"){{
|
||||||
size = 3;
|
size = 3;
|
||||||
health = 700;
|
health = 700;
|
||||||
powerMultiplier = 0.8f;
|
powerMultiplier = 0.8f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
fusionReactor = new FusionReactor("fusion-reactor") {{
|
fusionReactor = new FusionReactor("fusion-reactor"){{
|
||||||
size = 4;
|
size = 4;
|
||||||
health = 600;
|
health = 600;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
battery = new PowerDistributor("battery") {{
|
battery = new PowerDistributor("battery"){{
|
||||||
powerCapacity = 320f;
|
powerCapacity = 320f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
batteryLarge = new PowerDistributor("battery-large") {{
|
batteryLarge = new PowerDistributor("battery-large"){{
|
||||||
size = 3;
|
size = 3;
|
||||||
powerCapacity = 2000f;
|
powerCapacity = 2000f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
powerNode = new PowerNode("power-node") {{
|
powerNode = new PowerNode("power-node"){{
|
||||||
shadow = "shadow-round-1";
|
shadow = "shadow-round-1";
|
||||||
}};
|
}};
|
||||||
|
|
||||||
powerNodeLarge = new PowerNode("power-node-large") {{
|
powerNodeLarge = new PowerNode("power-node-large"){{
|
||||||
size = 2;
|
size = 2;
|
||||||
powerSpeed = 1f;
|
powerSpeed = 1f;
|
||||||
maxNodes = 5;
|
maxNodes = 5;
|
||||||
|
|||||||
@@ -11,22 +11,22 @@ import io.anuke.mindustry.world.blocks.production.Drill;
|
|||||||
import io.anuke.mindustry.world.blocks.production.Fracker;
|
import io.anuke.mindustry.world.blocks.production.Fracker;
|
||||||
import io.anuke.mindustry.world.blocks.production.SolidPump;
|
import io.anuke.mindustry.world.blocks.production.SolidPump;
|
||||||
|
|
||||||
public class ProductionBlocks extends BlockList implements ContentList {
|
public class ProductionBlocks extends BlockList implements ContentList{
|
||||||
public static Block tungstenDrill, carbideDrill, laserdrill, blastdrill, plasmadrill, waterextractor, oilextractor, cultivator;
|
public static Block tungstenDrill, carbideDrill, laserdrill, blastdrill, plasmadrill, waterextractor, oilextractor, cultivator;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
tungstenDrill = new Drill("tungsten-drill") {{
|
tungstenDrill = new Drill("tungsten-drill"){{
|
||||||
tier = 2;
|
tier = 2;
|
||||||
drillTime = 340;
|
drillTime = 340;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
carbideDrill = new Drill("carbide-drill") {{
|
carbideDrill = new Drill("carbide-drill"){{
|
||||||
tier = 3;
|
tier = 3;
|
||||||
drillTime = 280;
|
drillTime = 280;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
laserdrill = new Drill("laser-drill") {{
|
laserdrill = new Drill("laser-drill"){{
|
||||||
drillTime = 180;
|
drillTime = 180;
|
||||||
size = 2;
|
size = 2;
|
||||||
hasPower = true;
|
hasPower = true;
|
||||||
@@ -37,7 +37,7 @@ public class ProductionBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.2f);
|
consumes.power(0.2f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
blastdrill = new Drill("blast-drill") {{
|
blastdrill = new Drill("blast-drill"){{
|
||||||
drillTime = 120;
|
drillTime = 120;
|
||||||
size = 3;
|
size = 3;
|
||||||
drawRim = true;
|
drawRim = true;
|
||||||
@@ -52,7 +52,7 @@ public class ProductionBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.5f);
|
consumes.power(0.5f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
plasmadrill = new Drill("plasma-drill") {{
|
plasmadrill = new Drill("plasma-drill"){{
|
||||||
heatColor = Color.valueOf("ff461b");
|
heatColor = Color.valueOf("ff461b");
|
||||||
drillTime = 90;
|
drillTime = 90;
|
||||||
size = 4;
|
size = 4;
|
||||||
@@ -69,7 +69,7 @@ public class ProductionBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.7f);
|
consumes.power(0.7f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
waterextractor = new SolidPump("water-extractor") {{
|
waterextractor = new SolidPump("water-extractor"){{
|
||||||
result = Liquids.water;
|
result = Liquids.water;
|
||||||
pumpAmount = 0.1f;
|
pumpAmount = 0.1f;
|
||||||
size = 2;
|
size = 2;
|
||||||
@@ -79,7 +79,7 @@ public class ProductionBlocks extends BlockList implements ContentList {
|
|||||||
consumes.power(0.2f);
|
consumes.power(0.2f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
oilextractor = new Fracker("oil-extractor") {{
|
oilextractor = new Fracker("oil-extractor"){{
|
||||||
result = Liquids.oil;
|
result = Liquids.oil;
|
||||||
updateEffect = BlockFx.pulverize;
|
updateEffect = BlockFx.pulverize;
|
||||||
liquidCapacity = 50f;
|
liquidCapacity = 50f;
|
||||||
@@ -93,7 +93,7 @@ public class ProductionBlocks extends BlockList implements ContentList {
|
|||||||
consumes.liquid(Liquids.water, 0.3f);
|
consumes.liquid(Liquids.water, 0.3f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
cultivator = new Cultivator("cultivator") {{
|
cultivator = new Cultivator("cultivator"){{
|
||||||
result = Items.biomatter;
|
result = Items.biomatter;
|
||||||
drillTime = 260;
|
drillTime = 260;
|
||||||
size = 2;
|
size = 2;
|
||||||
|
|||||||
@@ -7,26 +7,26 @@ import io.anuke.mindustry.world.blocks.storage.SortedUnloader;
|
|||||||
import io.anuke.mindustry.world.blocks.storage.Unloader;
|
import io.anuke.mindustry.world.blocks.storage.Unloader;
|
||||||
import io.anuke.mindustry.world.blocks.storage.Vault;
|
import io.anuke.mindustry.world.blocks.storage.Vault;
|
||||||
|
|
||||||
public class StorageBlocks extends BlockList implements ContentList {
|
public class StorageBlocks extends BlockList implements ContentList{
|
||||||
public static Block core, vault, unloader, sortedunloader;
|
public static Block core, vault, unloader, sortedunloader;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
core = new CoreBlock("core") {{
|
core = new CoreBlock("core"){{
|
||||||
health = 800;
|
health = 800;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
vault = new Vault("vault") {{
|
vault = new Vault("vault"){{
|
||||||
size = 3;
|
size = 3;
|
||||||
health = 600;
|
health = 600;
|
||||||
itemCapacity = 2000;
|
itemCapacity = 2000;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
unloader = new Unloader("unloader") {{
|
unloader = new Unloader("unloader"){{
|
||||||
speed = 5;
|
speed = 5;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
sortedunloader = new SortedUnloader("sortedunloader") {{
|
sortedunloader = new SortedUnloader("sortedunloader"){{
|
||||||
speed = 5;
|
speed = 5;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,22 +12,23 @@ import io.anuke.ucore.util.Angles;
|
|||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
import io.anuke.ucore.util.Strings;
|
import io.anuke.ucore.util.Strings;
|
||||||
|
|
||||||
public class TurretBlocks extends BlockList implements ContentList {
|
public class TurretBlocks extends BlockList implements ContentList{
|
||||||
public static Block duo, /*scatter,*/ scorch, hail, wave, lancer, arc, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown;
|
public static Block duo, /*scatter,*/
|
||||||
|
scorch, hail, wave, lancer, arc, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
duo = new DoubleTurret("duo") {{
|
duo = new DoubleTurret("duo"){{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.bulletTungsten, AmmoTypes.bulletLead, AmmoTypes.bulletCarbide, AmmoTypes.bulletPyratite, AmmoTypes.bulletSilicon};
|
ammoTypes = new AmmoType[]{AmmoTypes.bulletTungsten, AmmoTypes.bulletLead, AmmoTypes.bulletCarbide, AmmoTypes.bulletPyratite, AmmoTypes.bulletSilicon};
|
||||||
reload = 25f;
|
reload = 25f;
|
||||||
restitution = 0.03f;
|
restitution = 0.03f;
|
||||||
range = 90f;
|
range = 90f;
|
||||||
shootCone = 15f;
|
shootCone = 15f;
|
||||||
ammoUseEffect = ShootFx.shellEjectSmall;
|
ammoUseEffect = ShootFx.shellEjectSmall;
|
||||||
health = 80;
|
health = 80;
|
||||||
inaccuracy = 2f;
|
inaccuracy = 2f;
|
||||||
rotatespeed = 10f;
|
rotatespeed = 10f;
|
||||||
}};
|
}};
|
||||||
/*
|
/*
|
||||||
scatter = new BurstTurret("scatter") {{
|
scatter = new BurstTurret("scatter") {{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.flakLead, AmmoTypes.flakExplosive, AmmoTypes.flakPlastic};
|
ammoTypes = new AmmoType[]{AmmoTypes.flakLead, AmmoTypes.flakExplosive, AmmoTypes.flakPlastic};
|
||||||
@@ -41,165 +42,165 @@ public class TurretBlocks extends BlockList implements ContentList {
|
|||||||
ammoUseEffect = ShootFx.shellEjectSmall;
|
ammoUseEffect = ShootFx.shellEjectSmall;
|
||||||
}};*/
|
}};*/
|
||||||
|
|
||||||
hail = new ArtilleryTurret("hail") {{
|
hail = new ArtilleryTurret("hail"){{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.artilleryCarbide, AmmoTypes.artilleryHoming, AmmoTypes.artilleryIncindiary};
|
ammoTypes = new AmmoType[]{AmmoTypes.artilleryCarbide, AmmoTypes.artilleryHoming, AmmoTypes.artilleryIncindiary};
|
||||||
reload = 100f;
|
reload = 100f;
|
||||||
recoil = 2f;
|
recoil = 2f;
|
||||||
range = 200f;
|
range = 200f;
|
||||||
inaccuracy = 5f;
|
inaccuracy = 5f;
|
||||||
health = 120;
|
health = 120;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
scorch = new LiquidTurret("scorch") {{
|
scorch = new LiquidTurret("scorch"){{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.basicFlame};
|
ammoTypes = new AmmoType[]{AmmoTypes.basicFlame};
|
||||||
recoil = 0f;
|
recoil = 0f;
|
||||||
reload = 4f;
|
reload = 4f;
|
||||||
shootCone = 50f;
|
shootCone = 50f;
|
||||||
ammoUseEffect = ShootFx.shellEjectSmall;
|
ammoUseEffect = ShootFx.shellEjectSmall;
|
||||||
health = 160;
|
health = 160;
|
||||||
|
|
||||||
drawer = (tile, entity) -> Draw.rect(entity.target != null ? name + "-shoot" : name, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
drawer = (tile, entity) -> Draw.rect(entity.target != null ? name + "-shoot" : name, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
wave = new LiquidTurret("wave") {{
|
wave = new LiquidTurret("wave"){{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.water, AmmoTypes.lava, AmmoTypes.cryofluid, AmmoTypes.oil};
|
ammoTypes = new AmmoType[]{AmmoTypes.water, AmmoTypes.lava, AmmoTypes.cryofluid, AmmoTypes.oil};
|
||||||
size = 2;
|
size = 2;
|
||||||
recoil = 0f;
|
recoil = 0f;
|
||||||
reload = 4f;
|
reload = 4f;
|
||||||
inaccuracy = 5f;
|
inaccuracy = 5f;
|
||||||
shootCone = 50f;
|
shootCone = 50f;
|
||||||
shootEffect = ShootFx.shootLiquid;
|
shootEffect = ShootFx.shootLiquid;
|
||||||
range = 70f;
|
range = 70f;
|
||||||
health = 360;
|
health = 360;
|
||||||
|
|
||||||
drawer = (tile, entity) -> {
|
drawer = (tile, entity) -> {
|
||||||
Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
||||||
|
|
||||||
Draw.color(entity.liquids.current().color);
|
Draw.color(entity.liquids.current().color);
|
||||||
Draw.alpha(entity.liquids.total() / liquidCapacity);
|
Draw.alpha(entity.liquids.total() / liquidCapacity);
|
||||||
Draw.rect(name + "-liquid", tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
Draw.rect(name + "-liquid", tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
||||||
Draw.color();
|
Draw.color();
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
lancer = new LaserTurret("lancer") {{
|
lancer = new LaserTurret("lancer"){{
|
||||||
range = 90f;
|
range = 90f;
|
||||||
chargeTime = 60f;
|
chargeTime = 60f;
|
||||||
chargeMaxDelay = 30f;
|
chargeMaxDelay = 30f;
|
||||||
chargeEffects = 7;
|
chargeEffects = 7;
|
||||||
shootType = AmmoTypes.lancerLaser;
|
shootType = AmmoTypes.lancerLaser;
|
||||||
recoil = 2f;
|
recoil = 2f;
|
||||||
reload = 100f;
|
reload = 100f;
|
||||||
cooldown = 0.03f;
|
cooldown = 0.03f;
|
||||||
powerUsed = 20f;
|
powerUsed = 20f;
|
||||||
powerCapacity = 60f;
|
powerCapacity = 60f;
|
||||||
shootShake = 2f;
|
shootShake = 2f;
|
||||||
shootEffect = ShootFx.lancerLaserShoot;
|
shootEffect = ShootFx.lancerLaserShoot;
|
||||||
smokeEffect = ShootFx.lancerLaserShootSmoke;
|
smokeEffect = ShootFx.lancerLaserShootSmoke;
|
||||||
chargeEffect = ShootFx.lancerLaserCharge;
|
chargeEffect = ShootFx.lancerLaserCharge;
|
||||||
chargeBeginEffect = ShootFx.lancerLaserChargeBegin;
|
chargeBeginEffect = ShootFx.lancerLaserChargeBegin;
|
||||||
heatColor = Color.RED;
|
heatColor = Color.RED;
|
||||||
size = 2;
|
size = 2;
|
||||||
health = 320;
|
health = 320;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
arc = new LaserTurret("arc") {{
|
arc = new LaserTurret("arc"){{
|
||||||
shootType = AmmoTypes.lightning;
|
shootType = AmmoTypes.lightning;
|
||||||
reload = 100f;
|
reload = 100f;
|
||||||
chargeTime = 70f;
|
chargeTime = 70f;
|
||||||
shootShake = 1f;
|
shootShake = 1f;
|
||||||
chargeMaxDelay = 30f;
|
chargeMaxDelay = 30f;
|
||||||
chargeEffects = 7;
|
chargeEffects = 7;
|
||||||
shootEffect = ShootFx.lightningShoot;
|
shootEffect = ShootFx.lightningShoot;
|
||||||
chargeEffect = ShootFx.lightningCharge;
|
chargeEffect = ShootFx.lightningCharge;
|
||||||
chargeBeginEffect = ShootFx.lancerLaserChargeBegin;
|
chargeBeginEffect = ShootFx.lancerLaserChargeBegin;
|
||||||
heatColor = Color.RED;
|
heatColor = Color.RED;
|
||||||
recoil = 3f;
|
recoil = 3f;
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
swarmer = new BurstTurret("swarmer") {{
|
swarmer = new BurstTurret("swarmer"){{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.missileExplosive, AmmoTypes.missileIncindiary/*, AmmoTypes.missileSurge*/};
|
ammoTypes = new AmmoType[]{AmmoTypes.missileExplosive, AmmoTypes.missileIncindiary/*, AmmoTypes.missileSurge*/};
|
||||||
reload = 60f;
|
reload = 60f;
|
||||||
shots = 4;
|
shots = 4;
|
||||||
burstSpacing = 5;
|
burstSpacing = 5;
|
||||||
inaccuracy = 10f;
|
inaccuracy = 10f;
|
||||||
range = 140f;
|
range = 140f;
|
||||||
xRand = 6f;
|
xRand = 6f;
|
||||||
size = 2;
|
size = 2;
|
||||||
health = 380;
|
health = 380;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
salvo = new BurstTurret("salvo") {{
|
salvo = new BurstTurret("salvo"){{
|
||||||
size = 2;
|
size = 2;
|
||||||
range = 120f;
|
range = 120f;
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.bulletTungsten, AmmoTypes.bulletCarbide, AmmoTypes.bulletPyratite, AmmoTypes.bulletThorium, AmmoTypes.bulletSilicon};
|
ammoTypes = new AmmoType[]{AmmoTypes.bulletTungsten, AmmoTypes.bulletCarbide, AmmoTypes.bulletPyratite, AmmoTypes.bulletThorium, AmmoTypes.bulletSilicon};
|
||||||
reload = 40f;
|
reload = 40f;
|
||||||
restitution = 0.03f;
|
restitution = 0.03f;
|
||||||
ammoEjectBack = 3f;
|
ammoEjectBack = 3f;
|
||||||
cooldown = 0.03f;
|
cooldown = 0.03f;
|
||||||
recoil = 3f;
|
recoil = 3f;
|
||||||
shootShake = 2f;
|
shootShake = 2f;
|
||||||
burstSpacing = 4;
|
burstSpacing = 4;
|
||||||
shots = 3;
|
shots = 3;
|
||||||
ammoUseEffect = ShootFx.shellEjectBig;
|
ammoUseEffect = ShootFx.shellEjectBig;
|
||||||
|
|
||||||
drawer = (tile, entity) -> {
|
drawer = (tile, entity) -> {
|
||||||
Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
Draw.rect(region, tile.drawx() + tr2.x, tile.drawy() + tr2.y, entity.rotation - 90);
|
||||||
float offsetx = (int) (Mathf.abscurve(Mathf.curve(entity.reload / reload, 0.3f, 0.2f)) * 3f);
|
float offsetx = (int) (Mathf.abscurve(Mathf.curve(entity.reload / reload, 0.3f, 0.2f)) * 3f);
|
||||||
float offsety = -(int) (Mathf.abscurve(Mathf.curve(entity.reload / reload, 0.3f, 0.2f)) * 2f);
|
float offsety = -(int) (Mathf.abscurve(Mathf.curve(entity.reload / reload, 0.3f, 0.2f)) * 2f);
|
||||||
|
|
||||||
for (int i : Mathf.signs) {
|
for(int i : Mathf.signs){
|
||||||
float rot = entity.rotation + 90 * i;
|
float rot = entity.rotation + 90 * i;
|
||||||
Draw.rect(name + "-panel-" + Strings.dir(i),
|
Draw.rect(name + "-panel-" + Strings.dir(i),
|
||||||
tile.drawx() + tr2.x + Angles.trnsx(rot, offsetx, offsety),
|
tile.drawx() + tr2.x + Angles.trnsx(rot, offsetx, offsety),
|
||||||
tile.drawy() + tr2.y + Angles.trnsy(rot, -offsetx, offsety), entity.rotation - 90);
|
tile.drawy() + tr2.y + Angles.trnsy(rot, -offsetx, offsety), entity.rotation - 90);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
health = 360;
|
health = 360;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
ripple = new ArtilleryTurret("ripple") {{
|
ripple = new ArtilleryTurret("ripple"){{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.artilleryCarbide, AmmoTypes.artilleryHoming, AmmoTypes.artilleryIncindiary, AmmoTypes.artilleryExplosive, AmmoTypes.artilleryPlastic};
|
ammoTypes = new AmmoType[]{AmmoTypes.artilleryCarbide, AmmoTypes.artilleryHoming, AmmoTypes.artilleryIncindiary, AmmoTypes.artilleryExplosive, AmmoTypes.artilleryPlastic};
|
||||||
size = 3;
|
size = 3;
|
||||||
shots = 4;
|
shots = 4;
|
||||||
inaccuracy = 12f;
|
inaccuracy = 12f;
|
||||||
reload = 60f;
|
reload = 60f;
|
||||||
ammoEjectBack = 5f;
|
ammoEjectBack = 5f;
|
||||||
ammoUseEffect = ShootFx.shellEjectBig;
|
ammoUseEffect = ShootFx.shellEjectBig;
|
||||||
cooldown = 0.03f;
|
cooldown = 0.03f;
|
||||||
velocityInaccuracy = 0.2f;
|
velocityInaccuracy = 0.2f;
|
||||||
restitution = 0.02f;
|
restitution = 0.02f;
|
||||||
recoil = 6f;
|
recoil = 6f;
|
||||||
shootShake = 2f;
|
shootShake = 2f;
|
||||||
range = 300f;
|
range = 300f;
|
||||||
|
|
||||||
health = 550;
|
health = 550;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
cyclone = new ItemTurret("cyclone") {{
|
cyclone = new ItemTurret("cyclone"){{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.flakLead, AmmoTypes.flakExplosive, AmmoTypes.flakPlastic, AmmoTypes.flakSurge};
|
ammoTypes = new AmmoType[]{AmmoTypes.flakLead, AmmoTypes.flakExplosive, AmmoTypes.flakPlastic, AmmoTypes.flakSurge};
|
||||||
size = 3;
|
size = 3;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
fuse = new ItemTurret("fuse") {{
|
fuse = new ItemTurret("fuse"){{
|
||||||
//TODO make it use power
|
//TODO make it use power
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.fuseShotgun};
|
ammoTypes = new AmmoType[]{AmmoTypes.fuseShotgun};
|
||||||
size = 3;
|
size = 3;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
spectre = new ItemTurret("spectre") {{
|
spectre = new ItemTurret("spectre"){{
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.bulletTungsten, AmmoTypes.bulletLead, AmmoTypes.bulletCarbide, AmmoTypes.bulletPyratite, AmmoTypes.bulletThorium, AmmoTypes.bulletSilicon};
|
ammoTypes = new AmmoType[]{AmmoTypes.bulletTungsten, AmmoTypes.bulletLead, AmmoTypes.bulletCarbide, AmmoTypes.bulletPyratite, AmmoTypes.bulletThorium, AmmoTypes.bulletSilicon};
|
||||||
reload = 25f;
|
reload = 25f;
|
||||||
restitution = 0.03f;
|
restitution = 0.03f;
|
||||||
ammoUseEffect = ShootFx.shellEjectSmall;
|
ammoUseEffect = ShootFx.shellEjectSmall;
|
||||||
size = 4;
|
size = 4;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
meltdown = new PowerTurret("meltdown") {{
|
meltdown = new PowerTurret("meltdown"){{
|
||||||
shootType = AmmoTypes.meltdownLaser;
|
shootType = AmmoTypes.meltdownLaser;
|
||||||
size = 4;
|
size = 4;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import io.anuke.mindustry.type.ItemStack;
|
|||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.blocks.units.*;
|
import io.anuke.mindustry.world.blocks.units.*;
|
||||||
|
|
||||||
public class UnitBlocks extends BlockList implements ContentList {
|
public class UnitBlocks extends BlockList implements ContentList{
|
||||||
public static Block resupplyPoint, repairPoint, droneFactory, fabricatorFactory, dropPoint, reconstructor, overdriveProjector, shieldProjector;
|
public static Block resupplyPoint, repairPoint, droneFactory, fabricatorFactory, dropPoint, reconstructor, overdriveProjector, shieldProjector;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
droneFactory = new UnitFactory("drone-factory") {{
|
droneFactory = new UnitFactory("drone-factory"){{
|
||||||
type = UnitTypes.drone;
|
type = UnitTypes.drone;
|
||||||
produceTime = 800;
|
produceTime = 800;
|
||||||
size = 2;
|
size = 2;
|
||||||
@@ -20,7 +20,7 @@ public class UnitBlocks extends BlockList implements ContentList {
|
|||||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)});
|
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
fabricatorFactory = new UnitFactory("fabricator-factory") {{
|
fabricatorFactory = new UnitFactory("fabricator-factory"){{
|
||||||
type = UnitTypes.fabricator;
|
type = UnitTypes.fabricator;
|
||||||
produceTime = 1600;
|
produceTime = 1600;
|
||||||
size = 2;
|
size = 2;
|
||||||
@@ -28,30 +28,30 @@ public class UnitBlocks extends BlockList implements ContentList {
|
|||||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80)});
|
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80)});
|
||||||
}};
|
}};
|
||||||
|
|
||||||
resupplyPoint = new ResupplyPoint("resupply-point") {{
|
resupplyPoint = new ResupplyPoint("resupply-point"){{
|
||||||
shadow = "shadow-round-1";
|
shadow = "shadow-round-1";
|
||||||
itemCapacity = 30;
|
itemCapacity = 30;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
dropPoint = new DropPoint("drop-point") {{
|
dropPoint = new DropPoint("drop-point"){{
|
||||||
shadow = "shadow-round-1";
|
shadow = "shadow-round-1";
|
||||||
itemCapacity = 40;
|
itemCapacity = 40;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
repairPoint = new RepairPoint("repair-point") {{
|
repairPoint = new RepairPoint("repair-point"){{
|
||||||
shadow = "shadow-round-1";
|
shadow = "shadow-round-1";
|
||||||
repairSpeed = 0.1f;
|
repairSpeed = 0.1f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
reconstructor = new Reconstructor("reconstructor") {{
|
reconstructor = new Reconstructor("reconstructor"){{
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
overdriveProjector = new OverdriveProjector("overdrive-projector") {{
|
overdriveProjector = new OverdriveProjector("overdrive-projector"){{
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
shieldProjector = new ShieldProjector("shieldprojector") {{
|
shieldProjector = new ShieldProjector("shieldprojector"){{
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import io.anuke.mindustry.content.Mechs;
|
|||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.blocks.units.MechFactory;
|
import io.anuke.mindustry.world.blocks.units.MechFactory;
|
||||||
|
|
||||||
public class UpgradeBlocks extends BlockList {
|
public class UpgradeBlocks extends BlockList{
|
||||||
public static Block deltaFactory, tauFactory, omegaFactory, dartFactory, javelinFactory, tridentFactory, halberdFactory;
|
public static Block deltaFactory, tauFactory, omegaFactory, dartFactory, javelinFactory, tridentFactory, halberdFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
deltaFactory = new MechFactory("delta-mech-factory"){{
|
deltaFactory = new MechFactory("delta-mech-factory"){{
|
||||||
mech = Mechs.delta;
|
mech = Mechs.delta;
|
||||||
size = 2;
|
size = 2;
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ public class ArtilleryBullets extends BulletList implements ContentList{
|
|||||||
public static BulletType carbide, plastic, plasticFrag, homing, incindiary, explosive, surge;
|
public static BulletType carbide, plastic, plasticFrag, homing, incindiary, explosive, surge;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
carbide = new ArtilleryBulletType(3f, 0, "shell") {
|
carbide = new ArtilleryBulletType(3f, 0, "shell"){
|
||||||
{
|
{
|
||||||
hiteffect = BulletFx.flakExplosion;
|
hiteffect = BulletFx.flakExplosion;
|
||||||
knockback = 0.8f;
|
knockback = 0.8f;
|
||||||
@@ -25,7 +25,7 @@ public class ArtilleryBullets extends BulletList implements ContentList{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
plasticFrag = new BasicBulletType(2.5f, 6, "bullet") {
|
plasticFrag = new BasicBulletType(2.5f, 6, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 10f;
|
bulletWidth = 10f;
|
||||||
bulletHeight = 12f;
|
bulletHeight = 12f;
|
||||||
@@ -36,7 +36,7 @@ public class ArtilleryBullets extends BulletList implements ContentList{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
plastic = new ArtilleryBulletType(3.3f, 0, "shell") {
|
plastic = new ArtilleryBulletType(3.3f, 0, "shell"){
|
||||||
{
|
{
|
||||||
hiteffect = BulletFx.plasticExplosion;
|
hiteffect = BulletFx.plasticExplosion;
|
||||||
knockback = 1f;
|
knockback = 1f;
|
||||||
@@ -52,7 +52,7 @@ public class ArtilleryBullets extends BulletList implements ContentList{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
homing = new ArtilleryBulletType(3f, 0, "shell") {
|
homing = new ArtilleryBulletType(3f, 0, "shell"){
|
||||||
{
|
{
|
||||||
hiteffect = BulletFx.flakExplosion;
|
hiteffect = BulletFx.flakExplosion;
|
||||||
knockback = 0.8f;
|
knockback = 0.8f;
|
||||||
@@ -66,7 +66,7 @@ public class ArtilleryBullets extends BulletList implements ContentList{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
incindiary = new ArtilleryBulletType(3f, 0, "shell") {
|
incindiary = new ArtilleryBulletType(3f, 0, "shell"){
|
||||||
{
|
{
|
||||||
hiteffect = BulletFx.blastExplosion;
|
hiteffect = BulletFx.blastExplosion;
|
||||||
knockback = 0.8f;
|
knockback = 0.8f;
|
||||||
@@ -83,7 +83,7 @@ public class ArtilleryBullets extends BulletList implements ContentList{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
explosive = new ArtilleryBulletType(2f, 0, "shell") {
|
explosive = new ArtilleryBulletType(2f, 0, "shell"){
|
||||||
{
|
{
|
||||||
hiteffect = BulletFx.blastExplosion;
|
hiteffect = BulletFx.blastExplosion;
|
||||||
knockback = 0.8f;
|
knockback = 0.8f;
|
||||||
@@ -97,7 +97,7 @@ public class ArtilleryBullets extends BulletList implements ContentList{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
surge = new ArtilleryBulletType(3f, 0, "shell") {
|
surge = new ArtilleryBulletType(3f, 0, "shell"){
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import io.anuke.mindustry.entities.bullet.BulletType;
|
|||||||
import io.anuke.mindustry.game.Content;
|
import io.anuke.mindustry.game.Content;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
|
|
||||||
public abstract class BulletList implements ContentList {
|
public abstract class BulletList implements ContentList{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return BulletType.all();
|
return BulletType.all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,34 +4,34 @@ import io.anuke.mindustry.entities.bullet.BasicBulletType;
|
|||||||
import io.anuke.mindustry.entities.bullet.BulletType;
|
import io.anuke.mindustry.entities.bullet.BulletType;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
|
|
||||||
public class FlakBullets extends BulletList implements ContentList {
|
public class FlakBullets extends BulletList implements ContentList{
|
||||||
public static BulletType lead, plastic, explosive, surge;
|
public static BulletType lead, plastic, explosive, surge;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
lead = new BasicBulletType(3f, 5, "bullet") {
|
lead = new BasicBulletType(3f, 5, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 7f;
|
bulletWidth = 7f;
|
||||||
bulletHeight = 9f;
|
bulletHeight = 9f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
plastic = new BasicBulletType(3f, 5, "bullet") {
|
plastic = new BasicBulletType(3f, 5, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 7f;
|
bulletWidth = 7f;
|
||||||
bulletHeight = 9f;
|
bulletHeight = 9f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
explosive = new BasicBulletType(3f, 5, "bullet") {
|
explosive = new BasicBulletType(3f, 5, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 7f;
|
bulletWidth = 7f;
|
||||||
bulletHeight = 9f;
|
bulletHeight = 9f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
surge = new BasicBulletType(3f, 5, "bullet") {
|
surge = new BasicBulletType(3f, 5, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 7f;
|
bulletWidth = 7f;
|
||||||
bulletHeight = 9f;
|
bulletHeight = 9f;
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import io.anuke.mindustry.entities.bullet.MissileBulletType;
|
|||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
|
|
||||||
public class MissileBullets extends BulletList implements ContentList {
|
public class MissileBullets extends BulletList implements ContentList{
|
||||||
public static BulletType explosive, incindiary, surge, javelin;
|
public static BulletType explosive, incindiary, surge, javelin;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
explosive = new MissileBulletType(1.8f, 10, "missile") {
|
explosive = new MissileBulletType(1.8f, 10, "missile"){
|
||||||
{
|
{
|
||||||
bulletWidth = 8f;
|
bulletWidth = 8f;
|
||||||
bulletHeight = 8f;
|
bulletHeight = 8f;
|
||||||
@@ -26,7 +26,7 @@ public class MissileBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
incindiary = new MissileBulletType(2f, 12, "missile") {
|
incindiary = new MissileBulletType(2f, 12, "missile"){
|
||||||
{
|
{
|
||||||
frontColor = Palette.lightishOrange;
|
frontColor = Palette.lightishOrange;
|
||||||
backColor = Palette.lightOrange;
|
backColor = Palette.lightOrange;
|
||||||
@@ -44,14 +44,14 @@ public class MissileBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
surge = new MissileBulletType(3f, 5, "bullet") {
|
surge = new MissileBulletType(3f, 5, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 7f;
|
bulletWidth = 7f;
|
||||||
bulletHeight = 9f;
|
bulletHeight = 9f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
javelin = new MissileBulletType(2.5f, 10, "missile") {
|
javelin = new MissileBulletType(2.5f, 10, "missile"){
|
||||||
{
|
{
|
||||||
bulletWidth = 8f;
|
bulletWidth = 8f;
|
||||||
bulletHeight = 8f;
|
bulletHeight = 8f;
|
||||||
|
|||||||
@@ -5,27 +5,27 @@ import io.anuke.mindustry.entities.bullet.BulletType;
|
|||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
|
|
||||||
public class StandardBullets extends BulletList implements ContentList {
|
public class StandardBullets extends BulletList implements ContentList{
|
||||||
public static BulletType tungsten, lead, carbide, thorium, homing, tracer;
|
public static BulletType tungsten, lead, carbide, thorium, homing, tracer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
tungsten = new BasicBulletType(3.2f, 10, "bullet") {
|
tungsten = new BasicBulletType(3.2f, 10, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 9f;
|
bulletWidth = 9f;
|
||||||
bulletHeight = 11f;
|
bulletHeight = 11f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
lead = new BasicBulletType(2.5f, 5, "bullet") {
|
lead = new BasicBulletType(2.5f, 5, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 7f;
|
bulletWidth = 7f;
|
||||||
bulletHeight = 9f;
|
bulletHeight = 9f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
carbide = new BasicBulletType(3.5f, 18, "bullet") {
|
carbide = new BasicBulletType(3.5f, 18, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 9f;
|
bulletWidth = 9f;
|
||||||
bulletHeight = 12f;
|
bulletHeight = 12f;
|
||||||
@@ -33,7 +33,7 @@ public class StandardBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
thorium = new BasicBulletType(4f, 29, "bullet") {
|
thorium = new BasicBulletType(4f, 29, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 10f;
|
bulletWidth = 10f;
|
||||||
bulletHeight = 13f;
|
bulletHeight = 13f;
|
||||||
@@ -41,7 +41,7 @@ public class StandardBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
homing = new BasicBulletType(3f, 9, "bullet") {
|
homing = new BasicBulletType(3f, 9, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 7f;
|
bulletWidth = 7f;
|
||||||
bulletHeight = 9f;
|
bulletHeight = 9f;
|
||||||
@@ -49,7 +49,7 @@ public class StandardBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tracer = new BasicBulletType(3.2f, 11, "bullet") {
|
tracer = new BasicBulletType(3.2f, 11, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 10f;
|
bulletWidth = 10f;
|
||||||
bulletHeight = 12f;
|
bulletHeight = 12f;
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ import io.anuke.ucore.util.Mathf;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class TurretBullets extends BulletList implements ContentList {
|
public class TurretBullets extends BulletList implements ContentList{
|
||||||
public static BulletType fireball, basicFlame, lancerLaser, fuseShot, waterShot, cryoShot, lavaShot, oilShot, lightning, driverBolt;
|
public static BulletType fireball, basicFlame, lancerLaser, fuseShot, waterShot, cryoShot, lavaShot, oilShot, lightning, driverBolt;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
fireball = new BulletType(1f, 4) {
|
fireball = new BulletType(1f, 4){
|
||||||
{
|
{
|
||||||
pierce = true;
|
pierce = true;
|
||||||
hitTiles = false;
|
hitTiles = false;
|
||||||
@@ -45,12 +45,12 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Bullet b) {
|
public void init(Bullet b){
|
||||||
b.getVelocity().setLength(0.6f + Mathf.random(2f));
|
b.getVelocity().setLength(0.6f + Mathf.random(2f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b) {
|
public void draw(Bullet b){
|
||||||
//TODO add color to the bullet depending on the color of the flame it came from
|
//TODO add color to the bullet depending on the color of the flame it came from
|
||||||
Draw.color(Palette.lightFlame, Palette.darkFlame, Color.GRAY, b.fin());
|
Draw.color(Palette.lightFlame, Palette.darkFlame, Color.GRAY, b.fin());
|
||||||
Fill.circle(b.x, b.y, 3f * b.fout());
|
Fill.circle(b.x, b.y, 3f * b.fout());
|
||||||
@@ -58,25 +58,25 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Bullet b) {
|
public void update(Bullet b){
|
||||||
if (Mathf.chance(0.04 * Timers.delta())) {
|
if(Mathf.chance(0.04 * Timers.delta())){
|
||||||
Tile tile = world.tileWorld(b.x, b.y);
|
Tile tile = world.tileWorld(b.x, b.y);
|
||||||
if (tile != null) {
|
if(tile != null){
|
||||||
Fire.create(tile);
|
Fire.create(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mathf.chance(0.1 * Timers.delta())) {
|
if(Mathf.chance(0.1 * Timers.delta())){
|
||||||
Effects.effect(EnvironmentFx.fireballsmoke, b.x, b.y);
|
Effects.effect(EnvironmentFx.fireballsmoke, b.x, b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mathf.chance(0.1 * Timers.delta())) {
|
if(Mathf.chance(0.1 * Timers.delta())){
|
||||||
Effects.effect(EnvironmentFx.ballfire, b.x, b.y);
|
Effects.effect(EnvironmentFx.ballfire, b.x, b.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
basicFlame = new BulletType(2f, 5) {
|
basicFlame = new BulletType(2f, 5){
|
||||||
{
|
{
|
||||||
hitsize = 7f;
|
hitsize = 7f;
|
||||||
lifetime = 30f;
|
lifetime = 30f;
|
||||||
@@ -88,11 +88,11 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b) {
|
public void draw(Bullet b){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
lancerLaser = new BulletType(0.001f, 110) {
|
lancerLaser = new BulletType(0.001f, 110){
|
||||||
Color[] colors = {Palette.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Palette.lancerLaser, Color.WHITE};
|
Color[] colors = {Palette.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Palette.lancerLaser, Color.WHITE};
|
||||||
float[] tscales = {1f, 0.7f, 0.5f, 0.2f};
|
float[] tscales = {1f, 0.7f, 0.5f, 0.2f};
|
||||||
float[] lenscales = {1f, 1.1f, 1.13f, 1.14f};
|
float[] lenscales = {1f, 1.1f, 1.13f, 1.14f};
|
||||||
@@ -107,19 +107,19 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Bullet b) {
|
public void init(Bullet b){
|
||||||
Damage.collideLine(b, b.getTeam(), hiteffect, b.x, b.y, b.angle(), length);
|
Damage.collideLine(b, b.getTeam(), hiteffect, b.x, b.y, b.angle(), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b) {
|
public void draw(Bullet b){
|
||||||
float f = Mathf.curve(b.fin(), 0f, 0.2f);
|
float f = Mathf.curve(b.fin(), 0f, 0.2f);
|
||||||
float baseLen = length * f;
|
float baseLen = length * f;
|
||||||
|
|
||||||
Lines.lineAngle(b.x, b.y, b.angle(), baseLen);
|
Lines.lineAngle(b.x, b.y, b.angle(), baseLen);
|
||||||
for (int s = 0; s < 3; s++) {
|
for(int s = 0; s < 3; s++){
|
||||||
Draw.color(colors[s]);
|
Draw.color(colors[s]);
|
||||||
for (int i = 0; i < tscales.length; i++) {
|
for(int i = 0; i < tscales.length; i++){
|
||||||
Lines.stroke(7f * b.fout() * (s == 0 ? 1.5f : s == 1 ? 1f : 0.3f) * tscales[i]);
|
Lines.stroke(7f * b.fout() * (s == 0 ? 1.5f : s == 1 ? 1f : 0.3f) * tscales[i]);
|
||||||
Lines.lineAngle(b.x, b.y, b.angle(), baseLen * lenscales[i]);
|
Lines.lineAngle(b.x, b.y, b.angle(), baseLen * lenscales[i]);
|
||||||
}
|
}
|
||||||
@@ -128,24 +128,24 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fuseShot = new BulletType(0.01f, 100) {
|
fuseShot = new BulletType(0.01f, 100){
|
||||||
//TODO
|
//TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
waterShot = new LiquidBulletType(Liquids.water) {
|
waterShot = new LiquidBulletType(Liquids.water){
|
||||||
{
|
{
|
||||||
status = StatusEffects.wet;
|
status = StatusEffects.wet;
|
||||||
statusIntensity = 0.5f;
|
statusIntensity = 0.5f;
|
||||||
knockback = 0.65f;
|
knockback = 0.65f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cryoShot = new LiquidBulletType(Liquids.cryofluid) {
|
cryoShot = new LiquidBulletType(Liquids.cryofluid){
|
||||||
{
|
{
|
||||||
status = StatusEffects.freezing;
|
status = StatusEffects.freezing;
|
||||||
statusIntensity = 0.5f;
|
statusIntensity = 0.5f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
lavaShot = new LiquidBulletType(Liquids.lava) {
|
lavaShot = new LiquidBulletType(Liquids.lava){
|
||||||
{
|
{
|
||||||
damage = 4;
|
damage = 4;
|
||||||
speed = 1.9f;
|
speed = 1.9f;
|
||||||
@@ -154,7 +154,7 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
statusIntensity = 0.5f;
|
statusIntensity = 0.5f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
oilShot = new LiquidBulletType(Liquids.oil) {
|
oilShot = new LiquidBulletType(Liquids.oil){
|
||||||
{
|
{
|
||||||
speed = 2f;
|
speed = 2f;
|
||||||
drag = 0.03f;
|
drag = 0.03f;
|
||||||
@@ -162,7 +162,7 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
statusIntensity = 0.5f;
|
statusIntensity = 0.5f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
lightning = new BulletType(0.001f, 10) {
|
lightning = new BulletType(0.001f, 10){
|
||||||
{
|
{
|
||||||
lifetime = 1;
|
lifetime = 1;
|
||||||
despawneffect = Fx.none;
|
despawneffect = Fx.none;
|
||||||
@@ -170,16 +170,16 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b) {
|
public void draw(Bullet b){
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(Bullet b) {
|
public void init(Bullet b){
|
||||||
Lightning.create(b.getTeam(), hiteffect, Palette.lancerLaser, damage, b.x, b.y, b.angle(), 30);
|
Lightning.create(b.getTeam(), hiteffect, Palette.lancerLaser, damage, b.x, b.y, b.angle(), 30);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
driverBolt = new BulletType(5f, 20) {
|
driverBolt = new BulletType(5f, 20){
|
||||||
{
|
{
|
||||||
collidesTiles = false;
|
collidesTiles = false;
|
||||||
lifetime = 200f;
|
lifetime = 200f;
|
||||||
@@ -189,7 +189,7 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b) {
|
public void draw(Bullet b){
|
||||||
Draw.color(Color.LIGHT_GRAY);
|
Draw.color(Color.LIGHT_GRAY);
|
||||||
Fill.square(b.x, b.y, 3f, b.angle());
|
Fill.square(b.x, b.y, 3f, b.angle());
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Bullet b) {
|
public void update(Bullet b){
|
||||||
//data MUST be an instance of DriverBulletData
|
//data MUST be an instance of DriverBulletData
|
||||||
if(!(b.getData() instanceof DriverBulletData)){
|
if(!(b.getData() instanceof DriverBulletData)){
|
||||||
hit(b);
|
hit(b);
|
||||||
@@ -208,7 +208,7 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
|
|
||||||
float hitDst = 7f;
|
float hitDst = 7f;
|
||||||
|
|
||||||
DriverBulletData data = (DriverBulletData)b.getData();
|
DriverBulletData data = (DriverBulletData) b.getData();
|
||||||
|
|
||||||
//if the target is dead, just keep flying until the bullet explodes
|
//if the target is dead, just keep flying until the bullet explodes
|
||||||
if(data.to.isDead()){
|
if(data.to.isDead()){
|
||||||
@@ -245,15 +245,15 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void despawned(Bullet b) {
|
public void despawned(Bullet b){
|
||||||
super.despawned(b);
|
super.despawned(b);
|
||||||
|
|
||||||
if(!(b.getData() instanceof DriverBulletData)) return;
|
if(!(b.getData() instanceof DriverBulletData)) return;
|
||||||
|
|
||||||
DriverBulletData data = (DriverBulletData)b.getData();
|
DriverBulletData data = (DriverBulletData) b.getData();
|
||||||
data.to.isRecieving = false;
|
data.to.isRecieving = false;
|
||||||
|
|
||||||
for(int i = 0; i < data.items.length; i ++){
|
for(int i = 0; i < data.items.length; i++){
|
||||||
int amountDropped = Mathf.random(0, data.items[i]);
|
int amountDropped = Mathf.random(0, data.items[i]);
|
||||||
if(amountDropped > 0){
|
if(amountDropped > 0){
|
||||||
float angle = b.angle() + Mathf.range(100f);
|
float angle = b.angle() + Mathf.range(100f);
|
||||||
@@ -264,7 +264,7 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hit(Bullet b, float hitx, float hity) {
|
public void hit(Bullet b, float hitx, float hity){
|
||||||
super.hit(b, hitx, hity);
|
super.hit(b, hitx, hity);
|
||||||
despawned(b);
|
despawned(b);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ import io.anuke.ucore.util.Mathf;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class WeaponBullets extends BulletList {
|
public class WeaponBullets extends BulletList{
|
||||||
public static BulletType tungstenShotgun, bombExplosive, bombIncendiary, bombOil, shellCarbide;
|
public static BulletType tungstenShotgun, bombExplosive, bombIncendiary, bombOil, shellCarbide;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
tungstenShotgun = new BasicBulletType(5f, 8, "bullet") {
|
tungstenShotgun = new BasicBulletType(5f, 8, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 8f;
|
bulletWidth = 8f;
|
||||||
bulletHeight = 9f;
|
bulletHeight = 9f;
|
||||||
@@ -49,10 +49,10 @@ public class WeaponBullets extends BulletList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hit(Bullet b, float x, float y) {
|
public void hit(Bullet b, float x, float y){
|
||||||
super.hit(b, x, y);
|
super.hit(b, x, y);
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for(int i = 0; i < 3; i++){
|
||||||
float cx = x + Mathf.range(10f);
|
float cx = x + Mathf.range(10f);
|
||||||
float cy = y + Mathf.range(10f);
|
float cy = y + Mathf.range(10f);
|
||||||
Tile tile = world.tileWorld(cx, cy);
|
Tile tile = world.tileWorld(cx, cy);
|
||||||
@@ -73,17 +73,17 @@ public class WeaponBullets extends BulletList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hit(Bullet b, float x, float y) {
|
public void hit(Bullet b, float x, float y){
|
||||||
super.hit(b, x, y);
|
super.hit(b, x, y);
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for(int i = 0; i < 3; i++){
|
||||||
Tile tile = world.tileWorld(x + Mathf.range(8f), y + Mathf.range(8f));
|
Tile tile = world.tileWorld(x + Mathf.range(8f), y + Mathf.range(8f));
|
||||||
Puddle.deposit(tile, Liquids.oil, 5f);
|
Puddle.deposit(tile, Liquids.oil, 5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
shellCarbide = new BasicBulletType(3.4f, 20, "bullet") {
|
shellCarbide = new BasicBulletType(3.4f, 20, "bullet"){
|
||||||
{
|
{
|
||||||
bulletWidth = 10f;
|
bulletWidth = 10f;
|
||||||
bulletHeight = 12f;
|
bulletHeight = 12f;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class BlockFx extends FxList implements ContentList{
|
|||||||
public static Effect reactorsmoke, nuclearsmoke, nuclearcloud, redgeneratespark, generatespark, fuelburn, plasticburn, pulverize, pulverizeRed, pulverizeRedder, pulverizeSmall, pulverizeMedium, producesmoke, smeltsmoke, formsmoke, blastsmoke, lava, dooropen, doorclose, dooropenlarge, doorcloselarge, purify, purifyoil, purifystone, generate, mine, mineBig, mineHuge, smelt, teleportActivate, teleport, teleportOut, ripple, bubble;
|
public static Effect reactorsmoke, nuclearsmoke, nuclearcloud, redgeneratespark, generatespark, fuelburn, plasticburn, pulverize, pulverizeRed, pulverizeRedder, pulverizeSmall, pulverizeMedium, producesmoke, smeltsmoke, formsmoke, blastsmoke, lava, dooropen, doorclose, dooropenlarge, doorcloselarge, purify, purifyoil, purifystone, generate, mine, mineBig, mineHuge, smelt, teleportActivate, teleport, teleportOut, ripple, bubble;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
reactorsmoke = new Effect(17, e -> {
|
reactorsmoke = new Effect(17, e -> {
|
||||||
Angles.randLenVectors(e.id, 4, e.fin() * 8f, (x, y) -> {
|
Angles.randLenVectors(e.id, 4, e.fin() * 8f, (x, y) -> {
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ import io.anuke.ucore.graphics.Lines;
|
|||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class BulletFx extends FxList implements ContentList {
|
public class BulletFx extends FxList implements ContentList{
|
||||||
public static Effect hitBulletSmall, hitBulletBig, hitFlameSmall, hitLiquid, hitLancer, despawn, flakExplosion, blastExplosion, plasticExplosion,
|
public static Effect hitBulletSmall, hitBulletBig, hitFlameSmall, hitLiquid, hitLancer, despawn, flakExplosion, blastExplosion, plasticExplosion,
|
||||||
artilleryTrail, incendTrail, missileTrail;
|
artilleryTrail, incendTrail, missileTrail;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
hitBulletSmall = new Effect(14, e -> {
|
hitBulletSmall = new Effect(14, e -> {
|
||||||
Draw.color(Color.WHITE, Palette.lightOrange, e.fin());
|
Draw.color(Color.WHITE, Palette.lightOrange, e.fin());
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import io.anuke.ucore.graphics.Fill;
|
|||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class EnvironmentFx extends FxList implements ContentList {
|
public class EnvironmentFx extends FxList implements ContentList{
|
||||||
public static Effect burning, fire, smoke, steam, fireballsmoke, ballfire, freezing, melting, wet, oily;
|
public static Effect burning, fire, smoke, steam, fireballsmoke, ballfire, freezing, melting, wet, oily;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
burning = new Effect(35f, e -> {
|
burning = new Effect(35f, e -> {
|
||||||
Draw.color(Palette.lightFlame, Palette.darkFlame, e.fin());
|
Draw.color(Palette.lightFlame, Palette.darkFlame, e.fin());
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import io.anuke.ucore.graphics.Lines;
|
|||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class ExplosionFx extends FxList implements ContentList {
|
public class ExplosionFx extends FxList implements ContentList{
|
||||||
public static Effect shockwave, bigShockwave, nuclearShockwave, explosion, blockExplosion, blockExplosionSmoke;
|
public static Effect shockwave, bigShockwave, nuclearShockwave, explosion, blockExplosion, blockExplosionSmoke;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
shockwave = new Effect(10f, 80f, e -> {
|
shockwave = new Effect(10f, 80f, e -> {
|
||||||
Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin());
|
Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin());
|
||||||
|
|||||||
@@ -11,59 +11,59 @@ import io.anuke.ucore.util.Angles;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.tilesize;
|
import static io.anuke.mindustry.Vars.tilesize;
|
||||||
|
|
||||||
public class Fx extends FxList implements ContentList {
|
public class Fx extends FxList implements ContentList{
|
||||||
public static Effect none, placeBlock, breakBlock, smoke, spawn, tapBlock, select;
|
public static Effect none, placeBlock, breakBlock, smoke, spawn, tapBlock, select;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
none = new Effect(0, 0f, e -> {
|
none = new Effect(0, 0f, e -> {
|
||||||
});
|
});
|
||||||
|
|
||||||
placeBlock = new Effect(16, e -> {
|
placeBlock = new Effect(16, e -> {
|
||||||
Draw.color(Palette.accent);
|
Draw.color(Palette.accent);
|
||||||
Lines.stroke(3f - e.fin() * 2f);
|
Lines.stroke(3f - e.fin() * 2f);
|
||||||
Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f);
|
Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
tapBlock = new Effect(12, e -> {
|
tapBlock = new Effect(12, e -> {
|
||||||
Draw.color(Palette.accent);
|
Draw.color(Palette.accent);
|
||||||
Lines.stroke(3f - e.fin() * 2f);
|
Lines.stroke(3f - e.fin() * 2f);
|
||||||
Lines.circle(e.x, e.y, 4f + (tilesize/1.5f * e.rotation) * e.fin());
|
Lines.circle(e.x, e.y, 4f + (tilesize / 1.5f * e.rotation) * e.fin());
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
breakBlock = new Effect(12, e -> {
|
breakBlock = new Effect(12, e -> {
|
||||||
Draw.color(Palette.remove);
|
Draw.color(Palette.remove);
|
||||||
Lines.stroke(3f - e.fin() * 2f);
|
Lines.stroke(3f - e.fin() * 2f);
|
||||||
Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f);
|
Lines.square(e.x, e.y, tilesize / 2f * e.rotation + e.fin() * 3f);
|
||||||
|
|
||||||
Angles.randLenVectors(e.id, 3 + (int) (e.rotation * 3), e.rotation * 2f + (tilesize * e.rotation) * e.finpow(), (x, y) -> {
|
Angles.randLenVectors(e.id, 3 + (int) (e.rotation * 3), e.rotation * 2f + (tilesize * e.rotation) * e.finpow(), (x, y) -> {
|
||||||
Fill.square(e.x + x, e.y + y, 1f + e.fout() * (3f + e.rotation));
|
Fill.square(e.x + x, e.y + y, 1f + e.fout() * (3f + e.rotation));
|
||||||
});
|
});
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
select = new Effect(23, e -> {
|
select = new Effect(23, e -> {
|
||||||
Draw.color(Palette.accent);
|
Draw.color(Palette.accent);
|
||||||
Lines.stroke(e.fout() * 3f);
|
Lines.stroke(e.fout() * 3f);
|
||||||
Lines.circle(e.x, e.y, 3f + e.fin() * 14f);
|
Lines.circle(e.x, e.y, 3f + e.fin() * 14f);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
smoke = new Effect(100, e -> {
|
smoke = new Effect(100, e -> {
|
||||||
Draw.color(Color.GRAY, Palette.darkishGray, e.fin());
|
Draw.color(Color.GRAY, Palette.darkishGray, e.fin());
|
||||||
float size = 7f - e.fin() * 7f;
|
float size = 7f - e.fin() * 7f;
|
||||||
Draw.rect("circle", e.x, e.y, size, size);
|
Draw.rect("circle", e.x, e.y, size, size);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
spawn = new Effect(23, e -> {
|
spawn = new Effect(23, e -> {
|
||||||
Lines.stroke(2f * e.fout());
|
Lines.stroke(2f * e.fout());
|
||||||
Draw.color(Palette.accent);
|
Draw.color(Palette.accent);
|
||||||
Lines.poly(e.x, e.y, 4, 3f + e.fin() * 8f);
|
Lines.poly(e.x, e.y, 4, 3f + e.fin() * 8f);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import io.anuke.mindustry.type.ContentList;
|
|||||||
public abstract class FxList implements ContentList{
|
public abstract class FxList implements ContentList{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public Array<? extends Content> getAll(){
|
||||||
return Array.with();
|
return Array.with();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import io.anuke.ucore.graphics.Shapes;
|
|||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class ShootFx extends FxList implements ContentList {
|
public class ShootFx extends FxList implements ContentList{
|
||||||
public static Effect shootSmall, shootSmallSmoke, shootBig, shootBig2, shootBigSmoke, shootBigSmoke2, shootSmallFlame, shootLiquid, shellEjectSmall, shellEjectMedium, shellEjectBig, lancerLaserShoot, lancerLaserShootSmoke, lancerLaserCharge, lancerLaserChargeBegin, lightningCharge, lightningShoot;
|
public static Effect shootSmall, shootSmallSmoke, shootBig, shootBig2, shootBigSmoke, shootBigSmoke2, shootSmallFlame, shootLiquid, shellEjectSmall, shellEjectMedium, shellEjectBig, lancerLaserShoot, lancerLaserShootSmoke, lancerLaserCharge, lancerLaserChargeBegin, lightningCharge, lightningShoot;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
shootSmall = new Effect(8, e -> {
|
shootSmall = new Effect(8, e -> {
|
||||||
Draw.color(Palette.lighterOrange, Palette.lightOrange, e.fin());
|
Draw.color(Palette.lighterOrange, Palette.lightOrange, e.fin());
|
||||||
@@ -111,7 +111,7 @@ public class ShootFx extends FxList implements ContentList {
|
|||||||
shellEjectMedium = new GroundEffect(34f, 400f, e -> {
|
shellEjectMedium = new GroundEffect(34f, 400f, e -> {
|
||||||
Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin());
|
Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin());
|
||||||
float rot = e.rotation + 90f;
|
float rot = e.rotation + 90f;
|
||||||
for (int i : Mathf.signs) {
|
for(int i : Mathf.signs){
|
||||||
float len = (2f + e.finpow() * 10f) * i;
|
float len = (2f + e.finpow() * 10f) * i;
|
||||||
float lr = rot + e.fin() * 20f * i;
|
float lr = rot + e.fin() * 20f * i;
|
||||||
Draw.rect("casing",
|
Draw.rect("casing",
|
||||||
@@ -122,7 +122,7 @@ public class ShootFx extends FxList implements ContentList {
|
|||||||
|
|
||||||
Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin());
|
Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin());
|
||||||
|
|
||||||
for (int i : Mathf.signs) {
|
for(int i : Mathf.signs){
|
||||||
Angles.randLenVectors(e.id, 4, 1f + e.finpow() * 11f, e.rotation + 90f * i, 20f, (x, y) -> {
|
Angles.randLenVectors(e.id, 4, 1f + e.finpow() * 11f, e.rotation + 90f * i, 20f, (x, y) -> {
|
||||||
Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f);
|
Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f);
|
||||||
});
|
});
|
||||||
@@ -134,7 +134,7 @@ public class ShootFx extends FxList implements ContentList {
|
|||||||
shellEjectBig = new GroundEffect(22f, 400f, e -> {
|
shellEjectBig = new GroundEffect(22f, 400f, e -> {
|
||||||
Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin());
|
Draw.color(Palette.lightOrange, Color.LIGHT_GRAY, Palette.lightishGray, e.fin());
|
||||||
float rot = e.rotation + 90f;
|
float rot = e.rotation + 90f;
|
||||||
for (int i : Mathf.signs) {
|
for(int i : Mathf.signs){
|
||||||
float len = (4f + e.finpow() * 8f) * i;
|
float len = (4f + e.finpow() * 8f) * i;
|
||||||
float lr = rot + Mathf.randomSeedRange(e.id + i + 6, 20f * e.fin()) * i;
|
float lr = rot + Mathf.randomSeedRange(e.id + i + 6, 20f * e.fin()) * i;
|
||||||
Draw.rect("casing",
|
Draw.rect("casing",
|
||||||
@@ -146,7 +146,7 @@ public class ShootFx extends FxList implements ContentList {
|
|||||||
|
|
||||||
Draw.color(Color.LIGHT_GRAY);
|
Draw.color(Color.LIGHT_GRAY);
|
||||||
|
|
||||||
for (int i : Mathf.signs) {
|
for(int i : Mathf.signs){
|
||||||
Angles.randLenVectors(e.id, 4, -e.finpow() * 15f, e.rotation + 90f * i, 25f, (x, y) -> {
|
Angles.randLenVectors(e.id, 4, -e.finpow() * 15f, e.rotation + 90f * i, 25f, (x, y) -> {
|
||||||
Fill.circle(e.x + x, e.y + y, e.fout() * 2f);
|
Fill.circle(e.x + x, e.y + y, e.fout() * 2f);
|
||||||
});
|
});
|
||||||
@@ -158,7 +158,7 @@ public class ShootFx extends FxList implements ContentList {
|
|||||||
lancerLaserShoot = new Effect(21f, e -> {
|
lancerLaserShoot = new Effect(21f, e -> {
|
||||||
Draw.color(Palette.lancerLaser);
|
Draw.color(Palette.lancerLaser);
|
||||||
|
|
||||||
for (int i : Mathf.signs) {
|
for(int i : Mathf.signs){
|
||||||
Shapes.tri(e.x, e.y, 4f * e.fout(), 29f, e.rotation + 90f * i);
|
Shapes.tri(e.x, e.y, 4f * e.fout(), 29f, e.rotation + 90f * i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ import io.anuke.ucore.graphics.Lines;
|
|||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class UnitFx extends FxList implements ContentList {
|
public class UnitFx extends FxList implements ContentList{
|
||||||
public static Effect vtolHover, unitDrop, unitPickup, pickup;
|
public static Effect vtolHover, unitDrop, unitPickup, pickup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
|
|
||||||
vtolHover = new Effect(40f, e -> {
|
vtolHover = new Effect(40f, e -> {
|
||||||
float len = e.finpow() * 10f;
|
float len = e.finpow() * 10f;
|
||||||
|
|||||||
@@ -25,76 +25,80 @@ import io.anuke.ucore.core.Effects;
|
|||||||
import io.anuke.ucore.function.Consumer;
|
import io.anuke.ucore.function.Consumer;
|
||||||
import io.anuke.ucore.util.Log;
|
import io.anuke.ucore.util.Log;
|
||||||
|
|
||||||
/**Loads all game content.
|
/**
|
||||||
* Call load() before doing anything with content.*/
|
* Loads all game content.
|
||||||
public class ContentLoader {
|
* Call load() before doing anything with content.
|
||||||
|
*/
|
||||||
|
public class ContentLoader{
|
||||||
private static boolean loaded = false;
|
private static boolean loaded = false;
|
||||||
private static ObjectSet<Array<? extends Content>> contentSet = new OrderedSet<>();
|
private static ObjectSet<Array<? extends Content>> contentSet = new OrderedSet<>();
|
||||||
private static OrderedMap<String, Array<Content>> contentMap = new OrderedMap<>();
|
private static OrderedMap<String, Array<Content>> contentMap = new OrderedMap<>();
|
||||||
private static ObjectSet<Consumer<Content>> initialization = new ObjectSet<>();
|
private static ObjectSet<Consumer<Content>> initialization = new ObjectSet<>();
|
||||||
private static ContentList[] content = {
|
private static ContentList[] content = {
|
||||||
//effects
|
//effects
|
||||||
new BlockFx(),
|
new BlockFx(),
|
||||||
new BulletFx(),
|
new BulletFx(),
|
||||||
new EnvironmentFx(),
|
new EnvironmentFx(),
|
||||||
new ExplosionFx(),
|
new ExplosionFx(),
|
||||||
new Fx(),
|
new Fx(),
|
||||||
new ShootFx(),
|
new ShootFx(),
|
||||||
new UnitFx(),
|
new UnitFx(),
|
||||||
|
|
||||||
//items
|
//items
|
||||||
new Items(),
|
new Items(),
|
||||||
|
|
||||||
//status effects
|
//status effects
|
||||||
new StatusEffects(),
|
new StatusEffects(),
|
||||||
|
|
||||||
//liquids
|
//liquids
|
||||||
new Liquids(),
|
new Liquids(),
|
||||||
|
|
||||||
//bullets
|
//bullets
|
||||||
new ArtilleryBullets(),
|
new ArtilleryBullets(),
|
||||||
new FlakBullets(),
|
new FlakBullets(),
|
||||||
new MissileBullets(),
|
new MissileBullets(),
|
||||||
new StandardBullets(),
|
new StandardBullets(),
|
||||||
new TurretBullets(),
|
new TurretBullets(),
|
||||||
new WeaponBullets(),
|
new WeaponBullets(),
|
||||||
|
|
||||||
|
|
||||||
//ammotypes
|
//ammotypes
|
||||||
new AmmoTypes(),
|
new AmmoTypes(),
|
||||||
|
|
||||||
//weapons
|
//weapons
|
||||||
new Weapons(),
|
new Weapons(),
|
||||||
|
|
||||||
//mechs
|
//mechs
|
||||||
new Mechs(),
|
new Mechs(),
|
||||||
|
|
||||||
//units
|
//units
|
||||||
new UnitTypes(),
|
new UnitTypes(),
|
||||||
|
|
||||||
//blocks
|
//blocks
|
||||||
new Blocks(),
|
new Blocks(),
|
||||||
new DefenseBlocks(),
|
new DefenseBlocks(),
|
||||||
new DistributionBlocks(),
|
new DistributionBlocks(),
|
||||||
new ProductionBlocks(),
|
new ProductionBlocks(),
|
||||||
new TurretBlocks(),
|
new TurretBlocks(),
|
||||||
new DebugBlocks(),
|
new DebugBlocks(),
|
||||||
new LiquidBlocks(),
|
new LiquidBlocks(),
|
||||||
new StorageBlocks(),
|
new StorageBlocks(),
|
||||||
new UnitBlocks(),
|
new UnitBlocks(),
|
||||||
new PowerBlocks(),
|
new PowerBlocks(),
|
||||||
new CraftingBlocks(),
|
new CraftingBlocks(),
|
||||||
new UpgradeBlocks(),
|
new UpgradeBlocks(),
|
||||||
new OreBlocks(),
|
new OreBlocks(),
|
||||||
|
|
||||||
//not really a content class, but this makes initialization easier
|
//not really a content class, but this makes initialization easier
|
||||||
new ColorMapper(),
|
new ColorMapper(),
|
||||||
|
|
||||||
//recipes
|
//recipes
|
||||||
new Recipes(),
|
new Recipes(),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**Creates all content types.*/
|
/**
|
||||||
|
* Creates all content types.
|
||||||
|
*/
|
||||||
public static void load(){
|
public static void load(){
|
||||||
if(loaded){
|
if(loaded){
|
||||||
Log.info("Content already loaded, skipping.");
|
Log.info("Content already loaded, skipping.");
|
||||||
@@ -103,11 +107,11 @@ public class ContentLoader {
|
|||||||
|
|
||||||
registerTypes();
|
registerTypes();
|
||||||
|
|
||||||
for (ContentList list : content){
|
for(ContentList list : content){
|
||||||
list.load();
|
list.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ContentList list : content){
|
for(ContentList list : content){
|
||||||
if(list.getAll().size != 0){
|
if(list.getAll().size != 0){
|
||||||
String type = list.getAll().first().getContentTypeName();
|
String type = list.getAll().first().getContentTypeName();
|
||||||
|
|
||||||
@@ -134,7 +138,9 @@ public class ContentLoader {
|
|||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Initializes all content with the specified function.*/
|
/**
|
||||||
|
* Initializes all content with the specified function.
|
||||||
|
*/
|
||||||
public static void initialize(Consumer<Content> callable){
|
public static void initialize(Consumer<Content> callable){
|
||||||
if(initialization.contains(callable)) return;
|
if(initialization.contains(callable)) return;
|
||||||
|
|
||||||
@@ -155,8 +161,10 @@ public class ContentLoader {
|
|||||||
return contentMap;
|
return contentMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Registers sync IDs for all types of sync entities.
|
/**
|
||||||
* Do not register units here!*/
|
* Registers sync IDs for all types of sync entities.
|
||||||
|
* Do not register units here!
|
||||||
|
*/
|
||||||
private static void registerTypes(){
|
private static void registerTypes(){
|
||||||
TypeTrait.registerType(Player.class, Player::new);
|
TypeTrait.registerType(Player.class, Player::new);
|
||||||
TypeTrait.registerType(ItemDrop.class, ItemDrop::new);
|
TypeTrait.registerType(ItemDrop.class, ItemDrop::new);
|
||||||
|
|||||||
@@ -30,148 +30,152 @@ import io.anuke.ucore.util.Atlas;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
/**Control module.
|
/**
|
||||||
|
* Control module.
|
||||||
* Handles all input, saving, keybinds and keybinds.
|
* Handles all input, saving, keybinds and keybinds.
|
||||||
* Should <i>not</i> handle any logic-critical state.
|
* Should <i>not</i> handle any logic-critical state.
|
||||||
* This class is not created in the headless server.*/
|
* This class is not created in the headless server.
|
||||||
|
*/
|
||||||
public class Control extends Module{
|
public class Control extends Module{
|
||||||
/**Minimum period of time between the same sound being played.*/
|
/**
|
||||||
private static final long minSoundPeriod = 100;
|
* Minimum period of time between the same sound being played.
|
||||||
|
*/
|
||||||
|
private static final long minSoundPeriod = 100;
|
||||||
|
|
||||||
private boolean hiscore = false;
|
private boolean hiscore = false;
|
||||||
private boolean wasPaused = false;
|
private boolean wasPaused = false;
|
||||||
private Saves saves;
|
private Saves saves;
|
||||||
private ContentDatabase db;
|
private ContentDatabase db;
|
||||||
private InputHandler[] inputs = {};
|
private InputHandler[] inputs = {};
|
||||||
private ObjectMap<Sound, Long> soundMap = new ObjectMap<>();
|
private ObjectMap<Sound, Long> soundMap = new ObjectMap<>();
|
||||||
|
|
||||||
private Throwable error;
|
private Throwable error;
|
||||||
private Input gdxInput;
|
private Input gdxInput;
|
||||||
|
|
||||||
public Control(){
|
public Control(){
|
||||||
|
|
||||||
saves = new Saves();
|
saves = new Saves();
|
||||||
db = new ContentDatabase();
|
db = new ContentDatabase();
|
||||||
|
|
||||||
Inputs.useControllers(!gwt);
|
Inputs.useControllers(!gwt);
|
||||||
|
|
||||||
Gdx.input.setCatchBackKey(true);
|
Gdx.input.setCatchBackKey(true);
|
||||||
|
|
||||||
Effects.setShakeFalloff(10000f);
|
Effects.setShakeFalloff(10000f);
|
||||||
|
|
||||||
ContentLoader.initialize(Content::init);
|
ContentLoader.initialize(Content::init);
|
||||||
Core.atlas = new Atlas("sprites.atlas");
|
Core.atlas = new Atlas("sprites.atlas");
|
||||||
Core.atlas.setErrorRegion("error");
|
Core.atlas.setErrorRegion("error");
|
||||||
ContentLoader.initialize(Content::load);
|
ContentLoader.initialize(Content::load);
|
||||||
|
|
||||||
db.load();
|
db.load();
|
||||||
|
|
||||||
gdxInput = Gdx.input;
|
gdxInput = Gdx.input;
|
||||||
|
|
||||||
Sounds.load("shoot.mp3", "place.mp3", "explosion.mp3", "enemyshoot.mp3",
|
Sounds.load("shoot.mp3", "place.mp3", "explosion.mp3", "enemyshoot.mp3",
|
||||||
"corexplode.mp3", "break.mp3", "spawn.mp3", "flame.mp3", "die.mp3",
|
"corexplode.mp3", "break.mp3", "spawn.mp3", "flame.mp3", "die.mp3",
|
||||||
"respawn.mp3", "purchase.mp3", "flame2.mp3", "bigshot.mp3", "laser.mp3", "lasershot.mp3",
|
"respawn.mp3", "purchase.mp3", "flame2.mp3", "bigshot.mp3", "laser.mp3", "lasershot.mp3",
|
||||||
"ping.mp3", "tesla.mp3", "waveend.mp3", "railgun.mp3", "blast.mp3", "bang2.mp3");
|
"ping.mp3", "tesla.mp3", "waveend.mp3", "railgun.mp3", "blast.mp3", "bang2.mp3");
|
||||||
|
|
||||||
Sounds.setFalloff(9000f);
|
Sounds.setFalloff(9000f);
|
||||||
Sounds.setPlayer((sound, volume) -> {
|
Sounds.setPlayer((sound, volume) -> {
|
||||||
long time = TimeUtils.millis();
|
long time = TimeUtils.millis();
|
||||||
long value = soundMap.get(sound, 0L);
|
long value = soundMap.get(sound, 0L);
|
||||||
|
|
||||||
if(TimeUtils.timeSinceMillis(value) >= minSoundPeriod){
|
if(TimeUtils.timeSinceMillis(value) >= minSoundPeriod){
|
||||||
threads.run(() -> sound.play(volume));
|
threads.run(() -> sound.play(volume));
|
||||||
soundMap.put(sound, time);
|
soundMap.put(sound, time);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3", "5.mp3", "6.mp3");
|
Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3", "5.mp3", "6.mp3");
|
||||||
|
|
||||||
DefaultKeybinds.load();
|
DefaultKeybinds.load();
|
||||||
|
|
||||||
Settings.defaultList(
|
Settings.defaultList(
|
||||||
"ip", "localhost",
|
"ip", "localhost",
|
||||||
"port", port+"",
|
"port", port + "",
|
||||||
"color-0", Color.rgba8888(playerColors[8]),
|
"color-0", Color.rgba8888(playerColors[8]),
|
||||||
"color-1", Color.rgba8888(playerColors[11]),
|
"color-1", Color.rgba8888(playerColors[11]),
|
||||||
"color-2", Color.rgba8888(playerColors[13]),
|
"color-2", Color.rgba8888(playerColors[13]),
|
||||||
"color-3", Color.rgba8888(playerColors[9]),
|
"color-3", Color.rgba8888(playerColors[9]),
|
||||||
"name", "player",
|
"name", "player",
|
||||||
"lastBuild", 0
|
"lastBuild", 0
|
||||||
);
|
);
|
||||||
|
|
||||||
KeyBinds.load();
|
KeyBinds.load();
|
||||||
|
|
||||||
addPlayer(0);
|
addPlayer(0);
|
||||||
|
|
||||||
saves.load();
|
saves.load();
|
||||||
|
|
||||||
Events.on(StateChangeEvent.class, (from, to) -> {
|
Events.on(StateChangeEvent.class, (from, to) -> {
|
||||||
if((from == State.playing && to == State.menu) || (from == State.menu && to != State.menu)){
|
if((from == State.playing && to == State.menu) || (from == State.menu && to != State.menu)){
|
||||||
Timers.runTask(5f, Platform.instance::updateRPC);
|
Timers.runTask(5f, Platform.instance::updateRPC);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(PlayEvent.class, () -> {
|
Events.on(PlayEvent.class, () -> {
|
||||||
for(Player player : players){
|
for(Player player : players){
|
||||||
player.add();
|
player.add();
|
||||||
}
|
}
|
||||||
|
|
||||||
state.set(State.playing);
|
state.set(State.playing);
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(WorldLoadGraphicsEvent.class, () -> {
|
Events.on(WorldLoadGraphicsEvent.class, () -> {
|
||||||
if(mobile){
|
if(mobile){
|
||||||
Core.camera.position.set(players[0].x, players[0].y, 0);
|
Core.camera.position.set(players[0].x, players[0].y, 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(ResetEvent.class, () -> {
|
Events.on(ResetEvent.class, () -> {
|
||||||
for(Player player : players){
|
for(Player player : players){
|
||||||
player.reset();
|
player.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
hiscore = false;
|
hiscore = false;
|
||||||
|
|
||||||
saves.resetSave();
|
saves.resetSave();
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(WaveEvent.class, () -> {
|
Events.on(WaveEvent.class, () -> {
|
||||||
|
|
||||||
int last = Settings.getInt("hiscore" + world.getMap().name, 0);
|
int last = Settings.getInt("hiscore" + world.getMap().name, 0);
|
||||||
|
|
||||||
if(state.wave > last && !state.mode.infiniteResources && !state.mode.disableWaveTimer){
|
if(state.wave > last && !state.mode.infiniteResources && !state.mode.disableWaveTimer){
|
||||||
Settings.putInt("hiscore" + world.getMap().name, state.wave);
|
Settings.putInt("hiscore" + world.getMap().name, state.wave);
|
||||||
Settings.save();
|
Settings.save();
|
||||||
hiscore = true;
|
hiscore = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform.instance.updateRPC();
|
Platform.instance.updateRPC();
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(GameOverEvent.class, () -> {
|
Events.on(GameOverEvent.class, () -> {
|
||||||
Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
|
Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
|
||||||
|
|
||||||
//TODO game over effect
|
//TODO game over effect
|
||||||
ui.restart.show();
|
ui.restart.show();
|
||||||
|
|
||||||
Timers.runTask(30f, () -> state.set(State.menu));
|
Timers.runTask(30f, () -> state.set(State.menu));
|
||||||
});
|
});
|
||||||
|
|
||||||
Events.on(WorldLoadEvent.class, () -> threads.runGraphics(() -> Events.fire(WorldLoadGraphicsEvent.class)));
|
Events.on(WorldLoadEvent.class, () -> threads.runGraphics(() -> Events.fire(WorldLoadGraphicsEvent.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPlayer(int index){
|
public void addPlayer(int index){
|
||||||
if(players.length != index + 1){
|
if(players.length != index + 1){
|
||||||
Player[] old = players;
|
Player[] old = players;
|
||||||
players = new Player[index + 1];
|
players = new Player[index + 1];
|
||||||
System.arraycopy(old, 0, players, 0, old.length);
|
System.arraycopy(old, 0, players, 0, old.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inputs.length != index + 1){
|
if(inputs.length != index + 1){
|
||||||
InputHandler[] oldi = inputs;
|
InputHandler[] oldi = inputs;
|
||||||
inputs = new InputHandler[index + 1];
|
inputs = new InputHandler[index + 1];
|
||||||
System.arraycopy(oldi, 0, inputs, 0, oldi.length);
|
System.arraycopy(oldi, 0, inputs, 0, oldi.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
Player setTo = (index == 0 ? null : players[0]);
|
Player setTo = (index == 0 ? null : players[0]);
|
||||||
|
|
||||||
@@ -205,8 +209,8 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removePlayer(){
|
public void removePlayer(){
|
||||||
players[players.length-1].remove();
|
players[players.length - 1].remove();
|
||||||
inputs[inputs.length-1].remove();
|
inputs[inputs.length - 1].remove();
|
||||||
|
|
||||||
Player[] old = players;
|
Player[] old = players;
|
||||||
players = new Player[players.length - 1];
|
players = new Player[players.length - 1];
|
||||||
@@ -217,191 +221,191 @@ public class Control extends Module{
|
|||||||
System.arraycopy(oldi, 0, inputs, 0, inputs.length);
|
System.arraycopy(oldi, 0, inputs, 0, inputs.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentDatabase database() {
|
public ContentDatabase database(){
|
||||||
return db;
|
return db;
|
||||||
}
|
|
||||||
|
|
||||||
public Input gdxInput(){
|
|
||||||
return gdxInput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setError(Throwable error){
|
public Input gdxInput(){
|
||||||
this.error = error;
|
return gdxInput;
|
||||||
}
|
|
||||||
|
|
||||||
public Saves getSaves(){
|
|
||||||
return saves;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputHandler input(int index){
|
|
||||||
return inputs[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void triggerUpdateInput(){
|
|
||||||
//Gdx.input = proxy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playMap(Map map){
|
public void setError(Throwable error){
|
||||||
ui.loadfrag.show();
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
Timers.run(5f, () ->
|
public Saves getSaves(){
|
||||||
threads.run(() -> {
|
return saves;
|
||||||
logic.reset();
|
}
|
||||||
world.loadMap(map);
|
|
||||||
logic.play();
|
|
||||||
|
|
||||||
Gdx.app.postRunnable(ui.loadfrag::hide);
|
public InputHandler input(int index){
|
||||||
}));
|
return inputs[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHighScore(){
|
public void triggerUpdateInput(){
|
||||||
return hiscore;
|
//Gdx.input = proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkUnlockableBlocks(){
|
public void playMap(Map map){
|
||||||
TileEntity entity = players[0].getClosestCore();
|
ui.loadfrag.show();
|
||||||
|
|
||||||
if(entity == null) return;
|
Timers.run(5f, () ->
|
||||||
|
threads.run(() -> {
|
||||||
|
logic.reset();
|
||||||
|
world.loadMap(map);
|
||||||
|
logic.play();
|
||||||
|
|
||||||
entity.items.forEach((item, amount) -> control.database().unlockContent(item));
|
Gdx.app.postRunnable(ui.loadfrag::hide);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
if(players[0].inventory.hasItem()){
|
public boolean isHighScore(){
|
||||||
control.database().unlockContent(players[0].inventory.getItem().item);
|
return hiscore;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0 ; i < Recipe.all().size; i ++){
|
private void checkUnlockableBlocks(){
|
||||||
Recipe recipe = Recipe.all().get(i);
|
TileEntity entity = players[0].getClosestCore();
|
||||||
if(!recipe.debugOnly && entity.items.has(recipe.requirements, 1.4f)){
|
|
||||||
if(control.database().unlockContent(recipe)){
|
|
||||||
ui.hudfrag.showUnlock(recipe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if(entity == null) return;
|
||||||
public void dispose(){
|
|
||||||
Platform.instance.onGameExit();
|
|
||||||
ContentLoader.dispose();
|
|
||||||
Net.dispose();
|
|
||||||
ui.editor.dispose();
|
|
||||||
inputs = new InputHandler[]{};
|
|
||||||
players = new Player[]{};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
entity.items.forEach((item, amount) -> control.database().unlockContent(item));
|
||||||
public void pause(){
|
|
||||||
wasPaused = state.is(State.paused);
|
|
||||||
if(state.is(State.playing)) state.set(State.paused);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if(players[0].inventory.hasItem()){
|
||||||
public void resume(){
|
control.database().unlockContent(players[0].inventory.getItem().item);
|
||||||
if(state.is(State.paused) && !wasPaused){
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < Recipe.all().size; i++){
|
||||||
|
Recipe recipe = Recipe.all().get(i);
|
||||||
|
if(!recipe.debugOnly && entity.items.has(recipe.requirements, 1.4f)){
|
||||||
|
if(control.database().unlockContent(recipe)){
|
||||||
|
ui.hudfrag.showUnlock(recipe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose(){
|
||||||
|
Platform.instance.onGameExit();
|
||||||
|
ContentLoader.dispose();
|
||||||
|
Net.dispose();
|
||||||
|
ui.editor.dispose();
|
||||||
|
inputs = new InputHandler[]{};
|
||||||
|
players = new Player[]{};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pause(){
|
||||||
|
wasPaused = state.is(State.paused);
|
||||||
|
if(state.is(State.playing)) state.set(State.paused);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resume(){
|
||||||
|
if(state.is(State.paused) && !wasPaused){
|
||||||
state.set(State.playing);
|
state.set(State.playing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
EntityPhysics.initPhysics();
|
EntityPhysics.initPhysics();
|
||||||
|
|
||||||
Platform.instance.updateRPC();
|
Platform.instance.updateRPC();
|
||||||
|
|
||||||
if(!Settings.has("4.0-warning")){
|
if(!Settings.has("4.0-warning")){
|
||||||
Settings.putBool("4.0-warning", true);
|
Settings.putBool("4.0-warning", true);
|
||||||
|
|
||||||
Timers.run(5f, () -> {
|
Timers.run(5f, () -> {
|
||||||
FloatingDialog dialog = new FloatingDialog("[orange]WARNING![]");
|
FloatingDialog dialog = new FloatingDialog("[orange]WARNING![]");
|
||||||
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
||||||
dialog.content().add("The beta version you are about to play should be considered very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " +
|
dialog.content().add("The beta version you are about to play should be considered very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " +
|
||||||
"A large portion of content is still unimplemented. \nAll current art and UI is temporary, and will be re-drawn before release. " +
|
"A large portion of content is still unimplemented. \nAll current art and UI is temporary, and will be re-drawn before release. " +
|
||||||
"\n\n[accent]Saves and maps may be corrupted without warning between updates.[] You have been warned!").wrap().width(500f);
|
"\n\n[accent]Saves and maps may be corrupted without warning between updates.[] You have been warned!").wrap().width(500f);
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Settings.has("4.0-no-sound")){
|
if(!Settings.has("4.0-no-sound")){
|
||||||
Settings.putBool("4.0-no-sound", true);
|
Settings.putBool("4.0-no-sound", true);
|
||||||
|
|
||||||
Timers.run(4f, () -> {
|
Timers.run(4f, () -> {
|
||||||
FloatingDialog dialog = new FloatingDialog("[orange]Attention![]");
|
FloatingDialog dialog = new FloatingDialog("[orange]Attention![]");
|
||||||
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
||||||
dialog.content().add("You might have noticed that 4.0 does not have any sound.\nThis is [orange]intentional![] Sound will be added in a later update.\n\n[LIGHT_GRAY](now stop reporting this as a bug)").wrap().width(500f);
|
dialog.content().add("You might have noticed that 4.0 does not have any sound.\nThis is [orange]intentional![] Sound will be added in a later update.\n\n[LIGHT_GRAY](now stop reporting this as a bug)").wrap().width(500f);
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Called from main logic thread.*/
|
/** Called from main logic thread.*/
|
||||||
public void runUpdateLogic(){
|
public void runUpdateLogic(){
|
||||||
if(!state.is(State.menu)) {
|
if(!state.is(State.menu)){
|
||||||
renderer.minimap().updateUnitArray();
|
renderer.minimap().updateUnitArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
|
|
||||||
if(error != null){
|
if(error != null){
|
||||||
throw new RuntimeException(error);
|
throw new RuntimeException(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Inputs.keyTap("console")){
|
if(Inputs.keyTap("console")){
|
||||||
console = !console;
|
console = !console;
|
||||||
}
|
}
|
||||||
|
|
||||||
saves.update();
|
saves.update();
|
||||||
|
|
||||||
triggerUpdateInput();
|
triggerUpdateInput();
|
||||||
|
|
||||||
for(InputHandler inputHandler : inputs){
|
for(InputHandler inputHandler : inputs){
|
||||||
inputHandler.updateController();
|
inputHandler.updateController();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!state.is(State.menu)){
|
if(!state.is(State.menu)){
|
||||||
for(InputHandler input : inputs){
|
for(InputHandler input : inputs){
|
||||||
input.update();
|
input.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
//check unlocks every 2 seconds
|
//check unlocks every 2 seconds
|
||||||
if(!state.mode.infiniteResources && Timers.get("timerCheckUnlock", 120)){
|
if(!state.mode.infiniteResources && Timers.get("timerCheckUnlock", 120)){
|
||||||
checkUnlockableBlocks();
|
checkUnlockableBlocks();
|
||||||
|
|
||||||
//save if the db changed, but don't save unlocks
|
//save if the db changed, but don't save unlocks
|
||||||
if(db.isDirty() && !debug){
|
if(db.isDirty() && !debug){
|
||||||
db.save();
|
db.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Inputs.keyTap("pause") && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){
|
if(Inputs.keyTap("pause") && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){
|
||||||
state.set(state.is(State.playing) ? State.paused : State.playing);
|
state.set(state.is(State.playing) ? State.paused : State.playing);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Inputs.keyTap("menu")){
|
if(Inputs.keyTap("menu")){
|
||||||
if(state.is(State.paused)){
|
if(state.is(State.paused)){
|
||||||
ui.paused.hide();
|
ui.paused.hide();
|
||||||
state.set(State.playing);
|
state.set(State.playing);
|
||||||
}else if (!ui.restart.isShown()){
|
}else if(!ui.restart.isShown()){
|
||||||
if(ui.chatfrag.chatOpen()) {
|
if(ui.chatfrag.chatOpen()){
|
||||||
ui.chatfrag.hide();
|
ui.chatfrag.hide();
|
||||||
}else{
|
}else{
|
||||||
ui.paused.show();
|
ui.paused.show();
|
||||||
state.set(State.paused);
|
state.set(State.paused);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!state.is(State.paused) || Net.active()){
|
if(!state.is(State.paused) || Net.active()){
|
||||||
Entities.update(effectGroup);
|
Entities.update(effectGroup);
|
||||||
Entities.update(groundEffectGroup);
|
Entities.update(groundEffectGroup);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(!state.is(State.paused) || Net.active()){
|
if(!state.is(State.paused) || Net.active()){
|
||||||
Timers.update();
|
Timers.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,31 +8,30 @@ import io.anuke.mindustry.game.TeamInfo;
|
|||||||
import io.anuke.ucore.core.Events;
|
import io.anuke.ucore.core.Events;
|
||||||
|
|
||||||
public class GameState{
|
public class GameState{
|
||||||
private State state = State.menu;
|
public int wave = 1;
|
||||||
|
public float wavetime;
|
||||||
|
public boolean gameOver = false;
|
||||||
|
public GameMode mode = GameMode.waves;
|
||||||
|
public Difficulty difficulty = Difficulty.normal;
|
||||||
|
public boolean friendlyFire;
|
||||||
|
public WaveSpawner spawner = new WaveSpawner();
|
||||||
|
public TeamInfo teams = new TeamInfo();
|
||||||
|
private State state = State.menu;
|
||||||
|
|
||||||
public int wave = 1;
|
public void set(State astate){
|
||||||
public float wavetime;
|
Events.fire(StateChangeEvent.class, state, astate);
|
||||||
public boolean gameOver = false;
|
state = astate;
|
||||||
public GameMode mode = GameMode.waves;
|
}
|
||||||
public Difficulty difficulty = Difficulty.normal;
|
|
||||||
public boolean friendlyFire;
|
|
||||||
public WaveSpawner spawner = new WaveSpawner();
|
|
||||||
public TeamInfo teams = new TeamInfo();
|
|
||||||
|
|
||||||
public void set(State astate){
|
|
||||||
Events.fire(StateChangeEvent.class, state, astate);
|
|
||||||
state = astate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean is(State astate){
|
|
||||||
return state == astate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public State getState(){
|
public boolean is(State astate){
|
||||||
return state;
|
return state == astate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum State{
|
public State getState(){
|
||||||
paused, playing, menu
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum State{
|
||||||
|
paused, playing, menu
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,15 @@ import io.anuke.ucore.modules.Module;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
/**Logic module.
|
/**
|
||||||
|
* Logic module.
|
||||||
* Handles all logic for entities and waves.
|
* Handles all logic for entities and waves.
|
||||||
* Handles game state events.
|
* Handles game state events.
|
||||||
* Does not store any game state itself.
|
* Does not store any game state itself.
|
||||||
*
|
* <p>
|
||||||
* This class should <i>not</i> call any outside methods to change state of modules, but instead fire events.*/
|
* This class should <i>not</i> call any outside methods to change state of modules, but instead fire events.
|
||||||
public class Logic extends Module {
|
*/
|
||||||
|
public class Logic extends Module{
|
||||||
public boolean doUpdate = true;
|
public boolean doUpdate = true;
|
||||||
|
|
||||||
public Logic(){
|
public Logic(){
|
||||||
@@ -49,11 +51,11 @@ public class Logic extends Module {
|
|||||||
|
|
||||||
//fill inventory with items for debugging
|
//fill inventory with items for debugging
|
||||||
|
|
||||||
for (TeamData team : state.teams.getTeams()) {
|
for(TeamData team : state.teams.getTeams()){
|
||||||
for (Tile tile : team.cores) {
|
for(Tile tile : team.cores){
|
||||||
if(debug) {
|
if(debug){
|
||||||
for (Item item : Item.all()) {
|
for(Item item : Item.all()){
|
||||||
if (item.type == ItemType.material) {
|
if(item.type == ItemType.material){
|
||||||
tile.entity.items.add(item, 1000);
|
tile.entity.items.add(item, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +87,7 @@ public class Logic extends Module {
|
|||||||
|
|
||||||
public void runWave(){
|
public void runWave(){
|
||||||
state.spawner.spawnEnemies();
|
state.spawner.spawnEnemies();
|
||||||
state.wave ++;
|
state.wave++;
|
||||||
state.wavetime = wavespace * state.difficulty.timeScaling;
|
state.wavetime = wavespace * state.difficulty.timeScaling;
|
||||||
|
|
||||||
Events.fire(WaveEvent.class);
|
Events.fire(WaveEvent.class);
|
||||||
@@ -137,7 +139,8 @@ public class Logic extends Module {
|
|||||||
runWave();
|
runWave();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Entities.defaultGroup().isEmpty()) throw new RuntimeException("Do not add anything to the default group!");
|
if(!Entities.defaultGroup().isEmpty())
|
||||||
|
throw new RuntimeException("Do not add anything to the default group!");
|
||||||
|
|
||||||
Entities.update(bulletGroup);
|
Entities.update(bulletGroup);
|
||||||
for(EntityGroup group : unitGroups){
|
for(EntityGroup group : unitGroups){
|
||||||
|
|||||||
@@ -36,38 +36,64 @@ import java.util.Random;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class NetClient extends Module {
|
public class NetClient extends Module{
|
||||||
private final static float dataTimeout = 60*18;
|
private final static float dataTimeout = 60 * 18;
|
||||||
private final static float playerSyncTime = 2;
|
private final static float playerSyncTime = 2;
|
||||||
|
|
||||||
private Timer timer = new Timer(5);
|
private Timer timer = new Timer(5);
|
||||||
/**Whether the client is currently connecting.*/
|
/**
|
||||||
|
* Whether the client is currently connecting.
|
||||||
|
*/
|
||||||
private boolean connecting = false;
|
private boolean connecting = false;
|
||||||
/**If true, no message will be shown on disconnect.*/
|
/**
|
||||||
|
* If true, no message will be shown on disconnect.
|
||||||
|
*/
|
||||||
private boolean quiet = false;
|
private boolean quiet = false;
|
||||||
/**Counter for data timeout.*/
|
/**
|
||||||
|
* Counter for data timeout.
|
||||||
|
*/
|
||||||
private float timeoutTime = 0f;
|
private float timeoutTime = 0f;
|
||||||
/**Last sent client snapshot ID.*/
|
/**
|
||||||
|
* Last sent client snapshot ID.
|
||||||
|
*/
|
||||||
private int lastSent;
|
private int lastSent;
|
||||||
|
|
||||||
/**Last snapshot ID recieved.*/
|
/**
|
||||||
|
* Last snapshot ID recieved.
|
||||||
|
*/
|
||||||
private int lastSnapshotBaseID = -1;
|
private int lastSnapshotBaseID = -1;
|
||||||
/**Last snapshot recieved.*/
|
/**
|
||||||
|
* Last snapshot recieved.
|
||||||
|
*/
|
||||||
private byte[] lastSnapshotBase;
|
private byte[] lastSnapshotBase;
|
||||||
/**Current snapshot that is being built from chinks.*/
|
/**
|
||||||
|
* Current snapshot that is being built from chinks.
|
||||||
|
*/
|
||||||
private byte[] currentSnapshot;
|
private byte[] currentSnapshot;
|
||||||
/**Array of recieved chunk statuses.*/
|
/**
|
||||||
|
* Array of recieved chunk statuses.
|
||||||
|
*/
|
||||||
private boolean[] recievedChunks;
|
private boolean[] recievedChunks;
|
||||||
/**Counter of how many chunks have been recieved.*/
|
/**
|
||||||
|
* Counter of how many chunks have been recieved.
|
||||||
|
*/
|
||||||
private int recievedChunkCounter;
|
private int recievedChunkCounter;
|
||||||
/**ID of snapshot that is currently being constructed.*/
|
/**
|
||||||
|
* ID of snapshot that is currently being constructed.
|
||||||
|
*/
|
||||||
private int currentSnapshotID = -1;
|
private int currentSnapshotID = -1;
|
||||||
|
|
||||||
/**Decoder for uncompressing snapshots.*/
|
/**
|
||||||
|
* Decoder for uncompressing snapshots.
|
||||||
|
*/
|
||||||
private DEZDecoder decoder = new DEZDecoder();
|
private DEZDecoder decoder = new DEZDecoder();
|
||||||
/**List of entities that were removed, and need not be added while syncing.*/
|
/**
|
||||||
|
* List of entities that were removed, and need not be added while syncing.
|
||||||
|
*/
|
||||||
private IntSet removed = new IntSet();
|
private IntSet removed = new IntSet();
|
||||||
/**Byte stream for reading in snapshots.*/
|
/**
|
||||||
|
* Byte stream for reading in snapshots.
|
||||||
|
*/
|
||||||
private ReusableByteArrayInputStream byteStream = new ReusableByteArrayInputStream();
|
private ReusableByteArrayInputStream byteStream = new ReusableByteArrayInputStream();
|
||||||
private DataInputStream dataStream = new DataInputStream(byteStream);
|
private DataInputStream dataStream = new DataInputStream(byteStream);
|
||||||
|
|
||||||
@@ -120,7 +146,7 @@ public class NetClient extends Module {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Net.handleClient(Disconnect.class, packet -> {
|
Net.handleClient(Disconnect.class, packet -> {
|
||||||
if (quiet) return;
|
if(quiet) return;
|
||||||
|
|
||||||
Timers.runTask(3f, ui.loadfrag::hide);
|
Timers.runTask(3f, ui.loadfrag::hide);
|
||||||
|
|
||||||
@@ -145,6 +171,166 @@ public class NetClient extends Module {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Remote(variants = Variant.one, priority = PacketPriority.high)
|
||||||
|
public static void onKick(KickReason reason){
|
||||||
|
netClient.disconnectQuietly();
|
||||||
|
state.set(State.menu);
|
||||||
|
if(!reason.quiet) ui.showError("$text.server.kicked." + reason.name());
|
||||||
|
ui.loadfrag.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(variants = Variant.one)
|
||||||
|
public static void onPositionSet(float x, float y){
|
||||||
|
players[0].x = x;
|
||||||
|
players[0].y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(variants = Variant.one)
|
||||||
|
public static void onTraceInfo(TraceInfo info){
|
||||||
|
Player player = playerGroup.getByID(info.playerid);
|
||||||
|
ui.traces.show(player, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote
|
||||||
|
public static void onPlayerDisconnect(int playerid){
|
||||||
|
playerGroup.removeByID(playerid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true)
|
||||||
|
public static void onSnapshot(byte[] chunk, int snapshotID, short chunkID, int totalLength, int base){
|
||||||
|
if(NetServer.showSnapshotSize)
|
||||||
|
Log.info("Recieved snapshot: len {0} ID {1} chunkID {2} totalLength {3} base {4} client-base {5}", chunk.length, snapshotID, chunkID, totalLength, base, netClient.lastSnapshotBaseID);
|
||||||
|
|
||||||
|
//skip snapshot IDs that have already been recieved OR snapshots that are too far in front
|
||||||
|
if(snapshotID < netClient.lastSnapshotBaseID || base != netClient.lastSnapshotBaseID){
|
||||||
|
if(NetServer.showSnapshotSize) Log.info("//SKIP SNAPSHOT");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
byte[] snapshot;
|
||||||
|
|
||||||
|
//total length exceeds that needed to hold one snapshot, therefore, it is split into chunks
|
||||||
|
if(totalLength > NetServer.maxSnapshotSize){
|
||||||
|
//total amount of chunks to recieve
|
||||||
|
int totalChunks = Mathf.ceil((float) totalLength / NetServer.maxSnapshotSize);
|
||||||
|
|
||||||
|
//reset status when a new snapshot sending begins
|
||||||
|
if(netClient.currentSnapshotID != snapshotID){
|
||||||
|
netClient.currentSnapshotID = snapshotID;
|
||||||
|
netClient.currentSnapshot = new byte[totalLength];
|
||||||
|
netClient.recievedChunkCounter = 0;
|
||||||
|
netClient.recievedChunks = new boolean[totalChunks];
|
||||||
|
}
|
||||||
|
|
||||||
|
//if this chunk hasn't been recieved yet...
|
||||||
|
if(!netClient.recievedChunks[chunkID]){
|
||||||
|
netClient.recievedChunks[chunkID] = true;
|
||||||
|
netClient.recievedChunkCounter++; //update recieved status
|
||||||
|
//copy the recieved bytes into the holding array
|
||||||
|
System.arraycopy(chunk, 0, netClient.currentSnapshot, chunkID * NetServer.maxSnapshotSize,
|
||||||
|
Math.min(NetServer.maxSnapshotSize, totalLength - chunkID * NetServer.maxSnapshotSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
//when all chunks have been recieved, begin
|
||||||
|
if(netClient.recievedChunkCounter >= totalChunks){
|
||||||
|
snapshot = netClient.currentSnapshot;
|
||||||
|
}else{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
snapshot = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(NetServer.showSnapshotSize)
|
||||||
|
Log.info("Finished recieving snapshot ID {0} length {1}", snapshotID, chunk.length);
|
||||||
|
|
||||||
|
byte[] result;
|
||||||
|
int length;
|
||||||
|
if(base == -1){ //fresh snapshot
|
||||||
|
result = snapshot;
|
||||||
|
length = snapshot.length;
|
||||||
|
netClient.lastSnapshotBase = Arrays.copyOf(snapshot, snapshot.length);
|
||||||
|
}else{ //otherwise, last snapshot must not be null, decode it
|
||||||
|
if(NetServer.showSnapshotSize)
|
||||||
|
Log.info("Base size: {0} Patch size: {1}", netClient.lastSnapshotBase.length, snapshot.length);
|
||||||
|
netClient.decoder.init(netClient.lastSnapshotBase, snapshot);
|
||||||
|
result = netClient.decoder.decode();
|
||||||
|
length = netClient.decoder.getDecodedLength();
|
||||||
|
//set last snapshot to a copy to prevent issues
|
||||||
|
netClient.lastSnapshotBase = Arrays.copyOf(result, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
netClient.lastSnapshotBaseID = snapshotID;
|
||||||
|
|
||||||
|
//set stream bytes to begin snapshot reaeding
|
||||||
|
netClient.byteStream.setBytes(result, 0, length);
|
||||||
|
|
||||||
|
//get data input for reading from the stream
|
||||||
|
DataInputStream input = netClient.dataStream;
|
||||||
|
|
||||||
|
//read wave info
|
||||||
|
state.wavetime = input.readFloat();
|
||||||
|
state.wave = input.readInt();
|
||||||
|
|
||||||
|
byte cores = input.readByte();
|
||||||
|
for(int i = 0; i < cores; i++){
|
||||||
|
int pos = input.readInt();
|
||||||
|
world.tile(pos).entity.items.read(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
long timestamp = input.readLong();
|
||||||
|
|
||||||
|
byte totalGroups = input.readByte();
|
||||||
|
//for each group...
|
||||||
|
for(int i = 0; i < totalGroups; i++){
|
||||||
|
//read group info
|
||||||
|
byte groupID = input.readByte();
|
||||||
|
short amount = input.readShort();
|
||||||
|
|
||||||
|
EntityGroup group = Entities.getGroup(groupID);
|
||||||
|
|
||||||
|
//go through each entity
|
||||||
|
for(int j = 0; j < amount; j++){
|
||||||
|
int position = netClient.byteStream.position(); //save position to check read/write correctness
|
||||||
|
int id = input.readInt();
|
||||||
|
byte typeID = input.readByte();
|
||||||
|
|
||||||
|
SyncTrait entity = (SyncTrait) group.getByID(id);
|
||||||
|
boolean add = false;
|
||||||
|
|
||||||
|
//entity must not be added yet, so create it
|
||||||
|
if(entity == null){
|
||||||
|
entity = (SyncTrait) TypeTrait.getTypeByID(typeID).get(); //create entity from supplier
|
||||||
|
entity.resetID(id);
|
||||||
|
if(!netClient.isEntityUsed(entity.getID())){
|
||||||
|
add = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//read the entity
|
||||||
|
entity.read(input, timestamp);
|
||||||
|
|
||||||
|
byte readLength = input.readByte();
|
||||||
|
if(netClient.byteStream.position() - position - 1 != readLength){
|
||||||
|
throw new RuntimeException("Error reading entity of type '" + group.getType() + "': Read length mismatch [write=" + readLength + ", read=" + (netClient.byteStream.position() - position - 1) + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(add){
|
||||||
|
entity.add();
|
||||||
|
netClient.addRemovedEntity(entity.getID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//confirm that snapshot has been recieved
|
||||||
|
netClient.lastSnapshotBaseID = snapshotID;
|
||||||
|
|
||||||
|
}catch(Exception e){
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
if(!Net.client()) return;
|
if(!Net.client()) return;
|
||||||
@@ -224,161 +410,4 @@ public class NetClient extends Module {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(variants = Variant.one, priority = PacketPriority.high)
|
|
||||||
public static void onKick(KickReason reason){
|
|
||||||
netClient.disconnectQuietly();
|
|
||||||
state.set(State.menu);
|
|
||||||
if(!reason.quiet) ui.showError("$text.server.kicked." + reason.name());
|
|
||||||
ui.loadfrag.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(variants = Variant.one)
|
|
||||||
public static void onPositionSet(float x, float y){
|
|
||||||
players[0].x = x;
|
|
||||||
players[0].y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(variants = Variant.one)
|
|
||||||
public static void onTraceInfo(TraceInfo info){
|
|
||||||
Player player = playerGroup.getByID(info.playerid);
|
|
||||||
ui.traces.show(player, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote
|
|
||||||
public static void onPlayerDisconnect(int playerid){
|
|
||||||
playerGroup.removeByID(playerid);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true)
|
|
||||||
public static void onSnapshot(byte[] chunk, int snapshotID, short chunkID, int totalLength, int base){
|
|
||||||
if(NetServer.showSnapshotSize) Log.info("Recieved snapshot: len {0} ID {1} chunkID {2} totalLength {3} base {4} client-base {5}", chunk.length, snapshotID, chunkID, totalLength, base, netClient.lastSnapshotBaseID);
|
|
||||||
|
|
||||||
//skip snapshot IDs that have already been recieved OR snapshots that are too far in front
|
|
||||||
if(snapshotID < netClient.lastSnapshotBaseID || base != netClient.lastSnapshotBaseID){
|
|
||||||
if(NetServer.showSnapshotSize) Log.info("//SKIP SNAPSHOT");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
byte[] snapshot;
|
|
||||||
|
|
||||||
//total length exceeds that needed to hold one snapshot, therefore, it is split into chunks
|
|
||||||
if(totalLength > NetServer.maxSnapshotSize) {
|
|
||||||
//total amount of chunks to recieve
|
|
||||||
int totalChunks = Mathf.ceil((float) totalLength / NetServer.maxSnapshotSize);
|
|
||||||
|
|
||||||
//reset status when a new snapshot sending begins
|
|
||||||
if (netClient.currentSnapshotID != snapshotID) {
|
|
||||||
netClient.currentSnapshotID = snapshotID;
|
|
||||||
netClient.currentSnapshot = new byte[totalLength];
|
|
||||||
netClient.recievedChunkCounter = 0;
|
|
||||||
netClient.recievedChunks = new boolean[totalChunks];
|
|
||||||
}
|
|
||||||
|
|
||||||
//if this chunk hasn't been recieved yet...
|
|
||||||
if (!netClient.recievedChunks[chunkID]) {
|
|
||||||
netClient.recievedChunks[chunkID] = true;
|
|
||||||
netClient.recievedChunkCounter ++; //update recieved status
|
|
||||||
//copy the recieved bytes into the holding array
|
|
||||||
System.arraycopy(chunk, 0, netClient.currentSnapshot, chunkID * NetServer.maxSnapshotSize,
|
|
||||||
Math.min(NetServer.maxSnapshotSize, totalLength - chunkID * NetServer.maxSnapshotSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
//when all chunks have been recieved, begin
|
|
||||||
if(netClient.recievedChunkCounter >= totalChunks){
|
|
||||||
snapshot = netClient.currentSnapshot;
|
|
||||||
}else{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
snapshot = chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(NetServer.showSnapshotSize) Log.info("Finished recieving snapshot ID {0} length {1}", snapshotID, chunk.length);
|
|
||||||
|
|
||||||
byte[] result;
|
|
||||||
int length;
|
|
||||||
if (base == -1) { //fresh snapshot
|
|
||||||
result = snapshot;
|
|
||||||
length = snapshot.length;
|
|
||||||
netClient.lastSnapshotBase = Arrays.copyOf(snapshot, snapshot.length);
|
|
||||||
} else { //otherwise, last snapshot must not be null, decode it
|
|
||||||
if(NetServer.showSnapshotSize) Log.info("Base size: {0} Patch size: {1}", netClient.lastSnapshotBase.length, snapshot.length);
|
|
||||||
netClient.decoder.init(netClient.lastSnapshotBase, snapshot);
|
|
||||||
result = netClient.decoder.decode();
|
|
||||||
length = netClient.decoder.getDecodedLength();
|
|
||||||
//set last snapshot to a copy to prevent issues
|
|
||||||
netClient.lastSnapshotBase = Arrays.copyOf(result, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
netClient.lastSnapshotBaseID = snapshotID;
|
|
||||||
|
|
||||||
//set stream bytes to begin snapshot reaeding
|
|
||||||
netClient.byteStream.setBytes(result, 0, length);
|
|
||||||
|
|
||||||
//get data input for reading from the stream
|
|
||||||
DataInputStream input = netClient.dataStream;
|
|
||||||
|
|
||||||
//read wave info
|
|
||||||
state.wavetime = input.readFloat();
|
|
||||||
state.wave = input.readInt();
|
|
||||||
|
|
||||||
byte cores = input.readByte();
|
|
||||||
for (int i = 0; i < cores; i++) {
|
|
||||||
int pos = input.readInt();
|
|
||||||
world.tile(pos).entity.items.read(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
long timestamp = input.readLong();
|
|
||||||
|
|
||||||
byte totalGroups = input.readByte();
|
|
||||||
//for each group...
|
|
||||||
for (int i = 0; i < totalGroups; i++) {
|
|
||||||
//read group info
|
|
||||||
byte groupID = input.readByte();
|
|
||||||
short amount = input.readShort();
|
|
||||||
|
|
||||||
EntityGroup group = Entities.getGroup(groupID);
|
|
||||||
|
|
||||||
//go through each entity
|
|
||||||
for (int j = 0; j < amount; j++) {
|
|
||||||
int position = netClient.byteStream.position(); //save position to check read/write correctness
|
|
||||||
int id = input.readInt();
|
|
||||||
byte typeID = input.readByte();
|
|
||||||
|
|
||||||
SyncTrait entity = (SyncTrait) group.getByID(id);
|
|
||||||
boolean add = false;
|
|
||||||
|
|
||||||
//entity must not be added yet, so create it
|
|
||||||
if(entity == null){
|
|
||||||
entity = (SyncTrait) TypeTrait.getTypeByID(typeID).get(); //create entity from supplier
|
|
||||||
entity.resetID(id);
|
|
||||||
if(!netClient.isEntityUsed(entity.getID())){
|
|
||||||
add = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//read the entity
|
|
||||||
entity.read(input, timestamp);
|
|
||||||
|
|
||||||
byte readLength = input.readByte();
|
|
||||||
if(netClient.byteStream.position() - position - 1 != readLength){
|
|
||||||
throw new RuntimeException("Error reading entity of type '"+ group.getType() + "': Read length mismatch [write=" + readLength + ", read=" + (netClient.byteStream.position() - position - 1)+ "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(add){
|
|
||||||
entity.add();
|
|
||||||
netClient.addRemovedEntity(entity.getID());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//confirm that snapshot has been recieved
|
|
||||||
netClient.lastSnapshotBaseID = snapshotID;
|
|
||||||
|
|
||||||
}catch (Exception e){
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -45,20 +45,30 @@ public class NetServer extends Module{
|
|||||||
private final static byte[] reusableSnapArray = new byte[maxSnapshotSize];
|
private final static byte[] reusableSnapArray = new byte[maxSnapshotSize];
|
||||||
private final static float serverSyncTime = 4, kickDuration = 30 * 1000;
|
private final static float serverSyncTime = 4, kickDuration = 30 * 1000;
|
||||||
private final static Vector2 vector = new Vector2();
|
private final static Vector2 vector = new Vector2();
|
||||||
/**If a play goes away of their server-side coordinates by this distance, they get teleported back.*/
|
/**
|
||||||
|
* If a play goes away of their server-side coordinates by this distance, they get teleported back.
|
||||||
|
*/
|
||||||
private final static float correctDist = 16f;
|
private final static float correctDist = 16f;
|
||||||
|
|
||||||
public final Administration admins = new Administration();
|
public final Administration admins = new Administration();
|
||||||
|
|
||||||
/**Maps connection IDs to players.*/
|
/**
|
||||||
|
* Maps connection IDs to players.
|
||||||
|
*/
|
||||||
private IntMap<Player> connections = new IntMap<>();
|
private IntMap<Player> connections = new IntMap<>();
|
||||||
private boolean closing = false;
|
private boolean closing = false;
|
||||||
|
|
||||||
/**Stream for writing player sync data to.*/
|
/**
|
||||||
|
* Stream for writing player sync data to.
|
||||||
|
*/
|
||||||
private CountableByteArrayOutputStream syncStream = new CountableByteArrayOutputStream();
|
private CountableByteArrayOutputStream syncStream = new CountableByteArrayOutputStream();
|
||||||
/**Data stream for writing player sync data to.*/
|
/**
|
||||||
|
* Data stream for writing player sync data to.
|
||||||
|
*/
|
||||||
private DataOutputStream dataStream = new DataOutputStream(syncStream);
|
private DataOutputStream dataStream = new DataOutputStream(syncStream);
|
||||||
/**Encoder for computing snapshot deltas.*/
|
/**
|
||||||
|
* Encoder for computing snapshot deltas.
|
||||||
|
*/
|
||||||
private DEZEncoder encoder = new DEZEncoder();
|
private DEZEncoder encoder = new DEZEncoder();
|
||||||
|
|
||||||
public NetServer(){
|
public NetServer(){
|
||||||
@@ -105,14 +115,14 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
boolean preventDuplicates = headless;
|
boolean preventDuplicates = headless;
|
||||||
|
|
||||||
if(preventDuplicates) {
|
if(preventDuplicates){
|
||||||
for (Player player : playerGroup.all()) {
|
for(Player player : playerGroup.all()){
|
||||||
if (player.name.equalsIgnoreCase(packet.name)) {
|
if(player.name.equalsIgnoreCase(packet.name)){
|
||||||
kick(id, KickReason.nameInUse);
|
kick(id, KickReason.nameInUse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.uuid.equals(packet.uuid)) {
|
if(player.uuid.equals(packet.uuid)){
|
||||||
kick(id, KickReason.idInUse);
|
kick(id, KickReason.idInUse);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -181,7 +191,7 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
long elapsed = TimeUtils.timeSinceMillis(connection.lastRecievedClientTime);
|
long elapsed = TimeUtils.timeSinceMillis(connection.lastRecievedClientTime);
|
||||||
|
|
||||||
float maxSpeed = (packet.boosting && !player.mech.flying ? player.mech.boostSpeed : player.mech.speed)*2.5f;
|
float maxSpeed = (packet.boosting && !player.mech.flying ? player.mech.boostSpeed : player.mech.speed) * 2.5f;
|
||||||
|
|
||||||
//extra 1.1x multiplicaton is added just in case
|
//extra 1.1x multiplicaton is added just in case
|
||||||
float maxMove = elapsed / 1000f * 60f * maxSpeed * 1.1f;
|
float maxMove = elapsed / 1000f * 60f * maxSpeed * 1.1f;
|
||||||
@@ -238,6 +248,86 @@ public class NetServer extends Module{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a raw byte[] snapshot to a client, splitting up into chunks when needed.
|
||||||
|
*/
|
||||||
|
private static void sendSplitSnapshot(int userid, byte[] bytes, int snapshotID, int base){
|
||||||
|
if(bytes.length < maxSnapshotSize){
|
||||||
|
Call.onSnapshot(userid, bytes, snapshotID, (short) 0, bytes.length, base);
|
||||||
|
}else{
|
||||||
|
int remaining = bytes.length;
|
||||||
|
int offset = 0;
|
||||||
|
int chunkid = 0;
|
||||||
|
while(remaining > 0){
|
||||||
|
int used = Math.min(remaining, maxSnapshotSize);
|
||||||
|
byte[] toSend;
|
||||||
|
//re-use sent byte arrays when possible
|
||||||
|
if(used == maxSnapshotSize){
|
||||||
|
toSend = reusableSnapArray;
|
||||||
|
System.arraycopy(bytes, offset, toSend, 0, Math.min(offset + maxSnapshotSize, bytes.length) - offset);
|
||||||
|
}else{
|
||||||
|
toSend = Arrays.copyOfRange(bytes, offset, Math.min(offset + maxSnapshotSize, bytes.length));
|
||||||
|
}
|
||||||
|
Call.onSnapshot(userid, toSend, snapshotID, (short) chunkid, bytes.length, base);
|
||||||
|
|
||||||
|
remaining -= used;
|
||||||
|
offset += used;
|
||||||
|
chunkid++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onDisconnect(Player player){
|
||||||
|
Call.sendMessage("[accent]" + player.name + " has disconnected.");
|
||||||
|
Call.onPlayerDisconnect(player.id);
|
||||||
|
player.remove();
|
||||||
|
netServer.connections.remove(player.con.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(targets = Loc.client, called = Loc.server)
|
||||||
|
public static void onAdminRequest(Player player, Player other, AdminAction action){
|
||||||
|
|
||||||
|
if(!player.isAdmin){
|
||||||
|
Log.err("ACCESS DENIED: Player {0} / {1} attempted to perform admin action without proper security access.",
|
||||||
|
player.name, player.con.address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(other == null || (other.isAdmin && other != player)){ //fun fact: this means you can ban yourself
|
||||||
|
Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(action == AdminAction.wave){
|
||||||
|
//no verification is done, so admins can hypothetically spam waves
|
||||||
|
//not a real issue, because server owners may want to do just that
|
||||||
|
state.wavetime = 0f;
|
||||||
|
}else if(action == AdminAction.ban){
|
||||||
|
netServer.admins.banPlayerIP(other.con.address);
|
||||||
|
netServer.kick(other.con.id, KickReason.banned);
|
||||||
|
Log.info("&lc{0} has banned {1}.", player.name, other.name);
|
||||||
|
}else if(action == AdminAction.kick){
|
||||||
|
netServer.kick(other.con.id, KickReason.kick);
|
||||||
|
Log.info("&lc{0} has kicked {1}.", player.name, other.name);
|
||||||
|
}else if(action == AdminAction.trace){
|
||||||
|
//TODO
|
||||||
|
if(player.con != null){
|
||||||
|
Call.onTraceInfo(player.con.id, netServer.admins.getTraceByID(other.uuid));
|
||||||
|
}else{
|
||||||
|
NetClient.onTraceInfo(netServer.admins.getTraceByID(other.uuid));
|
||||||
|
}
|
||||||
|
Log.info("&lc{0} has requested trace info of {1}.", player.name, other.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(targets = Loc.client)
|
||||||
|
public static void connectConfirm(Player player){
|
||||||
|
player.add();
|
||||||
|
player.con.hasConnected = true;
|
||||||
|
Call.sendMessage("[accent]" + player.name + " has connected.");
|
||||||
|
Log.info("&y{0} has connected.", player.name);
|
||||||
|
}
|
||||||
|
|
||||||
public void update(){
|
public void update(){
|
||||||
if(!headless && !closing && Net.server() && state.is(State.menu)){
|
if(!headless && !closing && Net.server() && state.is(State.menu)){
|
||||||
closing = true;
|
closing = true;
|
||||||
@@ -270,7 +360,7 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
if((reason == KickReason.kick || reason == KickReason.banned) && admins.getTraceByID(getUUID(con.id)).uuid != null){
|
if((reason == KickReason.kick || reason == KickReason.banned) && admins.getTraceByID(getUUID(con.id)).uuid != null){
|
||||||
PlayerInfo info = admins.getInfo(admins.getTraceByID(getUUID(con.id)).uuid);
|
PlayerInfo info = admins.getInfo(admins.getTraceByID(getUUID(con.id)).uuid);
|
||||||
info.timesKicked ++;
|
info.timesKicked++;
|
||||||
info.lastKicked = TimeUtils.millis();
|
info.lastKicked = TimeUtils.millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +378,7 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
String fixName(String name){
|
String fixName(String name){
|
||||||
|
|
||||||
for(int i = 0; i < name.length(); i ++){
|
for(int i = 0; i < name.length(); i++){
|
||||||
if(name.charAt(i) == '[' && i != name.length() - 1 && name.charAt(i + 1) != '[' && (i == 0 || name.charAt(i - 1) != '[')){
|
if(name.charAt(i) == '[' && i != name.length() - 1 && name.charAt(i + 1) != '[' && (i == 0 || name.charAt(i - 1) != '[')){
|
||||||
String prev = name.substring(0, i);
|
String prev = name.substring(0, i);
|
||||||
String next = name.substring(i);
|
String next = name.substring(i);
|
||||||
@@ -303,7 +393,7 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
String checkColor(String str){
|
String checkColor(String str){
|
||||||
|
|
||||||
for(int i = 1; i < str.length(); i ++){
|
for(int i = 1; i < str.length(); i++){
|
||||||
if(str.charAt(i) == ']'){
|
if(str.charAt(i) == ']'){
|
||||||
String color = str.substring(1, i);
|
String color = str.substring(1, i);
|
||||||
|
|
||||||
@@ -318,7 +408,7 @@ public class NetServer extends Module{
|
|||||||
if(result.a <= 0.8f){
|
if(result.a <= 0.8f){
|
||||||
return str.substring(i + 1);
|
return str.substring(i + 1);
|
||||||
}
|
}
|
||||||
}catch (Exception e){
|
}catch(Exception e){
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,10 +418,10 @@ public class NetServer extends Module{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sync(){
|
void sync(){
|
||||||
try {
|
try{
|
||||||
|
|
||||||
//iterate through each player
|
//iterate through each player
|
||||||
for (Player player : connections.values()) {
|
for(Player player : connections.values()){
|
||||||
NetConnection connection = player.con;
|
NetConnection connection = player.con;
|
||||||
|
|
||||||
if(!connection.isConnected()){
|
if(!connection.isConnected()){
|
||||||
@@ -344,7 +434,8 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
//if the player hasn't acknowledged that it has recieved the packet, send the same thing again
|
//if the player hasn't acknowledged that it has recieved the packet, send the same thing again
|
||||||
if(connection.currentBaseID < connection.lastSentSnapshotID){
|
if(connection.currentBaseID < connection.lastSentSnapshotID){
|
||||||
if(showSnapshotSize) Log.info("Re-sending snapshot: {0} bytes, ID {1} base {2} baselength {3}", connection.lastSentSnapshot.length, connection.lastSentSnapshotID, connection.lastSentBase, connection.currentBaseSnapshot.length);
|
if(showSnapshotSize)
|
||||||
|
Log.info("Re-sending snapshot: {0} bytes, ID {1} base {2} baselength {3}", connection.lastSentSnapshot.length, connection.lastSentSnapshotID, connection.lastSentBase, connection.currentBaseSnapshot.length);
|
||||||
sendSplitSnapshot(connection.id, connection.lastSentSnapshot, connection.lastSentSnapshotID, connection.lastSentBase);
|
sendSplitSnapshot(connection.id, connection.lastSentSnapshot, connection.lastSentSnapshotID, connection.lastSentBase);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -371,17 +462,17 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
int totalGroups = 0;
|
int totalGroups = 0;
|
||||||
|
|
||||||
for (EntityGroup<?> group : Entities.getAllGroups()) {
|
for(EntityGroup<?> group : Entities.getAllGroups()){
|
||||||
if (!group.isEmpty() && (group.all().get(0) instanceof SyncTrait)) totalGroups ++;
|
if(!group.isEmpty() && (group.all().get(0) instanceof SyncTrait)) totalGroups++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//write total amount of serializable groups
|
//write total amount of serializable groups
|
||||||
dataStream.writeByte(totalGroups);
|
dataStream.writeByte(totalGroups);
|
||||||
|
|
||||||
//check for syncable groups
|
//check for syncable groups
|
||||||
for (EntityGroup<?> group : Entities.getAllGroups()) {
|
for(EntityGroup<?> group : Entities.getAllGroups()){
|
||||||
//TODO range-check sync positions to optimize?
|
//TODO range-check sync positions to optimize?
|
||||||
if (group.isEmpty() || !(group.all().get(0) instanceof SyncTrait)) continue;
|
if(group.isEmpty() || !(group.all().get(0) instanceof SyncTrait)) continue;
|
||||||
|
|
||||||
//make sure mapping is enabled for this group
|
//make sure mapping is enabled for this group
|
||||||
if(!group.mappingEnabled()){
|
if(!group.mappingEnabled()){
|
||||||
@@ -391,8 +482,8 @@ public class NetServer extends Module{
|
|||||||
int amount = 0;
|
int amount = 0;
|
||||||
|
|
||||||
for(Entity entity : group.all()){
|
for(Entity entity : group.all()){
|
||||||
if(((SyncTrait)entity).isSyncing()){
|
if(((SyncTrait) entity).isSyncing()){
|
||||||
amount ++;
|
amount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,15 +492,16 @@ public class NetServer extends Module{
|
|||||||
dataStream.writeShort(amount);
|
dataStream.writeShort(amount);
|
||||||
|
|
||||||
for(Entity entity : group.all()){
|
for(Entity entity : group.all()){
|
||||||
if(!((SyncTrait)entity).isSyncing()) continue;
|
if(!((SyncTrait) entity).isSyncing()) continue;
|
||||||
|
|
||||||
int position = syncStream.position();
|
int position = syncStream.position();
|
||||||
//write all entities now
|
//write all entities now
|
||||||
dataStream.writeInt(entity.getID()); //write id
|
dataStream.writeInt(entity.getID()); //write id
|
||||||
dataStream.writeByte(((SyncTrait)entity).getTypeID()); //write type ID
|
dataStream.writeByte(((SyncTrait) entity).getTypeID()); //write type ID
|
||||||
((SyncTrait)entity).write(dataStream); //write entity
|
((SyncTrait) entity).write(dataStream); //write entity
|
||||||
int length = syncStream.position() - position; //length must always be less than 127 bytes
|
int length = syncStream.position() - position; //length must always be less than 127 bytes
|
||||||
if(length > 127) throw new RuntimeException("Write size for entity of type " + group.getType() + " must not exceed 127!");
|
if(length > 127)
|
||||||
|
throw new RuntimeException("Write size for entity of type " + group.getType() + " must not exceed 127!");
|
||||||
dataStream.writeByte(length);
|
dataStream.writeByte(length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,7 +525,8 @@ public class NetServer extends Module{
|
|||||||
|
|
||||||
//send diff, otherwise
|
//send diff, otherwise
|
||||||
byte[] diff = ByteDeltaEncoder.toDiff(new ByteMatcherHash(connection.currentBaseSnapshot, bytes), encoder);
|
byte[] diff = ByteDeltaEncoder.toDiff(new ByteMatcherHash(connection.currentBaseSnapshot, bytes), encoder);
|
||||||
if(showSnapshotSize) Log.info("Shrank snapshot: {0} -> {1}, Base {2} ID {3} base length = {4}", bytes.length, diff.length, connection.currentBaseID, connection.currentBaseID + 1, connection.currentBaseSnapshot.length);
|
if(showSnapshotSize)
|
||||||
|
Log.info("Shrank snapshot: {0} -> {1}, Base {2} ID {3} base length = {4}", bytes.length, diff.length, connection.currentBaseID, connection.currentBaseID + 1, connection.currentBaseSnapshot.length);
|
||||||
sendSplitSnapshot(connection.id, diff, connection.currentBaseID + 1, connection.currentBaseID);
|
sendSplitSnapshot(connection.id, diff, connection.currentBaseID + 1, connection.currentBaseID);
|
||||||
connection.lastSentSnapshot = diff;
|
connection.lastSentSnapshot = diff;
|
||||||
connection.lastSentSnapshotID = connection.currentBaseID + 1;
|
connection.lastSentSnapshotID = connection.currentBaseID + 1;
|
||||||
@@ -441,86 +534,8 @@ public class NetServer extends Module{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch (IOException e){
|
}catch(IOException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Sends a raw byte[] snapshot to a client, splitting up into chunks when needed.*/
|
|
||||||
private static void sendSplitSnapshot(int userid, byte[] bytes, int snapshotID, int base){
|
|
||||||
if(bytes.length < maxSnapshotSize){
|
|
||||||
Call.onSnapshot(userid, bytes, snapshotID, (short)0, bytes.length, base);
|
|
||||||
}else{
|
|
||||||
int remaining = bytes.length;
|
|
||||||
int offset = 0;
|
|
||||||
int chunkid = 0;
|
|
||||||
while(remaining > 0){
|
|
||||||
int used = Math.min(remaining, maxSnapshotSize);
|
|
||||||
byte[] toSend;
|
|
||||||
//re-use sent byte arrays when possible
|
|
||||||
if(used == maxSnapshotSize){
|
|
||||||
toSend = reusableSnapArray;
|
|
||||||
System.arraycopy(bytes, offset, toSend, 0, Math.min(offset + maxSnapshotSize, bytes.length) - offset);
|
|
||||||
}else {
|
|
||||||
toSend = Arrays.copyOfRange(bytes, offset, Math.min(offset + maxSnapshotSize, bytes.length));
|
|
||||||
}
|
|
||||||
Call.onSnapshot(userid, toSend, snapshotID, (short)chunkid, bytes.length, base);
|
|
||||||
|
|
||||||
remaining -= used;
|
|
||||||
offset += used;
|
|
||||||
chunkid ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onDisconnect(Player player){
|
|
||||||
Call.sendMessage("[accent]" + player.name + " has disconnected.");
|
|
||||||
Call.onPlayerDisconnect(player.id);
|
|
||||||
player.remove();
|
|
||||||
netServer.connections.remove(player.con.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(targets = Loc.client, called = Loc.server)
|
|
||||||
public static void onAdminRequest(Player player, Player other, AdminAction action){
|
|
||||||
|
|
||||||
if(!player.isAdmin){
|
|
||||||
Log.err("ACCESS DENIED: Player {0} / {1} attempted to perform admin action without proper security access.",
|
|
||||||
player.name, player.con.address);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(other == null || (other.isAdmin && other != player)){ //fun fact: this means you can ban yourself
|
|
||||||
Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(action == AdminAction.wave) {
|
|
||||||
//no verification is done, so admins can hypothetically spam waves
|
|
||||||
//not a real issue, because server owners may want to do just that
|
|
||||||
state.wavetime = 0f;
|
|
||||||
}else if(action == AdminAction.ban){
|
|
||||||
netServer.admins.banPlayerIP(other.con.address);
|
|
||||||
netServer.kick(other.con.id, KickReason.banned);
|
|
||||||
Log.info("&lc{0} has banned {1}.", player.name, other.name);
|
|
||||||
}else if(action == AdminAction.kick){
|
|
||||||
netServer.kick(other.con.id, KickReason.kick);
|
|
||||||
Log.info("&lc{0} has kicked {1}.", player.name, other.name);
|
|
||||||
}else if(action == AdminAction.trace){
|
|
||||||
//TODO
|
|
||||||
if(player.con != null) {
|
|
||||||
Call.onTraceInfo(player.con.id, netServer.admins.getTraceByID(other.uuid));
|
|
||||||
}else{
|
|
||||||
NetClient.onTraceInfo(netServer.admins.getTraceByID(other.uuid));
|
|
||||||
}
|
|
||||||
Log.info("&lc{0} has requested trace info of {1}.", player.name, other.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(targets = Loc.client)
|
|
||||||
public static void connectConfirm(Player player){
|
|
||||||
player.add();
|
|
||||||
player.con.hasConnected = true;
|
|
||||||
Call.sendMessage("[accent]" + player.name + " has connected.");
|
|
||||||
Log.info("&y{0} has connected.", player.name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,63 +11,129 @@ import java.util.Date;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public abstract class Platform {
|
public abstract class Platform{
|
||||||
/**Each separate game platform should set this instance to their own implementation.*/
|
/**
|
||||||
public static Platform instance = new Platform() {};
|
* Each separate game platform should set this instance to their own implementation.
|
||||||
|
*/
|
||||||
|
public static Platform instance = new Platform(){
|
||||||
|
};
|
||||||
|
|
||||||
/**Format the date using the default date formatter.*/
|
/**
|
||||||
public String format(Date date){return "invalid";}
|
* Format the date using the default date formatter.
|
||||||
/**Format a number by adding in commas or periods where needed.*/
|
*/
|
||||||
public String format(int number){return "invalid";}
|
public String format(Date date){
|
||||||
/**Show a native error dialog.*/
|
return "invalid";
|
||||||
public void showError(String text){}
|
}
|
||||||
/**Add a text input dialog that should show up after the field is tapped.*/
|
|
||||||
public void addDialog(TextField field){
|
|
||||||
addDialog(field, 16);
|
|
||||||
}
|
|
||||||
/**See addDialog().*/
|
|
||||||
public void addDialog(TextField field, int maxLength){}
|
|
||||||
/**Update discord RPC.*/
|
|
||||||
public void updateRPC(){}
|
|
||||||
/**Called when the game is exited.*/
|
|
||||||
public void onGameExit(){}
|
|
||||||
/**Open donation dialog. Currently android only.*/
|
|
||||||
public void openDonations(){}
|
|
||||||
/**Whether donating is supported.*/
|
|
||||||
public boolean canDonate(){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/**Whether discord RPC is supported.*/
|
|
||||||
public boolean hasDiscord(){return true;}
|
|
||||||
/**Return the localized name for the locale. This is basically a workaround for GWT not supporting getName().*/
|
|
||||||
public String getLocaleName(Locale locale){
|
|
||||||
return locale.toString();
|
|
||||||
}
|
|
||||||
/**Whether joining games is supported.*/
|
|
||||||
public boolean canJoinGame(){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/**Whether debug mode is enabled.*/
|
|
||||||
public boolean isDebug(){return false;}
|
|
||||||
/**Must be a base64 string 8 bytes in length.*/
|
|
||||||
public String getUUID(){
|
|
||||||
String uuid = Settings.getString("uuid", "");
|
|
||||||
if(uuid.isEmpty()){
|
|
||||||
byte[] result = new byte[8];
|
|
||||||
new Random().nextBytes(result);
|
|
||||||
uuid = new String(Base64Coder.encode(result));
|
|
||||||
Settings.putString("uuid", uuid);
|
|
||||||
Settings.save();
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
/**Only used for iOS or android: open the share menu for a map or save.*/
|
|
||||||
public void shareFile(FileHandle file){}
|
|
||||||
/**Download a file. Only used on GWT backend.*/
|
|
||||||
public void downloadFile(String name, byte[] bytes){}
|
|
||||||
|
|
||||||
/**Show a file chooser. Desktop only.
|
/**
|
||||||
|
* Format a number by adding in commas or periods where needed.
|
||||||
|
*/
|
||||||
|
public String format(int number){
|
||||||
|
return "invalid";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a native error dialog.
|
||||||
|
*/
|
||||||
|
public void showError(String text){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a text input dialog that should show up after the field is tapped.
|
||||||
|
*/
|
||||||
|
public void addDialog(TextField field){
|
||||||
|
addDialog(field, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See addDialog().
|
||||||
|
*/
|
||||||
|
public void addDialog(TextField field, int maxLength){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update discord RPC.
|
||||||
|
*/
|
||||||
|
public void updateRPC(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the game is exited.
|
||||||
|
*/
|
||||||
|
public void onGameExit(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open donation dialog. Currently android only.
|
||||||
|
*/
|
||||||
|
public void openDonations(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether donating is supported.
|
||||||
|
*/
|
||||||
|
public boolean canDonate(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether discord RPC is supported.
|
||||||
|
*/
|
||||||
|
public boolean hasDiscord(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the localized name for the locale. This is basically a workaround for GWT not supporting getName().
|
||||||
|
*/
|
||||||
|
public String getLocaleName(Locale locale){
|
||||||
|
return locale.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether joining games is supported.
|
||||||
|
*/
|
||||||
|
public boolean canJoinGame(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether debug mode is enabled.
|
||||||
|
*/
|
||||||
|
public boolean isDebug(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be a base64 string 8 bytes in length.
|
||||||
|
*/
|
||||||
|
public String getUUID(){
|
||||||
|
String uuid = Settings.getString("uuid", "");
|
||||||
|
if(uuid.isEmpty()){
|
||||||
|
byte[] result = new byte[8];
|
||||||
|
new Random().nextBytes(result);
|
||||||
|
uuid = new String(Base64Coder.encode(result));
|
||||||
|
Settings.putString("uuid", uuid);
|
||||||
|
Settings.save();
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only used for iOS or android: open the share menu for a map or save.
|
||||||
|
*/
|
||||||
|
public void shareFile(FileHandle file){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download a file. Only used on GWT backend.
|
||||||
|
*/
|
||||||
|
public void downloadFile(String name, byte[] bytes){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a file chooser. Desktop only.
|
||||||
*
|
*
|
||||||
* @param text File chooser title text
|
* @param text File chooser title text
|
||||||
* @param content Description of the type of files to be loaded
|
* @param content Description of the type of files to be loaded
|
||||||
@@ -75,24 +141,54 @@ public abstract class Platform {
|
|||||||
* @param open Whether to open or save files
|
* @param open Whether to open or save files
|
||||||
* @param filetype File extension to filter
|
* @param filetype File extension to filter
|
||||||
*/
|
*/
|
||||||
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){}
|
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){
|
||||||
/**Use the default thread provider from the kryonet module for this.*/
|
}
|
||||||
public ThreadProvider getThreadProvider(){
|
|
||||||
return new ThreadProvider() {
|
|
||||||
@Override public boolean isOnThread() {return true;}
|
|
||||||
@Override public void sleep(long ms) {}
|
|
||||||
@Override public void start(Runnable run) {}
|
|
||||||
@Override public void stop() {}
|
|
||||||
@Override public void notify(Object object) {}
|
|
||||||
@Override public void wait(Object object) {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO iOS implementation
|
/**
|
||||||
/**Forces the app into landscape mode. Currently Android only.*/
|
* Use the default thread provider from the kryonet module for this.
|
||||||
public void beginForceLandscape(){}
|
*/
|
||||||
|
public ThreadProvider getThreadProvider(){
|
||||||
|
return new ThreadProvider(){
|
||||||
|
@Override
|
||||||
|
public boolean isOnThread(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO iOS implementation
|
@Override
|
||||||
/**Stops forcing the app into landscape orientation. Currently Android only.*/
|
public void sleep(long ms){
|
||||||
public void endForceLandscape(){}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Runnable run){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notify(Object object){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wait(Object object){
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO iOS implementation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces the app into landscape mode. Currently Android only.
|
||||||
|
*/
|
||||||
|
public void beginForceLandscape(){
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO iOS implementation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops forcing the app into landscape orientation. Currently Android only.
|
||||||
|
*/
|
||||||
|
public void endForceLandscape(){
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,429 +47,429 @@ import static io.anuke.ucore.core.Core.batch;
|
|||||||
import static io.anuke.ucore.core.Core.camera;
|
import static io.anuke.ucore.core.Core.camera;
|
||||||
|
|
||||||
public class Renderer extends RendererModule{
|
public class Renderer extends RendererModule{
|
||||||
public Surface effectSurface;
|
public Surface effectSurface;
|
||||||
|
|
||||||
private int targetscale = baseCameraScale;
|
|
||||||
private Texture background = new Texture("sprites/background.png");
|
|
||||||
|
|
||||||
private Rectangle rect = new Rectangle(), rect2 = new Rectangle();
|
private int targetscale = baseCameraScale;
|
||||||
private Vector2 avgPosition = new Translator();
|
private Texture background = new Texture("sprites/background.png");
|
||||||
private Vector2 tmpVector1 = new Translator();
|
|
||||||
private Vector2 tmpVector2 = new Translator();
|
|
||||||
|
|
||||||
private BlockRenderer blocks = new BlockRenderer();
|
private Rectangle rect = new Rectangle(), rect2 = new Rectangle();
|
||||||
private MinimapRenderer minimap = new MinimapRenderer();
|
private Vector2 avgPosition = new Translator();
|
||||||
private OverlayRenderer overlays = new OverlayRenderer();
|
private Vector2 tmpVector1 = new Translator();
|
||||||
private FogRenderer fog = new FogRenderer();
|
private Vector2 tmpVector2 = new Translator();
|
||||||
|
|
||||||
public Renderer() {
|
private BlockRenderer blocks = new BlockRenderer();
|
||||||
pixelate = true;
|
private MinimapRenderer minimap = new MinimapRenderer();
|
||||||
Lines.setCircleVertices(14);
|
private OverlayRenderer overlays = new OverlayRenderer();
|
||||||
|
private FogRenderer fog = new FogRenderer();
|
||||||
|
|
||||||
Shaders.init();
|
public Renderer(){
|
||||||
|
pixelate = true;
|
||||||
|
Lines.setCircleVertices(14);
|
||||||
|
|
||||||
Core.cameraScale = baseCameraScale;
|
Shaders.init();
|
||||||
Effects.setEffectProvider((effect, color, x, y, rotation, data) -> {
|
|
||||||
if(effect == Fx.none) return;
|
|
||||||
if(Settings.getBool("effects")){
|
|
||||||
Rectangle view = rect.setSize(camera.viewportWidth, camera.viewportHeight)
|
|
||||||
.setCenter(camera.position.x, camera.position.y);
|
|
||||||
Rectangle pos = rect2.setSize(effect.size).setCenter(x, y);
|
|
||||||
|
|
||||||
if(view.overlaps(pos)){
|
Core.cameraScale = baseCameraScale;
|
||||||
|
Effects.setEffectProvider((effect, color, x, y, rotation, data) -> {
|
||||||
|
if(effect == Fx.none) return;
|
||||||
|
if(Settings.getBool("effects")){
|
||||||
|
Rectangle view = rect.setSize(camera.viewportWidth, camera.viewportHeight)
|
||||||
|
.setCenter(camera.position.x, camera.position.y);
|
||||||
|
Rectangle pos = rect2.setSize(effect.size).setCenter(x, y);
|
||||||
|
|
||||||
if(!(effect instanceof GroundEffect)) {
|
if(view.overlaps(pos)){
|
||||||
EffectEntity entity = Pooling.obtain(EffectEntity.class);
|
|
||||||
entity.effect = effect;
|
|
||||||
entity.color = color;
|
|
||||||
entity.rotation = rotation;
|
|
||||||
entity.data = data;
|
|
||||||
entity.id ++;
|
|
||||||
entity.set(x, y);
|
|
||||||
if(data instanceof BaseEntity){
|
|
||||||
entity.setParent((BaseEntity)data);
|
|
||||||
}
|
|
||||||
threads.runGraphics(() -> effectGroup.add(entity));
|
|
||||||
}else{
|
|
||||||
GroundEffectEntity entity = Pooling.obtain(GroundEffectEntity.class);
|
|
||||||
entity.effect = effect;
|
|
||||||
entity.color = color;
|
|
||||||
entity.rotation = rotation;
|
|
||||||
entity.id ++;
|
|
||||||
entity.data = data;
|
|
||||||
entity.set(x, y);
|
|
||||||
threads.runGraphics(() -> groundEffectGroup.add(entity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Cursors.cursorScaling = 3;
|
if(!(effect instanceof GroundEffect)){
|
||||||
Cursors.outlineColor = Color.valueOf("444444");
|
EffectEntity entity = Pooling.obtain(EffectEntity.class);
|
||||||
|
entity.effect = effect;
|
||||||
|
entity.color = color;
|
||||||
|
entity.rotation = rotation;
|
||||||
|
entity.data = data;
|
||||||
|
entity.id++;
|
||||||
|
entity.set(x, y);
|
||||||
|
if(data instanceof BaseEntity){
|
||||||
|
entity.setParent((BaseEntity) data);
|
||||||
|
}
|
||||||
|
threads.runGraphics(() -> effectGroup.add(entity));
|
||||||
|
}else{
|
||||||
|
GroundEffectEntity entity = Pooling.obtain(GroundEffectEntity.class);
|
||||||
|
entity.effect = effect;
|
||||||
|
entity.color = color;
|
||||||
|
entity.rotation = rotation;
|
||||||
|
entity.id++;
|
||||||
|
entity.data = data;
|
||||||
|
entity.set(x, y);
|
||||||
|
threads.runGraphics(() -> groundEffectGroup.add(entity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Cursors.arrow = Cursors.loadCursor("cursor");
|
Cursors.cursorScaling = 3;
|
||||||
Cursors.hand = Cursors.loadCursor("hand");
|
Cursors.outlineColor = Color.valueOf("444444");
|
||||||
Cursors.ibeam = Cursors.loadCursor("ibar");
|
|
||||||
Cursors.loadCustom("drill");
|
|
||||||
Cursors.loadCustom("unload");
|
|
||||||
|
|
||||||
clearColor = Hue.lightness(0.4f);
|
Cursors.arrow = Cursors.loadCursor("cursor");
|
||||||
clearColor.a = 1f;
|
Cursors.hand = Cursors.loadCursor("hand");
|
||||||
|
Cursors.ibeam = Cursors.loadCursor("ibar");
|
||||||
|
Cursors.loadCustom("drill");
|
||||||
|
Cursors.loadCustom("unload");
|
||||||
|
|
||||||
background.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
|
clearColor = Hue.lightness(0.4f);
|
||||||
}
|
clearColor.a = 1f;
|
||||||
|
|
||||||
@Override
|
background.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
|
||||||
public void init(){
|
}
|
||||||
int scale = Core.cameraScale;
|
|
||||||
|
@Override
|
||||||
|
public void init(){
|
||||||
|
int scale = Core.cameraScale;
|
||||||
|
|
||||||
effectSurface = Graphics.createSurface(scale);
|
effectSurface = Graphics.createSurface(scale);
|
||||||
pixelSurface = Graphics.createSurface(scale);
|
pixelSurface = Graphics.createSurface(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
|
|
||||||
if(Core.cameraScale != targetscale){
|
if(Core.cameraScale != targetscale){
|
||||||
float targetzoom = (float) Core.cameraScale / targetscale;
|
float targetzoom = (float) Core.cameraScale / targetscale;
|
||||||
camera.zoom = Mathf.lerpDelta(camera.zoom, targetzoom, 0.2f);
|
camera.zoom = Mathf.lerpDelta(camera.zoom, targetzoom, 0.2f);
|
||||||
|
|
||||||
if(Mathf.in(camera.zoom, targetzoom, 0.005f)){
|
if(Mathf.in(camera.zoom, targetzoom, 0.005f)){
|
||||||
camera.zoom = 1f;
|
camera.zoom = 1f;
|
||||||
Graphics.setCameraScale(targetscale);
|
Graphics.setCameraScale(targetscale);
|
||||||
for(Player player : players) {
|
for(Player player : players){
|
||||||
control.input(player.playerIndex).resetCursor();
|
control.input(player.playerIndex).resetCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
camera.zoom = Mathf.lerpDelta(camera.zoom, 1f, 0.2f);
|
camera.zoom = Mathf.lerpDelta(camera.zoom, 1f, 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.is(State.menu)){
|
if(state.is(State.menu)){
|
||||||
Graphics.clear(Color.BLACK);
|
Graphics.clear(Color.BLACK);
|
||||||
}else{
|
}else{
|
||||||
Vector2 position = averagePosition();
|
Vector2 position = averagePosition();
|
||||||
|
|
||||||
if(!mobile){
|
if(!mobile){
|
||||||
setCamera(position.x + 0.0001f, position.y + 0.0001f);
|
setCamera(position.x + 0.0001f, position.y + 0.0001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
clampCamera(-tilesize / 2f, -tilesize / 2f + 1, world.width() * tilesize - tilesize / 2f, world.height() * tilesize - tilesize / 2f);
|
clampCamera(-tilesize / 2f, -tilesize / 2f + 1, world.width() * tilesize - tilesize / 2f, world.height() * tilesize - tilesize / 2f);
|
||||||
|
|
||||||
float prex = camera.position.x, prey = camera.position.y;
|
float prex = camera.position.x, prey = camera.position.y;
|
||||||
updateShake(0.75f);
|
updateShake(0.75f);
|
||||||
|
|
||||||
float deltax = camera.position.x - prex, deltay = camera.position.y - prey;
|
float deltax = camera.position.x - prex, deltay = camera.position.y - prey;
|
||||||
float lastx = camera.position.x, lasty = camera.position.y;
|
float lastx = camera.position.x, lasty = camera.position.y;
|
||||||
|
|
||||||
if(snapCamera){
|
|
||||||
camera.position.set((int) camera.position.x, (int) camera.position.y, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Gdx.graphics.getHeight() / Core.cameraScale % 2 == 1){
|
|
||||||
camera.position.add(0, -0.5f, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Gdx.graphics.getWidth() / Core.cameraScale % 2 == 1){
|
if(snapCamera){
|
||||||
camera.position.add(-0.5f, 0, 0);
|
camera.position.set((int) camera.position.x, (int) camera.position.y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw();
|
|
||||||
|
|
||||||
camera.position.set(lastx - deltax, lasty - deltay, 0);
|
if(Gdx.graphics.getHeight() / Core.cameraScale % 2 == 1){
|
||||||
}
|
camera.position.add(0, -0.5f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if(debug && !ui.chatfrag.chatOpen()) {
|
if(Gdx.graphics.getWidth() / Core.cameraScale % 2 == 1){
|
||||||
renderer.record(); //this only does something if GdxGifRecorder is on the class path, which it usually isn't
|
camera.position.add(-0.5f, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
draw();
|
||||||
public void draw(){
|
|
||||||
camera.update();
|
|
||||||
|
|
||||||
Graphics.clear(clearColor);
|
camera.position.set(lastx - deltax, lasty - deltay, 0);
|
||||||
|
}
|
||||||
batch.setProjectionMatrix(camera.combined);
|
|
||||||
|
|
||||||
Graphics.surface(pixelSurface, false);
|
if(debug && !ui.chatfrag.chatOpen()){
|
||||||
|
renderer.record(); //this only does something if GdxGifRecorder is on the class path, which it usually isn't
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
drawPadding();
|
@Override
|
||||||
|
public void draw(){
|
||||||
blocks.drawFloor();
|
camera.update();
|
||||||
|
|
||||||
drawAndInterpolate(groundEffectGroup, e -> e instanceof BelowLiquidTrait);
|
Graphics.clear(clearColor);
|
||||||
drawAndInterpolate(puddleGroup);
|
|
||||||
drawAndInterpolate(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait));
|
|
||||||
|
|
||||||
blocks.processBlocks();
|
batch.setProjectionMatrix(camera.combined);
|
||||||
blocks.drawBlocks(Layer.block);
|
|
||||||
|
|
||||||
Graphics.shader(Shaders.blockbuild, false);
|
Graphics.surface(pixelSurface, false);
|
||||||
|
|
||||||
|
drawPadding();
|
||||||
|
|
||||||
|
blocks.drawFloor();
|
||||||
|
|
||||||
|
drawAndInterpolate(groundEffectGroup, e -> e instanceof BelowLiquidTrait);
|
||||||
|
drawAndInterpolate(puddleGroup);
|
||||||
|
drawAndInterpolate(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait));
|
||||||
|
|
||||||
|
blocks.processBlocks();
|
||||||
|
blocks.drawBlocks(Layer.block);
|
||||||
|
|
||||||
|
Graphics.shader(Shaders.blockbuild, false);
|
||||||
blocks.drawBlocks(Layer.placement);
|
blocks.drawBlocks(Layer.placement);
|
||||||
Graphics.shader();
|
Graphics.shader();
|
||||||
|
|
||||||
blocks.drawBlocks(Layer.overlay);
|
blocks.drawBlocks(Layer.overlay);
|
||||||
|
|
||||||
if(itemGroup.size() > 0){
|
if(itemGroup.size() > 0){
|
||||||
Shaders.outline.color.set(Team.none.color);
|
Shaders.outline.color.set(Team.none.color);
|
||||||
|
|
||||||
Graphics.beginShaders(Shaders.outline);
|
Graphics.beginShaders(Shaders.outline);
|
||||||
drawAndInterpolate(itemGroup);
|
drawAndInterpolate(itemGroup);
|
||||||
Graphics.endShaders();
|
Graphics.endShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
drawAllTeams(false);
|
drawAllTeams(false);
|
||||||
|
|
||||||
blocks.skipLayer(Layer.turret);
|
blocks.skipLayer(Layer.turret);
|
||||||
blocks.drawBlocks(Layer.laser);
|
blocks.drawBlocks(Layer.laser);
|
||||||
|
|
||||||
drawFlyerShadows();
|
drawFlyerShadows();
|
||||||
|
|
||||||
drawAllTeams(true);
|
drawAllTeams(true);
|
||||||
|
|
||||||
drawAndInterpolate(bulletGroup);
|
drawAndInterpolate(bulletGroup);
|
||||||
drawAndInterpolate(effectGroup);
|
drawAndInterpolate(effectGroup);
|
||||||
|
|
||||||
overlays.drawBottom();
|
overlays.drawBottom();
|
||||||
drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests);
|
drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests);
|
||||||
overlays.drawTop();
|
overlays.drawTop();
|
||||||
|
|
||||||
Graphics.flushSurface();
|
Graphics.flushSurface();
|
||||||
|
|
||||||
if(showPaths && debug) drawDebug();
|
if(showPaths && debug) drawDebug();
|
||||||
|
|
||||||
batch.end();
|
batch.end();
|
||||||
|
|
||||||
if(showFog){
|
if(showFog){
|
||||||
fog.draw();
|
fog.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics.beginCam();
|
Graphics.beginCam();
|
||||||
EntityDraw.setClip(false);
|
EntityDraw.setClip(false);
|
||||||
drawAndInterpolate(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName);
|
drawAndInterpolate(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName);
|
||||||
EntityDraw.setClip(true);
|
EntityDraw.setClip(true);
|
||||||
Graphics.end();
|
Graphics.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawFlyerShadows(){
|
private void drawFlyerShadows(){
|
||||||
Graphics.surface(effectSurface, true, false);
|
Graphics.surface(effectSurface, true, false);
|
||||||
|
|
||||||
float trnsX = 12, trnsY = -13;
|
float trnsX = 12, trnsY = -13;
|
||||||
|
|
||||||
Graphics.end();
|
Graphics.end();
|
||||||
Core.batch.getTransformMatrix().translate(trnsX, trnsY, 0);
|
Core.batch.getTransformMatrix().translate(trnsX, trnsY, 0);
|
||||||
Graphics.begin();
|
Graphics.begin();
|
||||||
|
|
||||||
for(EntityGroup<? extends BaseUnit> group : unitGroups){
|
for(EntityGroup<? extends BaseUnit> group : unitGroups){
|
||||||
if(!group.isEmpty()){
|
if(!group.isEmpty()){
|
||||||
drawAndInterpolate(group, unit -> unit.isFlying() && !unit.isDead(), Unit::drawShadow);
|
drawAndInterpolate(group, unit -> unit.isFlying() && !unit.isDead(), Unit::drawShadow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!playerGroup.isEmpty()){
|
if(!playerGroup.isEmpty()){
|
||||||
drawAndInterpolate(playerGroup, unit -> unit.isFlying() && !unit.isDead(), Unit::drawShadow);
|
drawAndInterpolate(playerGroup, unit -> unit.isFlying() && !unit.isDead(), Unit::drawShadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics.end();
|
Graphics.end();
|
||||||
Core.batch.getTransformMatrix().translate(-trnsX, -trnsY, 0);
|
Core.batch.getTransformMatrix().translate(-trnsX, -trnsY, 0);
|
||||||
Graphics.begin();
|
Graphics.begin();
|
||||||
|
|
||||||
//TODO this actually isn't necessary
|
//TODO this actually isn't necessary
|
||||||
Draw.color(0, 0, 0, 0.15f);
|
Draw.color(0, 0, 0, 0.15f);
|
||||||
Graphics.flushSurface();
|
Graphics.flushSurface();
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawAllTeams(boolean flying){
|
private void drawAllTeams(boolean flying){
|
||||||
for(Team team : Team.all){
|
for(Team team : Team.all){
|
||||||
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
||||||
|
|
||||||
if(group.count(p -> p.isFlying() == flying) +
|
if(group.count(p -> p.isFlying() == flying) +
|
||||||
playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue;
|
playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue;
|
||||||
|
|
||||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
|
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
|
||||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawUnder);
|
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawUnder);
|
||||||
|
|
||||||
Shaders.outline.color.set(team.color);
|
Shaders.outline.color.set(team.color);
|
||||||
Shaders.mix.color.set(Color.WHITE);
|
Shaders.mix.color.set(Color.WHITE);
|
||||||
|
|
||||||
Graphics.beginShaders(Shaders.outline);
|
Graphics.beginShaders(Shaders.outline);
|
||||||
Graphics.shader(Shaders.mix, true);
|
Graphics.shader(Shaders.mix, true);
|
||||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead());
|
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead());
|
||||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team);
|
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team);
|
||||||
Graphics.shader();
|
Graphics.shader();
|
||||||
blocks.drawTeamBlocks(Layer.turret, team);
|
blocks.drawTeamBlocks(Layer.turret, team);
|
||||||
Graphics.endShaders();
|
Graphics.endShaders();
|
||||||
|
|
||||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
|
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
|
||||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
|
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group){
|
public <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group){
|
||||||
drawAndInterpolate(group, t -> true, DrawTrait::draw);
|
drawAndInterpolate(group, t -> true, DrawTrait::draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group, Predicate<T> toDraw){
|
public <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group, Predicate<T> toDraw){
|
||||||
drawAndInterpolate(group, toDraw, DrawTrait::draw);
|
drawAndInterpolate(group, toDraw, DrawTrait::draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group, Predicate<T> toDraw, Consumer<T> drawer){
|
public <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group, Predicate<T> toDraw, Consumer<T> drawer){
|
||||||
EntityDraw.drawWith(group, toDraw, t -> {
|
EntityDraw.drawWith(group, toDraw, t -> {
|
||||||
float lastx = t.getX(), lasty = t.getY(), lastrot = 0f;
|
float lastx = t.getX(), lasty = t.getY(), lastrot = 0f;
|
||||||
|
|
||||||
if(threads.doInterpolate() && threads.isEnabled() && t instanceof SolidTrait){
|
if(threads.doInterpolate() && threads.isEnabled() && t instanceof SolidTrait){
|
||||||
SolidTrait s = (SolidTrait)t;
|
SolidTrait s = (SolidTrait) t;
|
||||||
|
|
||||||
lastrot = s.getRotation();
|
lastrot = s.getRotation();
|
||||||
|
|
||||||
if(s.lastUpdated() != 0){
|
if(s.lastUpdated() != 0){
|
||||||
float timeSinceUpdate = TimeUtils.timeSinceMillis(s.lastUpdated());
|
float timeSinceUpdate = TimeUtils.timeSinceMillis(s.lastUpdated());
|
||||||
float alpha = Math.min(timeSinceUpdate / s.updateSpacing(), 1f);
|
float alpha = Math.min(timeSinceUpdate / s.updateSpacing(), 1f);
|
||||||
|
|
||||||
tmpVector1.set(s.lastPosition().x, s.lastPosition().y)
|
tmpVector1.set(s.lastPosition().x, s.lastPosition().y)
|
||||||
.lerp(tmpVector2.set(lastx, lasty), alpha);
|
.lerp(tmpVector2.set(lastx, lasty), alpha);
|
||||||
s.setRotation(Mathf.slerp(s.lastPosition().z, lastrot, alpha));
|
s.setRotation(Mathf.slerp(s.lastPosition().z, lastrot, alpha));
|
||||||
|
|
||||||
s.setX(tmpVector1.x);
|
s.setX(tmpVector1.x);
|
||||||
s.setY(tmpVector1.y);
|
s.setY(tmpVector1.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO extremely hacky
|
//TODO extremely hacky
|
||||||
if(t instanceof Player && ((Player) t).getCarry() != null && ((Player) t).getCarry() instanceof Player && ((Player) ((Player) t).getCarry()).isLocal){
|
if(t instanceof Player && ((Player) t).getCarry() != null && ((Player) t).getCarry() instanceof Player && ((Player) ((Player) t).getCarry()).isLocal){
|
||||||
((Player) t).x = ((Player) t).getCarry().getX();
|
((Player) t).x = ((Player) t).getCarry().getX();
|
||||||
((Player) t).y = ((Player) t).getCarry().getY();
|
((Player) t).y = ((Player) t).getCarry().getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
drawer.accept(t);
|
drawer.accept(t);
|
||||||
|
|
||||||
t.setX(lastx);
|
t.setX(lastx);
|
||||||
t.setY(lasty);
|
t.setY(lasty);
|
||||||
|
|
||||||
if(threads.doInterpolate() && threads.isEnabled()) {
|
if(threads.doInterpolate() && threads.isEnabled()){
|
||||||
|
|
||||||
if (t instanceof SolidTrait) {
|
if(t instanceof SolidTrait){
|
||||||
((SolidTrait) t).setRotation(lastrot);
|
((SolidTrait) t).setRotation(lastrot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resize(int width, int height){
|
public void resize(int width, int height){
|
||||||
super.resize(width, height);
|
super.resize(width, height);
|
||||||
for(Player player : players) {
|
for(Player player : players){
|
||||||
control.input(player.playerIndex).resetCursor();
|
control.input(player.playerIndex).resetCursor();
|
||||||
}
|
}
|
||||||
camera.position.set(players[0].x, players[0].y, 0);
|
camera.position.set(players[0].x, players[0].y, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose(){
|
||||||
background.dispose();
|
background.dispose();
|
||||||
fog.dispose();
|
fog.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 averagePosition(){
|
public Vector2 averagePosition(){
|
||||||
avgPosition.setZero();
|
avgPosition.setZero();
|
||||||
|
|
||||||
drawAndInterpolate(playerGroup, p -> p.isLocal, p -> {
|
drawAndInterpolate(playerGroup, p -> p.isLocal, p -> {
|
||||||
avgPosition.add(p.x, p.y);
|
avgPosition.add(p.x, p.y);
|
||||||
});
|
});
|
||||||
|
|
||||||
avgPosition.scl(1f / players.length);
|
avgPosition.scl(1f / players.length);
|
||||||
return avgPosition;
|
return avgPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FogRenderer fog() {
|
public FogRenderer fog(){
|
||||||
return fog;
|
return fog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinimapRenderer minimap() {
|
public MinimapRenderer minimap(){
|
||||||
return minimap;
|
return minimap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawPadding(){
|
void drawPadding(){
|
||||||
float vw = world.width() * tilesize;
|
float vw = world.width() * tilesize;
|
||||||
float cw = camera.viewportWidth * camera.zoom;
|
float cw = camera.viewportWidth * camera.zoom;
|
||||||
float ch = camera.viewportHeight * camera.zoom;
|
float ch = camera.viewportHeight * camera.zoom;
|
||||||
if(vw < cw){
|
if(vw < cw){
|
||||||
batch.draw(background,
|
batch.draw(background,
|
||||||
camera.position.x + vw/2,
|
camera.position.x + vw / 2,
|
||||||
Mathf.round(camera.position.y - ch/2, tilesize),
|
Mathf.round(camera.position.y - ch / 2, tilesize),
|
||||||
(cw - vw) /2,
|
(cw - vw) / 2,
|
||||||
ch + tilesize,
|
ch + tilesize,
|
||||||
0, 0,
|
0, 0,
|
||||||
((cw - vw) / 2 / tilesize), -ch / tilesize + 1);
|
((cw - vw) / 2 / tilesize), -ch / tilesize + 1);
|
||||||
|
|
||||||
batch.draw(background,
|
batch.draw(background,
|
||||||
camera.position.x - vw/2,
|
camera.position.x - vw / 2,
|
||||||
Mathf.round(camera.position.y - ch/2, tilesize),
|
Mathf.round(camera.position.y - ch / 2, tilesize),
|
||||||
-(cw - vw) /2,
|
-(cw - vw) / 2,
|
||||||
ch + tilesize,
|
ch + tilesize,
|
||||||
0, 0,
|
0, 0,
|
||||||
-((cw - vw) / 2 / tilesize), -ch / tilesize + 1);
|
-((cw - vw) / 2 / tilesize), -ch / tilesize + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawDebug(){
|
void drawDebug(){
|
||||||
int rangex = (int)(Core.camera.viewportWidth/tilesize/2), rangey = (int)(Core.camera.viewportHeight/tilesize/2);
|
int rangex = (int) (Core.camera.viewportWidth / tilesize / 2), rangey = (int) (Core.camera.viewportHeight / tilesize / 2);
|
||||||
|
|
||||||
for(int x = -rangex; x <= rangex; x++) {
|
for(int x = -rangex; x <= rangex; x++){
|
||||||
for (int y = -rangey; y <= rangey; y++) {
|
for(int y = -rangey; y <= rangey; y++){
|
||||||
int worldx = Mathf.scl(camera.position.x, tilesize) + x;
|
int worldx = Mathf.scl(camera.position.x, tilesize) + x;
|
||||||
int worldy = Mathf.scl(camera.position.y, tilesize) + y;
|
int worldy = Mathf.scl(camera.position.y, tilesize) + y;
|
||||||
|
|
||||||
if(world.tile(worldx, worldy) == null) continue;
|
if(world.tile(worldx, worldy) == null) continue;
|
||||||
|
|
||||||
float value = world.pathfinder().getDebugValue(worldx, worldy);
|
float value = world.pathfinder().getDebugValue(worldx, worldy);
|
||||||
Draw.color(Color.PURPLE);
|
Draw.color(Color.PURPLE);
|
||||||
Draw.alpha((value % 10f) / 10f);
|
Draw.alpha((value % 10f) / 10f);
|
||||||
Lines.square(worldx * tilesize, worldy*tilesize, 4f);
|
Lines.square(worldx * tilesize, worldy * tilesize, 4f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Draw.color(Color.ORANGE);
|
Draw.color(Color.ORANGE);
|
||||||
Draw.tcolor(Color.ORANGE);
|
Draw.tcolor(Color.ORANGE);
|
||||||
|
|
||||||
ObjectIntMap<Tile> seen = new ObjectIntMap<>();
|
ObjectIntMap<Tile> seen = new ObjectIntMap<>();
|
||||||
|
|
||||||
for(BlockFlag flag : BlockFlag.values()){
|
for(BlockFlag flag : BlockFlag.values()){
|
||||||
for(Tile tile : world.indexer().getEnemy(Team.blue, flag)){
|
for(Tile tile : world.indexer().getEnemy(Team.blue, flag)){
|
||||||
int index = seen.getAndIncrement(tile, 0, 1);
|
int index = seen.getAndIncrement(tile, 0, 1);
|
||||||
Draw.tscl(0.125f);
|
Draw.tscl(0.125f);
|
||||||
Draw.text(flag.name(), tile.drawx(), tile.drawy() + tile.block().size * tilesize/2f + 4 + index * 3);
|
Draw.text(flag.name(), tile.drawx(), tile.drawy() + tile.block().size * tilesize / 2f + 4 + index * 3);
|
||||||
Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize/2f);
|
Lines.square(tile.drawx(), tile.drawy(), tile.block().size * tilesize / 2f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Draw.tscl(fontScale);
|
Draw.tscl(fontScale);
|
||||||
Draw.tcolor();
|
Draw.tcolor();
|
||||||
|
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockRenderer getBlocks() {
|
public BlockRenderer getBlocks(){
|
||||||
return blocks;
|
return blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCameraScale(int amount){
|
public void setCameraScale(int amount){
|
||||||
targetscale = amount;
|
targetscale = amount;
|
||||||
clampScale();
|
clampScale();
|
||||||
//scale up all surfaces in preparation for the zoom
|
//scale up all surfaces in preparation for the zoom
|
||||||
for(Surface surface : Graphics.getSurfaces()){
|
for(Surface surface : Graphics.getSurfaces()){
|
||||||
surface.setScale(targetscale);
|
surface.setScale(targetscale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scaleCamera(int amount){
|
public void scaleCamera(int amount){
|
||||||
setCameraScale(targetscale + amount);
|
setCameraScale(targetscale + amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clampScale(){
|
public void clampScale(){
|
||||||
float s = io.anuke.ucore.scene.ui.layout.Unit.dp.scl(1f);
|
float s = io.anuke.ucore.scene.ui.layout.Unit.dp.scl(1f);
|
||||||
targetscale = Mathf.clamp(targetscale, Math.round(s*2), Math.round(s*5));
|
targetscale = Mathf.clamp(targetscale, Math.round(s * 2), Math.round(s * 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,30 +9,29 @@ import io.anuke.ucore.util.Log;
|
|||||||
import static io.anuke.mindustry.Vars.control;
|
import static io.anuke.mindustry.Vars.control;
|
||||||
import static io.anuke.mindustry.Vars.logic;
|
import static io.anuke.mindustry.Vars.logic;
|
||||||
|
|
||||||
public class ThreadHandler {
|
public class ThreadHandler{
|
||||||
private final Queue<Runnable> toRun = new Queue<>();
|
private final Queue<Runnable> toRun = new Queue<>();
|
||||||
private final ThreadProvider impl;
|
private final ThreadProvider impl;
|
||||||
|
private final Object updateLock = new Object();
|
||||||
private float delta = 1f;
|
private float delta = 1f;
|
||||||
private float smoothDelta = 1f;
|
private float smoothDelta = 1f;
|
||||||
private long frame = 0, lastDeltaUpdate;
|
private long frame = 0, lastDeltaUpdate;
|
||||||
private float framesSinceUpdate;
|
private float framesSinceUpdate;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
private final Object updateLock = new Object();
|
|
||||||
private boolean rendered = true;
|
private boolean rendered = true;
|
||||||
|
|
||||||
public ThreadHandler(ThreadProvider impl){
|
public ThreadHandler(ThreadProvider impl){
|
||||||
this.impl = impl;
|
this.impl = impl;
|
||||||
|
|
||||||
Timers.setDeltaProvider(() -> {
|
Timers.setDeltaProvider(() -> {
|
||||||
float result = impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime()*60f;
|
float result = impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime() * 60f;
|
||||||
return Math.min(Float.isNaN(result) ? 1f : result, 15f);
|
return Math.min(Float.isNaN(result) ? 1f : result, 15f);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run(Runnable r){
|
public void run(Runnable r){
|
||||||
if(enabled) {
|
if(enabled){
|
||||||
synchronized (toRun) {
|
synchronized(toRun){
|
||||||
toRun.addLast(r);
|
toRun.addLast(r);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -41,7 +40,7 @@ public class ThreadHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void runGraphics(Runnable r){
|
public void runGraphics(Runnable r){
|
||||||
if(enabled) {
|
if(enabled){
|
||||||
Gdx.app.postRunnable(r);
|
Gdx.app.postRunnable(r);
|
||||||
}else{
|
}else{
|
||||||
r.run();
|
r.run();
|
||||||
@@ -49,8 +48,8 @@ public class ThreadHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void runDelay(Runnable r){
|
public void runDelay(Runnable r){
|
||||||
if(enabled) {
|
if(enabled){
|
||||||
synchronized (toRun) {
|
synchronized(toRun){
|
||||||
toRun.addLast(r);
|
toRun.addLast(r);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -59,7 +58,7 @@ public class ThreadHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getTPS(){
|
public int getTPS(){
|
||||||
return (int)(60/smoothDelta);
|
return (int) (60 / smoothDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getFrameID(){
|
public long getFrameID(){
|
||||||
@@ -76,12 +75,16 @@ public class ThreadHandler {
|
|||||||
|
|
||||||
framesSinceUpdate += Timers.delta();
|
framesSinceUpdate += Timers.delta();
|
||||||
|
|
||||||
synchronized (updateLock) {
|
synchronized(updateLock){
|
||||||
rendered = true;
|
rendered = true;
|
||||||
impl.notify(updateLock);
|
impl.notify(updateLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled(){
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled){
|
public void setEnabled(boolean enabled){
|
||||||
if(enabled){
|
if(enabled){
|
||||||
logic.doUpdate = false;
|
logic.doUpdate = false;
|
||||||
@@ -98,10 +101,6 @@ public class ThreadHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled(){
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean doInterpolate(){
|
public boolean doInterpolate(){
|
||||||
return enabled && Gdx.graphics.getFramesPerSecond() - getTPS() > 20 && getTPS() < 30;
|
return enabled && Gdx.graphics.getFramesPerSecond() - getTPS() > 20 && getTPS() < 30;
|
||||||
}
|
}
|
||||||
@@ -111,13 +110,13 @@ public class ThreadHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void runLogic(){
|
private void runLogic(){
|
||||||
try {
|
try{
|
||||||
while (true) {
|
while(true){
|
||||||
long time = TimeUtils.nanoTime();
|
long time = TimeUtils.nanoTime();
|
||||||
|
|
||||||
while(true){
|
while(true){
|
||||||
Runnable r;
|
Runnable r;
|
||||||
synchronized (toRun){
|
synchronized(toRun){
|
||||||
if(toRun.size > 0){
|
if(toRun.size > 0){
|
||||||
r = toRun.removeFirst();
|
r = toRun.removeFirst();
|
||||||
}else{
|
}else{
|
||||||
@@ -135,12 +134,12 @@ public class ThreadHandler {
|
|||||||
long elapsed = TimeUtils.nanosToMillis(TimeUtils.timeSinceNanos(time));
|
long elapsed = TimeUtils.nanosToMillis(TimeUtils.timeSinceNanos(time));
|
||||||
long target = (long) ((1000) / 60f);
|
long target = (long) ((1000) / 60f);
|
||||||
|
|
||||||
if (elapsed < target) {
|
if(elapsed < target){
|
||||||
impl.sleep(target - elapsed);
|
impl.sleep(target - elapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized(updateLock) {
|
synchronized(updateLock){
|
||||||
while(!rendered) {
|
while(!rendered){
|
||||||
impl.wait(updateLock);
|
impl.wait(updateLock);
|
||||||
}
|
}
|
||||||
rendered = false;
|
rendered = false;
|
||||||
@@ -154,22 +153,27 @@ public class ThreadHandler {
|
|||||||
smoothDelta = delta;
|
smoothDelta = delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame ++;
|
frame++;
|
||||||
framesSinceUpdate = 0;
|
framesSinceUpdate = 0;
|
||||||
}
|
}
|
||||||
} catch (InterruptedException ex) {
|
}catch(InterruptedException ex){
|
||||||
Log.info("Stopping logic thread.");
|
Log.info("Stopping logic thread.");
|
||||||
} catch (Throwable ex) {
|
}catch(Throwable ex){
|
||||||
control.setError(ex);
|
control.setError(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ThreadProvider {
|
public interface ThreadProvider{
|
||||||
boolean isOnThread();
|
boolean isOnThread();
|
||||||
|
|
||||||
void sleep(long ms) throws InterruptedException;
|
void sleep(long ms) throws InterruptedException;
|
||||||
|
|
||||||
void start(Runnable run);
|
void start(Runnable run);
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
void wait(Object object) throws InterruptedException;
|
void wait(Object object) throws InterruptedException;
|
||||||
|
|
||||||
void notify(Object object);
|
void notify(Object object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,29 +37,7 @@ import static io.anuke.mindustry.Vars.players;
|
|||||||
import static io.anuke.ucore.scene.actions.Actions.*;
|
import static io.anuke.ucore.scene.actions.Actions.*;
|
||||||
|
|
||||||
public class UI extends SceneModule{
|
public class UI extends SceneModule{
|
||||||
public AboutDialog about;
|
public final MenuFragment menufrag = new MenuFragment();
|
||||||
public RestartDialog restart;
|
|
||||||
public LevelDialog levels;
|
|
||||||
public MapsDialog maps;
|
|
||||||
public LoadDialog load;
|
|
||||||
public DiscordDialog discord;
|
|
||||||
public JoinDialog join;
|
|
||||||
public HostDialog host;
|
|
||||||
public PausedDialog paused;
|
|
||||||
public SettingsMenuDialog settings;
|
|
||||||
public ControlsDialog controls;
|
|
||||||
public MapEditorDialog editor;
|
|
||||||
public LanguageDialog language;
|
|
||||||
public BansDialog bans;
|
|
||||||
public AdminsDialog admins;
|
|
||||||
public TraceDialog traces;
|
|
||||||
public RollbackDialog rollback;
|
|
||||||
public ChangelogDialog changelog;
|
|
||||||
public LocalPlayerDialog localplayers;
|
|
||||||
public UnlocksDialog unlocks;
|
|
||||||
public ContentInfoDialog content;
|
|
||||||
|
|
||||||
public final MenuFragment menufrag = new MenuFragment();
|
|
||||||
public final HudFragment hudfrag = new HudFragment();
|
public final HudFragment hudfrag = new HudFragment();
|
||||||
public final ChatFragment chatfrag = new ChatFragment();
|
public final ChatFragment chatfrag = new ChatFragment();
|
||||||
public final PlayerListFragment listfrag = new PlayerListFragment();
|
public final PlayerListFragment listfrag = new PlayerListFragment();
|
||||||
@@ -67,239 +45,246 @@ public class UI extends SceneModule{
|
|||||||
public final LoadingFragment loadfrag = new LoadingFragment();
|
public final LoadingFragment loadfrag = new LoadingFragment();
|
||||||
public final DebugFragment debugfrag = new DebugFragment();
|
public final DebugFragment debugfrag = new DebugFragment();
|
||||||
|
|
||||||
|
public AboutDialog about;
|
||||||
|
public RestartDialog restart;
|
||||||
|
public LevelDialog levels;
|
||||||
|
public MapsDialog maps;
|
||||||
|
public LoadDialog load;
|
||||||
|
public DiscordDialog discord;
|
||||||
|
public JoinDialog join;
|
||||||
|
public HostDialog host;
|
||||||
|
public PausedDialog paused;
|
||||||
|
public SettingsMenuDialog settings;
|
||||||
|
public ControlsDialog controls;
|
||||||
|
public MapEditorDialog editor;
|
||||||
|
public LanguageDialog language;
|
||||||
|
public BansDialog bans;
|
||||||
|
public AdminsDialog admins;
|
||||||
|
public TraceDialog traces;
|
||||||
|
public RollbackDialog rollback;
|
||||||
|
public ChangelogDialog changelog;
|
||||||
|
public LocalPlayerDialog localplayers;
|
||||||
|
public UnlocksDialog unlocks;
|
||||||
|
public ContentInfoDialog content;
|
||||||
|
|
||||||
private Locale lastLocale;
|
private Locale lastLocale;
|
||||||
|
|
||||||
public UI() {
|
|
||||||
Dialog.setShowAction(()-> sequence(
|
|
||||||
alpha(0f),
|
|
||||||
originCenter(),
|
|
||||||
moveToAligned(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2, Align.center),
|
|
||||||
scaleTo(0.0f, 1f),
|
|
||||||
parallel(
|
|
||||||
scaleTo(1f, 1f, 0.1f, Interpolation.fade),
|
|
||||||
fadeIn(0.1f, Interpolation.fade)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
|
|
||||||
Dialog.setHideAction(()-> sequence(
|
|
||||||
parallel(
|
|
||||||
scaleTo(0.01f, 0.01f, 0.1f, Interpolation.fade),
|
|
||||||
fadeOut(0.1f, Interpolation.fade)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
|
|
||||||
TooltipManager.getInstance().animations = false;
|
|
||||||
|
|
||||||
Settings.setErrorHandler(()-> Timers.run(1f, ()-> showError("[crimson]Failed to access local storage.\nSettings will not be saved.")));
|
|
||||||
|
|
||||||
Dialog.closePadR = -1;
|
|
||||||
Dialog.closePadT = 5;
|
|
||||||
|
|
||||||
Colors.put("description", Palette.description);
|
|
||||||
Colors.put("turretinfo", Palette.turretinfo);
|
|
||||||
Colors.put("iteminfo", Palette.iteminfo);
|
|
||||||
Colors.put("powerinfo", Palette.powerinfo);
|
|
||||||
Colors.put("liquidinfo", Palette.liquidinfo);
|
|
||||||
Colors.put("craftinfo", Palette.craftinfo);
|
|
||||||
Colors.put("missingitems", Palette.missingitems);
|
|
||||||
Colors.put("health", Palette.health);
|
|
||||||
Colors.put("healthstats", Palette.healthstats);
|
|
||||||
Colors.put("interact", Palette.interact);
|
|
||||||
Colors.put("accent", Palette.accent);
|
|
||||||
Colors.put("place", Palette.place);
|
|
||||||
Colors.put("remove", Palette.remove);
|
|
||||||
Colors.put("placeRotate", Palette.placeRotate);
|
|
||||||
Colors.put("range", Palette.range);
|
|
||||||
Colors.put("power", Palette.power);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public UI(){
|
||||||
protected void loadSkin(){
|
Dialog.setShowAction(() -> sequence(
|
||||||
skin = new Skin(Gdx.files.internal("ui/uiskin.json"), Core.atlas);
|
alpha(0f),
|
||||||
Mathf.each(font -> {
|
originCenter(),
|
||||||
font.setUseIntegerPositions(false);
|
moveToAligned(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, Align.center),
|
||||||
font.getData().setScale(Vars.fontScale);
|
scaleTo(0.0f, 1f),
|
||||||
font.getData().down += Unit.dp.scl(4f);
|
parallel(
|
||||||
font.getData().lineHeight -= Unit.dp.scl(2f);
|
scaleTo(1f, 1f, 0.1f, Interpolation.fade),
|
||||||
}, skin.font(), skin.getFont("default-font-chat"), skin.getFont("korean"));
|
fadeIn(0.1f, Interpolation.fade)
|
||||||
}
|
)
|
||||||
|
));
|
||||||
|
|
||||||
@Override
|
Dialog.setHideAction(() -> sequence(
|
||||||
public synchronized void update(){
|
parallel(
|
||||||
if(Vars.debug && !Vars.showUI) return;
|
scaleTo(0.01f, 0.01f, 0.1f, Interpolation.fade),
|
||||||
|
fadeOut(0.1f, Interpolation.fade)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
|
||||||
if(Graphics.drawing()) Graphics.end();
|
TooltipManager.getInstance().animations = false;
|
||||||
|
|
||||||
act();
|
|
||||||
|
|
||||||
Graphics.begin();
|
Settings.setErrorHandler(() -> Timers.run(1f, () -> showError("[crimson]Failed to access local storage.\nSettings will not be saved.")));
|
||||||
|
|
||||||
for(int i = 0; i < players.length; i ++){
|
Dialog.closePadR = -1;
|
||||||
InputHandler input = control.input(i);
|
Dialog.closePadT = 5;
|
||||||
|
|
||||||
if(input.isCursorVisible()) {
|
Colors.put("description", Palette.description);
|
||||||
|
Colors.put("turretinfo", Palette.turretinfo);
|
||||||
|
Colors.put("iteminfo", Palette.iteminfo);
|
||||||
|
Colors.put("powerinfo", Palette.powerinfo);
|
||||||
|
Colors.put("liquidinfo", Palette.liquidinfo);
|
||||||
|
Colors.put("craftinfo", Palette.craftinfo);
|
||||||
|
Colors.put("missingitems", Palette.missingitems);
|
||||||
|
Colors.put("health", Palette.health);
|
||||||
|
Colors.put("healthstats", Palette.healthstats);
|
||||||
|
Colors.put("interact", Palette.interact);
|
||||||
|
Colors.put("accent", Palette.accent);
|
||||||
|
Colors.put("place", Palette.place);
|
||||||
|
Colors.put("remove", Palette.remove);
|
||||||
|
Colors.put("placeRotate", Palette.placeRotate);
|
||||||
|
Colors.put("range", Palette.range);
|
||||||
|
Colors.put("power", Palette.power);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadSkin(){
|
||||||
|
skin = new Skin(Gdx.files.internal("ui/uiskin.json"), Core.atlas);
|
||||||
|
Mathf.each(font -> {
|
||||||
|
font.setUseIntegerPositions(false);
|
||||||
|
font.getData().setScale(Vars.fontScale);
|
||||||
|
font.getData().down += Unit.dp.scl(4f);
|
||||||
|
font.getData().lineHeight -= Unit.dp.scl(2f);
|
||||||
|
}, skin.font(), skin.getFont("default-font-chat"), skin.getFont("korean"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void update(){
|
||||||
|
if(Vars.debug && !Vars.showUI) return;
|
||||||
|
|
||||||
|
if(Graphics.drawing()) Graphics.end();
|
||||||
|
|
||||||
|
act();
|
||||||
|
|
||||||
|
Graphics.begin();
|
||||||
|
|
||||||
|
for(int i = 0; i < players.length; i++){
|
||||||
|
InputHandler input = control.input(i);
|
||||||
|
|
||||||
|
if(input.isCursorVisible()){
|
||||||
Draw.color();
|
Draw.color();
|
||||||
|
|
||||||
float scl = Unit.dp.scl(3f);
|
float scl = Unit.dp.scl(3f);
|
||||||
|
|
||||||
Draw.rect("controller-cursor", input.getMouseX(), Gdx.graphics.getHeight() - input.getMouseY(), 16*scl, 16*scl);
|
Draw.rect("controller-cursor", input.getMouseX(), Gdx.graphics.getHeight() - input.getMouseY(), 16 * scl, 16 * scl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Graphics.end();
|
Graphics.end();
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
editor = new MapEditorDialog();
|
editor = new MapEditorDialog();
|
||||||
controls = new ControlsDialog();
|
controls = new ControlsDialog();
|
||||||
restart = new RestartDialog();
|
restart = new RestartDialog();
|
||||||
join = new JoinDialog();
|
join = new JoinDialog();
|
||||||
discord = new DiscordDialog();
|
discord = new DiscordDialog();
|
||||||
load = new LoadDialog();
|
load = new LoadDialog();
|
||||||
levels = new LevelDialog();
|
levels = new LevelDialog();
|
||||||
language = new LanguageDialog();
|
language = new LanguageDialog();
|
||||||
settings = new SettingsMenuDialog();
|
settings = new SettingsMenuDialog();
|
||||||
paused = new PausedDialog();
|
paused = new PausedDialog();
|
||||||
changelog = new ChangelogDialog();
|
changelog = new ChangelogDialog();
|
||||||
about = new AboutDialog();
|
about = new AboutDialog();
|
||||||
host = new HostDialog();
|
host = new HostDialog();
|
||||||
bans = new BansDialog();
|
bans = new BansDialog();
|
||||||
admins = new AdminsDialog();
|
admins = new AdminsDialog();
|
||||||
traces = new TraceDialog();
|
traces = new TraceDialog();
|
||||||
rollback = new RollbackDialog();
|
rollback = new RollbackDialog();
|
||||||
maps = new MapsDialog();
|
maps = new MapsDialog();
|
||||||
localplayers = new LocalPlayerDialog();
|
localplayers = new LocalPlayerDialog();
|
||||||
unlocks = new UnlocksDialog();
|
unlocks = new UnlocksDialog();
|
||||||
content = new ContentInfoDialog();
|
content = new ContentInfoDialog();
|
||||||
|
|
||||||
build.begin(scene);
|
build.begin(scene);
|
||||||
|
|
||||||
Group group = Core.scene.getRoot();
|
Group group = Core.scene.getRoot();
|
||||||
|
|
||||||
backfrag.build(group);
|
backfrag.build(group);
|
||||||
hudfrag.build(group);
|
hudfrag.build(group);
|
||||||
menufrag.build(group);
|
menufrag.build(group);
|
||||||
chatfrag.container().build(group);
|
chatfrag.container().build(group);
|
||||||
listfrag.build(group);
|
listfrag.build(group);
|
||||||
debugfrag.build(group);
|
debugfrag.build(group);
|
||||||
loadfrag.build(group);
|
loadfrag.build(group);
|
||||||
|
|
||||||
build.end();
|
build.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasMouse() {
|
public boolean hasMouse(){
|
||||||
return super.hasMouse();
|
return super.hasMouse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resize(int width, int height) {
|
public void resize(int width, int height){
|
||||||
super.resize(width, height);
|
super.resize(width, height);
|
||||||
|
|
||||||
Events.fire(ResizeEvent.class);
|
Events.fire(ResizeEvent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Locale getLocale(){
|
public Locale getLocale(){
|
||||||
String loc = Settings.getString("locale");
|
String loc = Settings.getString("locale");
|
||||||
if(loc.equals("default")){
|
if(loc.equals("default")){
|
||||||
return Locale.getDefault();
|
return Locale.getDefault();
|
||||||
}else{
|
}else{
|
||||||
if(lastLocale == null || !lastLocale.toString().equals(loc)){
|
if(lastLocale == null || !lastLocale.toString().equals(loc)){
|
||||||
if(loc.contains("_")){
|
if(loc.contains("_")){
|
||||||
String[] split = loc.split("_");
|
String[] split = loc.split("_");
|
||||||
lastLocale = new Locale(split[0], split[1]);
|
lastLocale = new Locale(split[0], split[1]);
|
||||||
}else{
|
}else{
|
||||||
lastLocale = new Locale(loc);
|
lastLocale = new Locale(loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastLocale;
|
return lastLocale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadAnd(Callable call){
|
public void loadAnd(Callable call){
|
||||||
loadAnd("$text.loading", call);
|
loadAnd("$text.loading", call);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadAnd(String text, Callable call){
|
public void loadAnd(String text, Callable call){
|
||||||
loadfrag.show(text);
|
loadfrag.show(text);
|
||||||
Timers.runTask(7f, () -> {
|
Timers.runTask(7f, () -> {
|
||||||
call.run();
|
call.run();
|
||||||
loadfrag.hide();
|
loadfrag.hide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showTextInput(String title, String text, String def, TextFieldFilter filter, Consumer<String> confirmed){
|
public void showTextInput(String title, String text, String def, TextFieldFilter filter, Consumer<String> confirmed){
|
||||||
new Dialog(title, "dialog"){{
|
new Dialog(title, "dialog"){{
|
||||||
content().margin(30).add(text).padRight(6f);
|
content().margin(30).add(text).padRight(6f);
|
||||||
TextField field = content().addField(def, t->{}).size(170f, 50f).get();
|
TextField field = content().addField(def, t -> {
|
||||||
field.setTextFieldFilter((f, c) -> field.getText().length() < 12 && filter.acceptChar(f, c));
|
}).size(170f, 50f).get();
|
||||||
Platform.instance.addDialog(field);
|
field.setTextFieldFilter((f, c) -> field.getText().length() < 12 && filter.acceptChar(f, c));
|
||||||
buttons().defaults().size(120, 54).pad(4);
|
Platform.instance.addDialog(field);
|
||||||
buttons().addButton("$text.ok", () -> {
|
buttons().defaults().size(120, 54).pad(4);
|
||||||
confirmed.accept(field.getText());
|
buttons().addButton("$text.ok", () -> {
|
||||||
hide();
|
confirmed.accept(field.getText());
|
||||||
}).disabled(b -> field.getText().isEmpty());
|
hide();
|
||||||
buttons().addButton("$text.cancel", this::hide);
|
}).disabled(b -> field.getText().isEmpty());
|
||||||
}}.show();
|
buttons().addButton("$text.cancel", this::hide);
|
||||||
}
|
}}.show();
|
||||||
|
}
|
||||||
|
|
||||||
public void showTextInput(String title, String text, String def, Consumer<String> confirmed){
|
public void showTextInput(String title, String text, String def, Consumer<String> confirmed){
|
||||||
showTextInput(title, text, def, (field, c) -> true, confirmed);
|
showTextInput(title, text, def, (field, c) -> true, confirmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showInfoFade(String info){
|
public void showInfoFade(String info){
|
||||||
Table table = new Table();
|
Table table = new Table();
|
||||||
table.setFillParent(true);
|
table.setFillParent(true);
|
||||||
table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor());
|
table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor());
|
||||||
table.top().add(info).padTop(8);
|
table.top().add(info).padTop(8);
|
||||||
Core.scene.add(table);
|
Core.scene.add(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showInfo(String info){
|
public void showInfo(String info){
|
||||||
new Dialog("$text.info.title", "dialog"){{
|
new Dialog("$text.info.title", "dialog"){{
|
||||||
getCell(content()).growX();
|
getCell(content()).growX();
|
||||||
content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
|
content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
|
||||||
buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
|
buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
|
||||||
}}.show();
|
}}.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showError(String text){
|
public void showError(String text){
|
||||||
new Dialog("$text.error.title", "dialog"){{
|
new Dialog("$text.error.title", "dialog"){{
|
||||||
content().margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
|
content().margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
|
||||||
buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
|
buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
|
||||||
}}.show();
|
}}.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showConfirm(String title, String text, Listenable confirmed){
|
public void showConfirm(String title, String text, Listenable confirmed){
|
||||||
FloatingDialog dialog = new FloatingDialog(title);
|
FloatingDialog dialog = new FloatingDialog(title);
|
||||||
dialog.content().add(text).width(400f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
|
dialog.content().add(text).width(400f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
|
||||||
dialog.buttons().defaults().size(200f, 54f).pad(2f);
|
dialog.buttons().defaults().size(200f, 54f).pad(2f);
|
||||||
dialog.buttons().addButton("$text.cancel", dialog::hide);
|
dialog.buttons().addButton("$text.cancel", dialog::hide);
|
||||||
dialog.buttons().addButton("$text.ok", () -> {
|
dialog.buttons().addButton("$text.ok", () -> {
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
confirmed.listen();
|
confirmed.listen();
|
||||||
});
|
});
|
||||||
dialog.keyDown(Keys.ESCAPE, dialog::hide);
|
dialog.keyDown(Keys.ESCAPE, dialog::hide);
|
||||||
dialog.keyDown(Keys.BACK, dialog::hide);
|
dialog.keyDown(Keys.BACK, dialog::hide);
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showConfirmListen(String title, String text, Consumer<Boolean> listener){
|
|
||||||
FloatingDialog dialog = new FloatingDialog(title);
|
|
||||||
dialog.content().add(text).pad(4f);
|
|
||||||
dialog.buttons().defaults().size(200f, 54f).pad(2f);
|
|
||||||
dialog.buttons().addButton("$text.cancel", () -> {
|
|
||||||
dialog.hide();
|
|
||||||
listener.accept(true);
|
|
||||||
});
|
|
||||||
dialog.buttons().addButton("$text.ok", () -> {
|
|
||||||
dialog.hide();
|
|
||||||
listener.accept(true);
|
|
||||||
});
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ import io.anuke.mindustry.core.GameState.State;
|
|||||||
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
||||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.io.*;
|
import io.anuke.mindustry.io.Map;
|
||||||
|
import io.anuke.mindustry.io.MapIO;
|
||||||
|
import io.anuke.mindustry.io.MapMeta;
|
||||||
|
import io.anuke.mindustry.io.Maps;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.mapgen.WorldGenerator;
|
import io.anuke.mindustry.world.mapgen.WorldGenerator;
|
||||||
@@ -27,124 +30,130 @@ import io.anuke.ucore.util.Tmp;
|
|||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class World extends Module{
|
public class World extends Module{
|
||||||
private int seed;
|
private int seed;
|
||||||
|
|
||||||
private Map currentMap;
|
|
||||||
private Tile[][] tiles;
|
|
||||||
private Pathfinder pathfinder = new Pathfinder();
|
|
||||||
private BlockIndexer indexer = new BlockIndexer();
|
|
||||||
private Maps maps = new Maps();
|
|
||||||
|
|
||||||
private Array<Tile> tempTiles = new ThreadArray<>();
|
private Map currentMap;
|
||||||
private boolean generating, invalidMap;
|
private Tile[][] tiles;
|
||||||
|
private Pathfinder pathfinder = new Pathfinder();
|
||||||
public World(){
|
private BlockIndexer indexer = new BlockIndexer();
|
||||||
maps.load();
|
private Maps maps = new Maps();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispose(){
|
|
||||||
maps.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Maps maps(){
|
|
||||||
return maps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockIndexer indexer() {
|
private Array<Tile> tempTiles = new ThreadArray<>();
|
||||||
return indexer;
|
private boolean generating, invalidMap;
|
||||||
}
|
|
||||||
|
|
||||||
public Pathfinder pathfinder(){
|
public World(){
|
||||||
return pathfinder;
|
maps.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInvalidMap() {
|
@Override
|
||||||
return invalidMap;
|
public void dispose(){
|
||||||
}
|
maps.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean solid(int x, int y){
|
public Maps maps(){
|
||||||
Tile tile = tile(x, y);
|
return maps;
|
||||||
|
}
|
||||||
return tile == null || tile.solid();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean passable(int x, int y){
|
|
||||||
Tile tile = tile(x, y);
|
|
||||||
|
|
||||||
return tile != null && tile.passable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean wallSolid(int x, int y){
|
|
||||||
Tile tile = tile(x, y);
|
|
||||||
return tile == null || tile.block().solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAccessible(int x, int y){
|
|
||||||
return !wallSolid(x, y-1) || !wallSolid(x, y+1) || !wallSolid(x-1, y) ||!wallSolid(x+1, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean floorBlends(int x, int y, Block block){
|
|
||||||
Tile tile = tile(x, y);
|
|
||||||
return tile == null || tile.floor().id <= block.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map getMap(){
|
|
||||||
return currentMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int width(){
|
|
||||||
return tiles == null ? 0 : tiles.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int height(){
|
|
||||||
return tiles == null ? 0 : tiles[0].length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int toPacked(int x, int y){
|
public BlockIndexer indexer(){
|
||||||
return x + y *width();
|
return indexer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile tile(int packed){
|
public Pathfinder pathfinder(){
|
||||||
return tiles == null ? null : tile(packed % width(), packed / width());
|
return pathfinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile tile(int x, int y){
|
|
||||||
if(tiles == null){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if(!Mathf.inBounds(x, y, tiles)) return null;
|
|
||||||
return tiles[x][y];
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tile rawTile(int x, int y){
|
public boolean isInvalidMap(){
|
||||||
return tiles[x][y];
|
return invalidMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile tileWorld(float x, float y){
|
|
||||||
return tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int toTile(float coord){
|
public boolean solid(int x, int y){
|
||||||
return Mathf.scl2(coord, tilesize);
|
Tile tile = tile(x, y);
|
||||||
}
|
|
||||||
|
|
||||||
public Tile[][] getTiles(){
|
|
||||||
return tiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearTileEntities(){
|
|
||||||
for(int x = 0; x < tiles.length; x ++){
|
|
||||||
for(int y = 0; y < tiles[0].length; y ++){
|
|
||||||
if(tiles[x][y] != null && tiles[x][y].entity != null){
|
|
||||||
tiles[x][y].entity.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Resizes the tile array to the specified size and returns the resulting tile array.
|
return tile == null || tile.solid();
|
||||||
* Only use for loading saves!*/
|
}
|
||||||
|
|
||||||
|
public boolean passable(int x, int y){
|
||||||
|
Tile tile = tile(x, y);
|
||||||
|
|
||||||
|
return tile != null && tile.passable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean wallSolid(int x, int y){
|
||||||
|
Tile tile = tile(x, y);
|
||||||
|
return tile == null || tile.block().solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAccessible(int x, int y){
|
||||||
|
return !wallSolid(x, y - 1) || !wallSolid(x, y + 1) || !wallSolid(x - 1, y) || !wallSolid(x + 1, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean floorBlends(int x, int y, Block block){
|
||||||
|
Tile tile = tile(x, y);
|
||||||
|
return tile == null || tile.floor().id <= block.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map getMap(){
|
||||||
|
return currentMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMap(Map map){
|
||||||
|
this.currentMap = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int width(){
|
||||||
|
return tiles == null ? 0 : tiles.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int height(){
|
||||||
|
return tiles == null ? 0 : tiles[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int toPacked(int x, int y){
|
||||||
|
return x + y * width();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tile tile(int packed){
|
||||||
|
return tiles == null ? null : tile(packed % width(), packed / width());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tile tile(int x, int y){
|
||||||
|
if(tiles == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if(!Mathf.inBounds(x, y, tiles)) return null;
|
||||||
|
return tiles[x][y];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tile rawTile(int x, int y){
|
||||||
|
return tiles[x][y];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tile tileWorld(float x, float y){
|
||||||
|
return tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int toTile(float coord){
|
||||||
|
return Mathf.scl2(coord, tilesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tile[][] getTiles(){
|
||||||
|
return tiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearTileEntities(){
|
||||||
|
for(int x = 0; x < tiles.length; x++){
|
||||||
|
for(int y = 0; y < tiles[0].length; y++){
|
||||||
|
if(tiles[x][y] != null && tiles[x][y].entity != null){
|
||||||
|
tiles[x][y].entity.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes the tile array to the specified size and returns the resulting tile array.
|
||||||
|
* Only use for loading saves!
|
||||||
|
*/
|
||||||
public Tile[][] createTiles(int width, int height){
|
public Tile[][] createTiles(int width, int height){
|
||||||
if(tiles != null){
|
if(tiles != null){
|
||||||
clearTileEntities();
|
clearTileEntities();
|
||||||
@@ -159,207 +168,214 @@ public class World extends Module{
|
|||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Call to signify the beginning of map loading.
|
/**
|
||||||
* TileChangeEvents will not be fired until endMapLoad().*/
|
* Call to signify the beginning of map loading.
|
||||||
public void beginMapLoad(){
|
* TileChangeEvents will not be fired until endMapLoad().
|
||||||
generating = true;
|
*/
|
||||||
}
|
public void beginMapLoad(){
|
||||||
|
generating = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**Call to signify the end of map loading. Updates tile occlusions and sets up physics for the world.
|
/**
|
||||||
* A WorldLoadEvent will be fire.*/
|
* Call to signify the end of map loading. Updates tile occlusions and sets up physics for the world.
|
||||||
public void endMapLoad(){
|
* A WorldLoadEvent will be fire.
|
||||||
for(int x = 0; x < tiles.length; x ++) {
|
*/
|
||||||
for (int y = 0; y < tiles[0].length; y++) {
|
public void endMapLoad(){
|
||||||
tiles[x][y].updateOcclusion();
|
for(int x = 0; x < tiles.length; x++){
|
||||||
|
for(int y = 0; y < tiles[0].length; y++){
|
||||||
|
tiles[x][y].updateOcclusion();
|
||||||
|
|
||||||
if(tiles[x][y].entity != null){
|
if(tiles[x][y].entity != null){
|
||||||
tiles[x][y].entity.updateProximity();
|
tiles[x][y].entity.updateProximity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityPhysics.resizeTree(0, 0, tiles.length * tilesize, tiles[0].length * tilesize);
|
EntityPhysics.resizeTree(0, 0, tiles.length * tilesize, tiles[0].length * tilesize);
|
||||||
|
|
||||||
generating = false;
|
generating = false;
|
||||||
Events.fire(WorldLoadEvent.class);
|
Events.fire(WorldLoadEvent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Loads up a procedural map. This does not call play(), but calls reset().*/
|
/**
|
||||||
public void loadProceduralMap(){
|
* Loads up a procedural map. This does not call play(), but calls reset().
|
||||||
Timers.mark();
|
*/
|
||||||
Timers.mark();
|
public void loadProceduralMap(){
|
||||||
|
Timers.mark();
|
||||||
|
Timers.mark();
|
||||||
|
|
||||||
logic.reset();
|
logic.reset();
|
||||||
|
|
||||||
beginMapLoad();
|
beginMapLoad();
|
||||||
|
|
||||||
int width = 400, height = 400;
|
int width = 400, height = 400;
|
||||||
|
|
||||||
Tile[][] tiles = createTiles(width, height);
|
Tile[][] tiles = createTiles(width, height);
|
||||||
|
|
||||||
Map map = new Map("Generated Map", new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null);
|
Map map = new Map("Generated Map", new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null);
|
||||||
setMap(map);
|
setMap(map);
|
||||||
|
|
||||||
EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize);
|
EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize);
|
||||||
|
|
||||||
Timers.mark();
|
Timers.mark();
|
||||||
WorldGenerator.generateMap(tiles, Mathf.random(9999999));
|
WorldGenerator.generateMap(tiles, Mathf.random(9999999));
|
||||||
Log.info("Time to generate base map: {0}", Timers.elapsed());
|
Log.info("Time to generate base map: {0}", Timers.elapsed());
|
||||||
|
|
||||||
Log.info("Time to generate fully without additional events: {0}", Timers.elapsed());
|
Log.info("Time to generate fully without additional events: {0}", Timers.elapsed());
|
||||||
|
|
||||||
endMapLoad();
|
endMapLoad();
|
||||||
|
|
||||||
Log.info("Full time to generate: {0}", Timers.elapsed());
|
Log.info("Full time to generate: {0}", Timers.elapsed());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMap(Map map){
|
public void loadMap(Map map){
|
||||||
this.currentMap = map;
|
loadMap(map, MathUtils.random(0, 999999));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadMap(Map map){
|
|
||||||
loadMap(map, MathUtils.random(0, 999999));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadMap(Map map, int seed){
|
|
||||||
beginMapLoad();
|
|
||||||
this.currentMap = map;
|
|
||||||
this.seed = seed;
|
|
||||||
|
|
||||||
int width = map.meta.width, height = map.meta.height;
|
public void loadMap(Map map, int seed){
|
||||||
|
beginMapLoad();
|
||||||
|
this.currentMap = map;
|
||||||
|
this.seed = seed;
|
||||||
|
|
||||||
createTiles(width, height);
|
int width = map.meta.width, height = map.meta.height;
|
||||||
|
|
||||||
EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize);
|
|
||||||
|
|
||||||
WorldGenerator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), seed);
|
createTiles(width, height);
|
||||||
|
|
||||||
if(!headless && state.teams.get(players[0].getTeam()).cores.size == 0){
|
EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize);
|
||||||
ui.showError("$text.map.nospawn");
|
|
||||||
threads.runDelay(() -> state.set(State.menu));
|
|
||||||
invalidMap = true;
|
|
||||||
}else{
|
|
||||||
invalidMap = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
endMapLoad();
|
WorldGenerator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), seed);
|
||||||
}
|
|
||||||
|
|
||||||
public int getSeed(){
|
if(!headless && state.teams.get(players[0].getTeam()).cores.size == 0){
|
||||||
return seed;
|
ui.showError("$text.map.nospawn");
|
||||||
}
|
threads.runDelay(() -> state.set(State.menu));
|
||||||
|
invalidMap = true;
|
||||||
|
}else{
|
||||||
|
invalidMap = false;
|
||||||
|
}
|
||||||
|
|
||||||
public void notifyChanged(Tile tile){
|
endMapLoad();
|
||||||
if(!generating){
|
}
|
||||||
threads.runDelay(() -> Events.fire(TileChangeEvent.class, tile));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeBlock(Tile tile){
|
public int getSeed(){
|
||||||
if(!tile.block().isMultiblock() && !tile.isLinked()){
|
return seed;
|
||||||
tile.setBlock(Blocks.air);
|
}
|
||||||
}else{
|
|
||||||
Tile target = tile.target();
|
|
||||||
Array<Tile> removals = target.getLinkedTiles(tempTiles);
|
|
||||||
for(Tile toremove : removals){
|
|
||||||
//note that setting a new block automatically unlinks it
|
|
||||||
if(toremove != null) toremove.setBlock(Blocks.air);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlock(Tile tile, Block block, Team team){
|
public void notifyChanged(Tile tile){
|
||||||
tile.setBlock(block);
|
if(!generating){
|
||||||
if (block.isMultiblock()) {
|
threads.runDelay(() -> Events.fire(TileChangeEvent.class, tile));
|
||||||
int offsetx = -(block.size - 1) / 2;
|
}
|
||||||
int offsety = -(block.size - 1) / 2;
|
}
|
||||||
|
|
||||||
for (int dx = 0; dx < block.size; dx++) {
|
public void removeBlock(Tile tile){
|
||||||
for (int dy = 0; dy < block.size; dy++) {
|
if(!tile.block().isMultiblock() && !tile.isLinked()){
|
||||||
int worldx = dx + offsetx + tile.x;
|
tile.setBlock(Blocks.air);
|
||||||
int worldy = dy + offsety + tile.y;
|
}else{
|
||||||
if (!(worldx == tile.x && worldy == tile.y)) {
|
Tile target = tile.target();
|
||||||
Tile toplace = world.tile(worldx, worldy);
|
Array<Tile> removals = target.getLinkedTiles(tempTiles);
|
||||||
if (toplace != null) {
|
for(Tile toremove : removals){
|
||||||
toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety));
|
//note that setting a new block automatically unlinks it
|
||||||
toplace.setTeam(team);
|
if(toremove != null) toremove.setBlock(Blocks.air);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Raycast, but with world coordinates.*/
|
public void setBlock(Tile tile, Block block, Team team){
|
||||||
public GridPoint2 raycastWorld(float x, float y, float x2, float y2){
|
tile.setBlock(block);
|
||||||
return raycast(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize),
|
if(block.isMultiblock()){
|
||||||
Mathf.scl2(x2, tilesize), Mathf.scl2(y2, tilesize));
|
int offsetx = -(block.size - 1) / 2;
|
||||||
}
|
int offsety = -(block.size - 1) / 2;
|
||||||
|
|
||||||
/**Input is in block coordinates, not world coordinates.
|
|
||||||
* @return null if no collisions found, block position otherwise.*/
|
|
||||||
public GridPoint2 raycast(int x0f, int y0f, int x1, int y1){
|
|
||||||
int x0 = x0f;
|
|
||||||
int y0 = y0f;
|
|
||||||
int dx = Math.abs(x1 - x0);
|
|
||||||
int dy = Math.abs(y1 - y0);
|
|
||||||
|
|
||||||
int sx = x0 < x1 ? 1 : -1;
|
for(int dx = 0; dx < block.size; dx++){
|
||||||
int sy = y0 < y1 ? 1 : -1;
|
for(int dy = 0; dy < block.size; dy++){
|
||||||
|
int worldx = dx + offsetx + tile.x;
|
||||||
|
int worldy = dy + offsety + tile.y;
|
||||||
|
if(!(worldx == tile.x && worldy == tile.y)){
|
||||||
|
Tile toplace = world.tile(worldx, worldy);
|
||||||
|
if(toplace != null){
|
||||||
|
toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety));
|
||||||
|
toplace.setTeam(team);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int err = dx - dy;
|
/**
|
||||||
int e2;
|
* Raycast, but with world coordinates.
|
||||||
while(true){
|
*/
|
||||||
|
public GridPoint2 raycastWorld(float x, float y, float x2, float y2){
|
||||||
|
return raycast(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize),
|
||||||
|
Mathf.scl2(x2, tilesize), Mathf.scl2(y2, tilesize));
|
||||||
|
}
|
||||||
|
|
||||||
if(!passable(x0, y0)){
|
/**
|
||||||
return Tmp.g1.set(x0, y0);
|
* Input is in block coordinates, not world coordinates.
|
||||||
}
|
*
|
||||||
if(x0 == x1 && y0 == y1) break;
|
* @return null if no collisions found, block position otherwise.
|
||||||
|
*/
|
||||||
|
public GridPoint2 raycast(int x0f, int y0f, int x1, int y1){
|
||||||
|
int x0 = x0f;
|
||||||
|
int y0 = y0f;
|
||||||
|
int dx = Math.abs(x1 - x0);
|
||||||
|
int dy = Math.abs(y1 - y0);
|
||||||
|
|
||||||
e2 = 2 * err;
|
int sx = x0 < x1 ? 1 : -1;
|
||||||
if(e2 > -dy){
|
int sy = y0 < y1 ? 1 : -1;
|
||||||
err = err - dy;
|
|
||||||
x0 = x0 + sx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e2 < dx){
|
int err = dx - dy;
|
||||||
err = err + dx;
|
int e2;
|
||||||
y0 = y0 + sy;
|
while(true){
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void raycastEach(int x0f, int y0f, int x1, int y1, Raycaster cons){
|
if(!passable(x0, y0)){
|
||||||
int x0 = x0f;
|
return Tmp.g1.set(x0, y0);
|
||||||
int y0 = y0f;
|
}
|
||||||
int dx = Math.abs(x1 - x0);
|
if(x0 == x1 && y0 == y1) break;
|
||||||
int dy = Math.abs(y1 - y0);
|
|
||||||
|
|
||||||
int sx = x0 < x1 ? 1 : -1;
|
e2 = 2 * err;
|
||||||
int sy = y0 < y1 ? 1 : -1;
|
if(e2 > -dy){
|
||||||
|
err = err - dy;
|
||||||
|
x0 = x0 + sx;
|
||||||
|
}
|
||||||
|
|
||||||
int err = dx - dy;
|
if(e2 < dx){
|
||||||
int e2;
|
err = err + dx;
|
||||||
while(true){
|
y0 = y0 + sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if(cons.accept(x0, y0)) break;
|
public void raycastEach(int x0f, int y0f, int x1, int y1, Raycaster cons){
|
||||||
if(x0 == x1 && y0 == y1) break;
|
int x0 = x0f;
|
||||||
|
int y0 = y0f;
|
||||||
|
int dx = Math.abs(x1 - x0);
|
||||||
|
int dy = Math.abs(y1 - y0);
|
||||||
|
|
||||||
e2 = 2 * err;
|
int sx = x0 < x1 ? 1 : -1;
|
||||||
if(e2 > -dy){
|
int sy = y0 < y1 ? 1 : -1;
|
||||||
err = err - dy;
|
|
||||||
x0 = x0 + sx;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(e2 < dx){
|
int err = dx - dy;
|
||||||
err = err + dx;
|
int e2;
|
||||||
y0 = y0 + sy;
|
while(true){
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Raycaster{
|
if(cons.accept(x0, y0)) break;
|
||||||
boolean accept(int x, int y);
|
if(x0 == x1 && y0 == y1) break;
|
||||||
}
|
|
||||||
|
e2 = 2 * err;
|
||||||
|
if(e2 > -dy){
|
||||||
|
err = err - dy;
|
||||||
|
x0 = x0 + sx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e2 < dx){
|
||||||
|
err = err + dx;
|
||||||
|
y0 = y0 + sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Raycaster{
|
||||||
|
boolean accept(int x, int y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,60 +7,66 @@ import io.anuke.mindustry.io.MapTileData.TileDataMarker;
|
|||||||
import io.anuke.ucore.util.Bits;
|
import io.anuke.ucore.util.Bits;
|
||||||
|
|
||||||
public class DrawOperation{
|
public class DrawOperation{
|
||||||
/**Data to apply operation to.*/
|
/**
|
||||||
private MapTileData data;
|
* Data to apply operation to.
|
||||||
/**List of per-tile operations that occurred.*/
|
*/
|
||||||
private Array<TileOperation> operations = new Array<>();
|
private MapTileData data;
|
||||||
/**Checks for duplicate operations, useful for brushes.*/
|
/**
|
||||||
private IntSet checks = new IntSet();
|
* List of per-tile operations that occurred.
|
||||||
|
*/
|
||||||
|
private Array<TileOperation> operations = new Array<>();
|
||||||
|
/**
|
||||||
|
* Checks for duplicate operations, useful for brushes.
|
||||||
|
*/
|
||||||
|
private IntSet checks = new IntSet();
|
||||||
|
|
||||||
public DrawOperation(MapTileData data){
|
public DrawOperation(MapTileData data){
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty(){
|
public boolean isEmpty(){
|
||||||
return operations.size == 0;
|
return operations.size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkDuplicate(short x, short y){
|
public boolean checkDuplicate(short x, short y){
|
||||||
int i = Bits.packInt(x, y);
|
int i = Bits.packInt(x, y);
|
||||||
if(checks.contains(i)) return true;
|
if(checks.contains(i)) return true;
|
||||||
|
|
||||||
checks.add(i);
|
checks.add(i);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOperation(TileOperation op){
|
public void addOperation(TileOperation op){
|
||||||
operations.add(op);
|
operations.add(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undo(MapEditor editor) {
|
public void undo(MapEditor editor){
|
||||||
for(int i = operations.size - 1; i >= 0; i --){
|
for(int i = operations.size - 1; i >= 0; i--){
|
||||||
TileOperation op = operations.get(i);
|
TileOperation op = operations.get(i);
|
||||||
data.position(op.x, op.y);
|
data.position(op.x, op.y);
|
||||||
data.write(op.from);
|
data.write(op.from);
|
||||||
editor.renderer().updatePoint(op.x, op.y);
|
editor.renderer().updatePoint(op.x, op.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void redo(MapEditor editor) {
|
public void redo(MapEditor editor){
|
||||||
for(TileOperation op : operations){
|
for(TileOperation op : operations){
|
||||||
data.position(op.x, op.y);
|
data.position(op.x, op.y);
|
||||||
data.write(op.to);
|
data.write(op.to);
|
||||||
editor.renderer().updatePoint(op.x, op.y);
|
editor.renderer().updatePoint(op.x, op.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TileOperation{
|
public static class TileOperation{
|
||||||
public short x, y;
|
public short x, y;
|
||||||
public TileDataMarker from;
|
public TileDataMarker from;
|
||||||
public TileDataMarker to;
|
public TileDataMarker to;
|
||||||
|
|
||||||
public TileOperation(short x, short y, TileDataMarker from, TileDataMarker to) {
|
public TileOperation(short x, short y, TileDataMarker from, TileDataMarker to){
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.from = from;
|
this.from = from;
|
||||||
this.to = to;
|
this.to = to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,132 +12,132 @@ import io.anuke.ucore.util.Bits;
|
|||||||
import static io.anuke.mindustry.Vars.ui;
|
import static io.anuke.mindustry.Vars.ui;
|
||||||
|
|
||||||
public enum EditorTool{
|
public enum EditorTool{
|
||||||
pick{
|
pick{
|
||||||
public void touched(MapEditor editor, int x, int y){
|
public void touched(MapEditor editor, int x, int y){
|
||||||
byte bf = editor.getMap().read(x, y, DataPosition.floor);
|
byte bf = editor.getMap().read(x, y, DataPosition.floor);
|
||||||
byte bw = editor.getMap().read(x, y, DataPosition.wall);
|
byte bw = editor.getMap().read(x, y, DataPosition.wall);
|
||||||
byte link = editor.getMap().read(x, y, DataPosition.link);
|
byte link = editor.getMap().read(x, y, DataPosition.link);
|
||||||
|
|
||||||
if(link != 0){
|
if(link != 0){
|
||||||
x -= (Bits.getLeftByte(link) - 8);
|
x -= (Bits.getLeftByte(link) - 8);
|
||||||
y -= (Bits.getRightByte(link) - 8);
|
y -= (Bits.getRightByte(link) - 8);
|
||||||
bf = editor.getMap().read(x, y, DataPosition.floor);
|
bf = editor.getMap().read(x, y, DataPosition.floor);
|
||||||
bw = editor.getMap().read(x, y, DataPosition.wall);
|
bw = editor.getMap().read(x, y, DataPosition.wall);
|
||||||
}
|
}
|
||||||
|
|
||||||
Block block = Block.getByID(bw == 0 ? bf : bw);
|
Block block = Block.getByID(bw == 0 ? bf : bw);
|
||||||
editor.setDrawBlock(block);
|
editor.setDrawBlock(block);
|
||||||
ui.editor.updateSelectedBlock();
|
ui.editor.updateSelectedBlock();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pencil{
|
pencil{
|
||||||
{
|
{
|
||||||
edit = true;
|
edit = true;
|
||||||
draggable = true;
|
draggable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void touched(MapEditor editor, int x, int y){
|
public void touched(MapEditor editor, int x, int y){
|
||||||
editor.draw(x, y);
|
editor.draw(x, y);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
eraser{
|
eraser{
|
||||||
{
|
{
|
||||||
edit = true;
|
edit = true;
|
||||||
draggable = true;
|
draggable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void touched(MapEditor editor, int x, int y){
|
public void touched(MapEditor editor, int x, int y){
|
||||||
editor.draw(x, y, Blocks.air);
|
editor.draw(x, y, Blocks.air);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
elevation{
|
elevation{
|
||||||
{
|
{
|
||||||
edit = true;
|
edit = true;
|
||||||
draggable = true;
|
draggable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void touched(MapEditor editor, int x, int y){
|
public void touched(MapEditor editor, int x, int y){
|
||||||
editor.elevate(x, y);
|
editor.elevate(x, y);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
line{
|
line{
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fill{
|
fill{
|
||||||
{
|
{
|
||||||
edit = true;
|
edit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void touched(MapEditor editor, int x, int y){
|
|
||||||
if(editor.getDrawBlock().isMultiblock()){
|
|
||||||
//don't fill multiblocks, thanks
|
|
||||||
pencil.touched(editor, x, y);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean floor = editor.getDrawBlock() instanceof Floor;
|
public void touched(MapEditor editor, int x, int y){
|
||||||
|
if(editor.getDrawBlock().isMultiblock()){
|
||||||
|
//don't fill multiblocks, thanks
|
||||||
|
pencil.touched(editor, x, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
byte bf = editor.getMap().read(x, y, DataPosition.floor);
|
boolean floor = editor.getDrawBlock() instanceof Floor;
|
||||||
byte bw = editor.getMap().read(x, y, DataPosition.wall);
|
|
||||||
boolean synth = editor.getDrawBlock().synthetic();
|
|
||||||
byte brt = Bits.packByte((byte)editor.getDrawRotation(), (byte)editor.getDrawTeam().ordinal());
|
|
||||||
|
|
||||||
byte dest = floor ? bf: bw;
|
byte bf = editor.getMap().read(x, y, DataPosition.floor);
|
||||||
byte draw = (byte)editor.getDrawBlock().id;
|
byte bw = editor.getMap().read(x, y, DataPosition.wall);
|
||||||
|
boolean synth = editor.getDrawBlock().synthetic();
|
||||||
|
byte brt = Bits.packByte((byte) editor.getDrawRotation(), (byte) editor.getDrawTeam().ordinal());
|
||||||
|
|
||||||
int width = editor.getMap().width();
|
byte dest = floor ? bf : bw;
|
||||||
int height = editor.getMap().height();
|
byte draw = (byte) editor.getDrawBlock().id;
|
||||||
|
|
||||||
IntSet set = new IntSet();
|
int width = editor.getMap().width();
|
||||||
IntArray points = new IntArray();
|
int height = editor.getMap().height();
|
||||||
points.add(asInt(x, y, editor.getMap().width()));
|
|
||||||
|
|
||||||
while(points.size != 0){
|
IntSet set = new IntSet();
|
||||||
int pos = points.pop();
|
IntArray points = new IntArray();
|
||||||
int px = pos % width;
|
points.add(asInt(x, y, editor.getMap().width()));
|
||||||
int py = pos / width;
|
|
||||||
set.add(pos);
|
|
||||||
|
|
||||||
byte nbf = editor.getMap().read(px, py, DataPosition.floor);
|
while(points.size != 0){
|
||||||
byte nbw = editor.getMap().read(px, py, DataPosition.wall);
|
int pos = points.pop();
|
||||||
|
int px = pos % width;
|
||||||
|
int py = pos / width;
|
||||||
|
set.add(pos);
|
||||||
|
|
||||||
if((floor ? nbf : nbw) == dest){
|
byte nbf = editor.getMap().read(px, py, DataPosition.floor);
|
||||||
TileDataMarker prev = editor.getPrev(px, py, false);
|
byte nbw = editor.getMap().read(px, py, DataPosition.wall);
|
||||||
|
|
||||||
if(floor) {
|
if((floor ? nbf : nbw) == dest){
|
||||||
editor.getMap().write(px, py, DataPosition.floor, draw);
|
TileDataMarker prev = editor.getPrev(px, py, false);
|
||||||
}else {
|
|
||||||
editor.getMap().write(px, py, DataPosition.wall, draw);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(synth){
|
if(floor){
|
||||||
editor.getMap().write(px, py, DataPosition.rotationTeam, brt);
|
editor.getMap().write(px, py, DataPosition.floor, draw);
|
||||||
}
|
}else{
|
||||||
|
editor.getMap().write(px, py, DataPosition.wall, draw);
|
||||||
|
}
|
||||||
|
|
||||||
if(px > 0 && !set.contains(asInt(px - 1, py, width))) points.add(asInt(px - 1, py, width));
|
if(synth){
|
||||||
if(py > 0 && !set.contains(asInt(px, py - 1, width))) points.add(asInt(px, py - 1, width));
|
editor.getMap().write(px, py, DataPosition.rotationTeam, brt);
|
||||||
if(px < width - 1 && !set.contains(asInt(px + 1, py, width))) points.add(asInt(px + 1, py, width));
|
}
|
||||||
if(py < height - 1 && !set.contains(asInt(px, py + 1, width))) points.add(asInt(px, py + 1, width));
|
|
||||||
|
|
||||||
editor.onWrite(px, py, prev);
|
if(px > 0 && !set.contains(asInt(px - 1, py, width))) points.add(asInt(px - 1, py, width));
|
||||||
}
|
if(py > 0 && !set.contains(asInt(px, py - 1, width))) points.add(asInt(px, py - 1, width));
|
||||||
}
|
if(px < width - 1 && !set.contains(asInt(px + 1, py, width))) points.add(asInt(px + 1, py, width));
|
||||||
}
|
if(py < height - 1 && !set.contains(asInt(px, py + 1, width))) points.add(asInt(px, py + 1, width));
|
||||||
|
|
||||||
int asInt(int x, int y, int width){
|
|
||||||
return x+y*width;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
zoom;
|
|
||||||
|
|
||||||
boolean edit, draggable;
|
editor.onWrite(px, py, prev);
|
||||||
|
}
|
||||||
public void touched(MapEditor editor, int x, int y){
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
int asInt(int x, int y, int width){
|
||||||
|
return x + y * width;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
zoom;
|
||||||
|
|
||||||
|
boolean edit, draggable;
|
||||||
|
|
||||||
|
public void touched(MapEditor editor, int x, int y){
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,267 +14,267 @@ import io.anuke.ucore.util.Bits;
|
|||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class MapEditor{
|
public class MapEditor{
|
||||||
public static final int minMapSize = 128, maxMapSize = 512;
|
public static final int minMapSize = 128, maxMapSize = 512;
|
||||||
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15};
|
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15};
|
||||||
|
|
||||||
private MapTileData map;
|
|
||||||
private ObjectMap<String, String> tags = new ObjectMap<>();
|
|
||||||
private MapRenderer renderer = new MapRenderer(this);
|
|
||||||
|
|
||||||
private int brushSize = 1;
|
private MapTileData map;
|
||||||
private byte elevation;
|
private ObjectMap<String, String> tags = new ObjectMap<>();
|
||||||
private int rotation;
|
private MapRenderer renderer = new MapRenderer(this);
|
||||||
private Block drawBlock = Blocks.stone;
|
|
||||||
private Team drawTeam = Team.none;
|
|
||||||
|
|
||||||
public MapEditor(){
|
|
||||||
|
|
||||||
}
|
private int brushSize = 1;
|
||||||
|
private byte elevation;
|
||||||
public MapTileData getMap(){
|
private int rotation;
|
||||||
return map;
|
private Block drawBlock = Blocks.stone;
|
||||||
}
|
private Team drawTeam = Team.none;
|
||||||
|
|
||||||
public ObjectMap<String, String> getTags() {
|
public MapEditor(){
|
||||||
return tags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void beginEdit(MapTileData map, ObjectMap<String, String> tags, boolean clear){
|
}
|
||||||
this.map = map;
|
|
||||||
this.brushSize = 1;
|
|
||||||
this.tags = tags;
|
|
||||||
|
|
||||||
if(clear) {
|
public MapTileData getMap(){
|
||||||
for (int x = 0; x < map.width(); x++) {
|
return map;
|
||||||
for (int y = 0; y < map.height(); y++) {
|
}
|
||||||
map.write(x, y, DataPosition.floor, (byte) Blocks.stone.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drawBlock = Blocks.stone;
|
public ObjectMap<String, String> getTags(){
|
||||||
renderer.resize(map.width(), map.height());
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDrawElevation(int elevation){
|
public void beginEdit(MapTileData map, ObjectMap<String, String> tags, boolean clear){
|
||||||
this.elevation = (byte)elevation;
|
this.map = map;
|
||||||
}
|
this.brushSize = 1;
|
||||||
|
this.tags = tags;
|
||||||
|
|
||||||
public byte getDrawElevation(){
|
if(clear){
|
||||||
return elevation;
|
for(int x = 0; x < map.width(); x++){
|
||||||
}
|
for(int y = 0; y < map.height(); y++){
|
||||||
|
map.write(x, y, DataPosition.floor, (byte) Blocks.stone.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getDrawRotation(){
|
drawBlock = Blocks.stone;
|
||||||
return rotation;
|
renderer.resize(map.width(), map.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDrawRotation(int rotation){
|
public byte getDrawElevation(){
|
||||||
this.rotation = rotation;
|
return elevation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDrawTeam(Team team){
|
public void setDrawElevation(int elevation){
|
||||||
this.drawTeam = team;
|
this.elevation = (byte) elevation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Team getDrawTeam() {
|
public int getDrawRotation(){
|
||||||
return drawTeam;
|
return rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block getDrawBlock(){
|
public void setDrawRotation(int rotation){
|
||||||
return drawBlock;
|
this.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDrawBlock(Block block){
|
|
||||||
this.drawBlock = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBrushSize(int size){
|
|
||||||
this.brushSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBrushSize() {
|
public Team getDrawTeam(){
|
||||||
return brushSize;
|
return drawTeam;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw(int x, int y){
|
public void setDrawTeam(Team team){
|
||||||
draw(x, y, drawBlock);
|
this.drawTeam = team;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void draw(int x, int y, Block drawBlock){
|
public Block getDrawBlock(){
|
||||||
if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){
|
return drawBlock;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
byte writeID = (byte)drawBlock.id;
|
public void setDrawBlock(Block block){
|
||||||
byte partID = (byte)Blocks.blockpart.id;
|
this.drawBlock = block;
|
||||||
byte rotationTeam = Bits.packByte(drawBlock.rotate ? (byte)rotation : 0, drawBlock.synthetic() ? (byte)drawTeam.ordinal() : 0);
|
}
|
||||||
|
|
||||||
boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air;
|
public int getBrushSize(){
|
||||||
|
return brushSize;
|
||||||
|
}
|
||||||
|
|
||||||
if(drawBlock.isMultiblock()) {
|
public void setBrushSize(int size){
|
||||||
|
this.brushSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
int offsetx = -(drawBlock.size - 1) / 2;
|
public void draw(int x, int y){
|
||||||
int offsety = -(drawBlock.size - 1) / 2;
|
draw(x, y, drawBlock);
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 2; i ++){
|
public void draw(int x, int y, Block drawBlock){
|
||||||
for (int dx = 0; dx < drawBlock.size; dx++) {
|
if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){
|
||||||
for (int dy = 0; dy < drawBlock.size; dy++) {
|
return;
|
||||||
int worldx = dx + offsetx + x;
|
}
|
||||||
int worldy = dy + offsety + y;
|
|
||||||
|
|
||||||
if (Mathf.inBounds(worldx, worldy, map.width(), map.height())) {
|
byte writeID = (byte) drawBlock.id;
|
||||||
TileDataMarker prev = getPrev(worldx, worldy, false);
|
byte partID = (byte) Blocks.blockpart.id;
|
||||||
|
byte rotationTeam = Bits.packByte(drawBlock.rotate ? (byte) rotation : 0, drawBlock.synthetic() ? (byte) drawTeam.ordinal() : 0);
|
||||||
|
|
||||||
if(i == 1) {
|
boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air;
|
||||||
map.write(worldx, worldy, DataPosition.wall, partID);
|
|
||||||
map.write(worldx, worldy, DataPosition.rotationTeam, rotationTeam);
|
|
||||||
map.write(worldx, worldy, DataPosition.link, Bits.packByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8)));
|
|
||||||
}else{
|
|
||||||
byte link = map.read(worldx, worldy, DataPosition.link);
|
|
||||||
byte block = map.read(worldx, worldy, DataPosition.wall);
|
|
||||||
|
|
||||||
if (link != 0) {
|
if(drawBlock.isMultiblock()){
|
||||||
removeLinked(worldx - (Bits.getLeftByte(link) - 8), worldy - (Bits.getRightByte(link) - 8));
|
|
||||||
}else if(Block.getByID(block).isMultiblock()){
|
|
||||||
removeLinked(worldx, worldy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onWrite(worldx, worldy, prev);
|
int offsetx = -(drawBlock.size - 1) / 2;
|
||||||
}
|
int offsety = -(drawBlock.size - 1) / 2;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TileDataMarker prev = getPrev(x, y, false);
|
for(int i = 0; i < 2; i++){
|
||||||
|
for(int dx = 0; dx < drawBlock.size; dx++){
|
||||||
|
for(int dy = 0; dy < drawBlock.size; dy++){
|
||||||
|
int worldx = dx + offsetx + x;
|
||||||
|
int worldy = dy + offsety + y;
|
||||||
|
|
||||||
map.write(x, y, DataPosition.wall, writeID);
|
if(Mathf.inBounds(worldx, worldy, map.width(), map.height())){
|
||||||
map.write(x, y, DataPosition.link, (byte)0);
|
TileDataMarker prev = getPrev(worldx, worldy, false);
|
||||||
map.write(x, y, DataPosition.rotationTeam, rotationTeam);
|
|
||||||
|
|
||||||
onWrite(x, y, prev);
|
if(i == 1){
|
||||||
}else{
|
map.write(worldx, worldy, DataPosition.wall, partID);
|
||||||
|
map.write(worldx, worldy, DataPosition.rotationTeam, rotationTeam);
|
||||||
|
map.write(worldx, worldy, DataPosition.link, Bits.packByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8)));
|
||||||
|
}else{
|
||||||
|
byte link = map.read(worldx, worldy, DataPosition.link);
|
||||||
|
byte block = map.read(worldx, worldy, DataPosition.wall);
|
||||||
|
|
||||||
for (int rx = -brushSize; rx <= brushSize; rx++) {
|
if(link != 0){
|
||||||
for (int ry = -brushSize; ry <= brushSize; ry++) {
|
removeLinked(worldx - (Bits.getLeftByte(link) - 8), worldy - (Bits.getRightByte(link) - 8));
|
||||||
if (Mathf.dst(rx, ry) <= brushSize - 0.5f) {
|
}else if(Block.getByID(block).isMultiblock()){
|
||||||
int wx = x + rx, wy = y + ry;
|
removeLinked(worldx, worldy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height()) {
|
onWrite(worldx, worldy, prev);
|
||||||
continue;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TileDataMarker prev = getPrev(wx, wy, true);
|
TileDataMarker prev = getPrev(x, y, false);
|
||||||
|
|
||||||
if(!isfloor) {
|
map.write(x, y, DataPosition.wall, writeID);
|
||||||
byte link = map.read(wx, wy, DataPosition.link);
|
map.write(x, y, DataPosition.link, (byte) 0);
|
||||||
|
map.write(x, y, DataPosition.rotationTeam, rotationTeam);
|
||||||
|
|
||||||
if (link != 0) {
|
onWrite(x, y, prev);
|
||||||
removeLinked(wx - (Bits.getLeftByte(link) - 8), wy - (Bits.getRightByte(link) - 8));
|
}else{
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isfloor){
|
for(int rx = -brushSize; rx <= brushSize; rx++){
|
||||||
map.write(wx, wy, DataPosition.floor, writeID);
|
for(int ry = -brushSize; ry <= brushSize; ry++){
|
||||||
map.write(wx, wy, DataPosition.elevation, elevation);
|
if(Mathf.dst(rx, ry) <= brushSize - 0.5f){
|
||||||
}else{
|
int wx = x + rx, wy = y + ry;
|
||||||
map.write(wx, wy, DataPosition.wall, writeID);
|
|
||||||
map.write(wx, wy, DataPosition.link, (byte)0);
|
|
||||||
map.write(wx, wy, DataPosition.rotationTeam, rotationTeam);
|
|
||||||
}
|
|
||||||
|
|
||||||
onWrite(x + rx, y + ry, prev);
|
if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height()){
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void elevate(int x, int y){
|
TileDataMarker prev = getPrev(wx, wy, true);
|
||||||
if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int rx = -brushSize; rx <= brushSize; rx++) {
|
if(!isfloor){
|
||||||
for (int ry = -brushSize; ry <= brushSize; ry++) {
|
byte link = map.read(wx, wy, DataPosition.link);
|
||||||
if (Mathf.dst(rx, ry) <= brushSize - 0.5f) {
|
|
||||||
int wx = x + rx, wy = y + ry;
|
|
||||||
|
|
||||||
if (wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height()) {
|
if(link != 0){
|
||||||
continue;
|
removeLinked(wx - (Bits.getLeftByte(link) - 8), wy - (Bits.getRightByte(link) - 8));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TileDataMarker prev = getPrev(wx, wy, true);
|
if(isfloor){
|
||||||
|
map.write(wx, wy, DataPosition.floor, writeID);
|
||||||
|
map.write(wx, wy, DataPosition.elevation, elevation);
|
||||||
|
}else{
|
||||||
|
map.write(wx, wy, DataPosition.wall, writeID);
|
||||||
|
map.write(wx, wy, DataPosition.link, (byte) 0);
|
||||||
|
map.write(wx, wy, DataPosition.rotationTeam, rotationTeam);
|
||||||
|
}
|
||||||
|
|
||||||
map.write(wx, wy, DataPosition.elevation, elevation);
|
onWrite(x + rx, y + ry, prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onWrite(x + rx, y + ry, prev);
|
public void elevate(int x, int y){
|
||||||
}
|
if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void removeLinked(int x, int y){
|
for(int rx = -brushSize; rx <= brushSize; rx++){
|
||||||
Block block = Block.getByID(map.read(x, y, DataPosition.wall));
|
for(int ry = -brushSize; ry <= brushSize; ry++){
|
||||||
|
if(Mathf.dst(rx, ry) <= brushSize - 0.5f){
|
||||||
|
int wx = x + rx, wy = y + ry;
|
||||||
|
|
||||||
int offsetx = -(block.size-1)/2;
|
if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height()){
|
||||||
int offsety = -(block.size-1)/2;
|
continue;
|
||||||
for(int dx = 0; dx < block.size; dx ++){
|
}
|
||||||
for(int dy = 0; dy < block.size; dy ++){
|
|
||||||
int worldx = x + dx + offsetx, worldy = y + dy + offsety;
|
|
||||||
if(Mathf.inBounds(worldx, worldy, map.width(), map.height())){
|
|
||||||
TileDataMarker prev = getPrev(worldx, worldy, false);
|
|
||||||
|
|
||||||
map.write(worldx, worldy, DataPosition.link, (byte)0);
|
TileDataMarker prev = getPrev(wx, wy, true);
|
||||||
map.write(worldx, worldy, DataPosition.rotationTeam, (byte)0);
|
|
||||||
map.write(worldx, worldy, DataPosition.wall, (byte)0);
|
|
||||||
|
|
||||||
onWrite(worldx, worldy, prev);
|
map.write(wx, wy, DataPosition.elevation, elevation);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean checkDupes(int x, int y){
|
onWrite(x + rx, y + ry, prev);
|
||||||
return Vars.ui.editor.getView().checkForDuplicates((short) x, (short) y);
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onWrite(int x, int y, TileDataMarker previous){
|
private void removeLinked(int x, int y){
|
||||||
if(previous == null){
|
Block block = Block.getByID(map.read(x, y, DataPosition.wall));
|
||||||
renderer.updatePoint(x, y);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TileDataMarker current = map.new TileDataMarker();
|
int offsetx = -(block.size - 1) / 2;
|
||||||
map.position(x, y);
|
int offsety = -(block.size - 1) / 2;
|
||||||
map.read(current);
|
for(int dx = 0; dx < block.size; dx++){
|
||||||
|
for(int dy = 0; dy < block.size; dy++){
|
||||||
|
int worldx = x + dx + offsetx, worldy = y + dy + offsety;
|
||||||
|
if(Mathf.inBounds(worldx, worldy, map.width(), map.height())){
|
||||||
|
TileDataMarker prev = getPrev(worldx, worldy, false);
|
||||||
|
|
||||||
Vars.ui.editor.getView().addTileOp(new TileOperation((short) x, (short) y, previous, current));
|
map.write(worldx, worldy, DataPosition.link, (byte) 0);
|
||||||
renderer.updatePoint(x, y);
|
map.write(worldx, worldy, DataPosition.rotationTeam, (byte) 0);
|
||||||
}
|
map.write(worldx, worldy, DataPosition.wall, (byte) 0);
|
||||||
|
|
||||||
TileDataMarker getPrev(int x, int y, boolean checkDupes){
|
onWrite(worldx, worldy, prev);
|
||||||
if(checkDupes && checkDupes(x, y)){
|
}
|
||||||
return null;
|
}
|
||||||
}else{
|
}
|
||||||
TileDataMarker marker = map.newDataMarker();
|
}
|
||||||
map.position(x, y);
|
|
||||||
map.read(marker);
|
|
||||||
return marker;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public MapRenderer renderer() {
|
boolean checkDupes(int x, int y){
|
||||||
return renderer;
|
return Vars.ui.editor.getView().checkForDuplicates((short) x, (short) y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resize(int width, int height){
|
void onWrite(int x, int y, TileDataMarker previous){
|
||||||
map = new MapTileData(width, height);
|
if(previous == null){
|
||||||
for (int x = 0; x < map.width(); x++) {
|
renderer.updatePoint(x, y);
|
||||||
for (int y = 0; y < map.height(); y++) {
|
return;
|
||||||
map.write(x, y, DataPosition.floor, (byte)Blocks.stone.id);
|
}
|
||||||
}
|
|
||||||
}
|
TileDataMarker current = map.new TileDataMarker();
|
||||||
renderer.resize(width, height);
|
map.position(x, y);
|
||||||
}
|
map.read(current);
|
||||||
|
|
||||||
|
Vars.ui.editor.getView().addTileOp(new TileOperation((short) x, (short) y, previous, current));
|
||||||
|
renderer.updatePoint(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
TileDataMarker getPrev(int x, int y, boolean checkDupes){
|
||||||
|
if(checkDupes && checkDupes(x, y)){
|
||||||
|
return null;
|
||||||
|
}else{
|
||||||
|
TileDataMarker marker = map.newDataMarker();
|
||||||
|
map.position(x, y);
|
||||||
|
map.read(marker);
|
||||||
|
return marker;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MapRenderer renderer(){
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resize(int width, int height){
|
||||||
|
map = new MapTileData(width, height);
|
||||||
|
for(int x = 0; x < map.width(); x++){
|
||||||
|
for(int y = 0; y < map.height(); y++){
|
||||||
|
map.write(x, y, DataPosition.floor, (byte) Blocks.stone.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
renderer.resize(width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,68 +14,68 @@ import io.anuke.ucore.scene.ui.layout.Table;
|
|||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class MapLoadDialog extends FloatingDialog{
|
public class MapLoadDialog extends FloatingDialog{
|
||||||
private Map selected = null;
|
private Map selected = null;
|
||||||
|
|
||||||
public MapLoadDialog(Consumer<Map> loader) {
|
public MapLoadDialog(Consumer<Map> loader){
|
||||||
super("$text.editor.loadmap");
|
super("$text.editor.loadmap");
|
||||||
|
|
||||||
shown(this::rebuild);
|
shown(this::rebuild);
|
||||||
rebuild();
|
rebuild();
|
||||||
|
|
||||||
TextButton button = new TextButton("$text.load");
|
TextButton button = new TextButton("$text.load");
|
||||||
button.setDisabled(() -> selected == null);
|
button.setDisabled(() -> selected == null);
|
||||||
button.clicked(() -> {
|
button.clicked(() -> {
|
||||||
if (selected != null) {
|
if(selected != null){
|
||||||
loader.accept(selected);
|
loader.accept(selected);
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
buttons().defaults().size(200f, 50f);
|
buttons().defaults().size(200f, 50f);
|
||||||
buttons().addButton("$text.cancel", this::hide);
|
buttons().addButton("$text.cancel", this::hide);
|
||||||
buttons().add(button);
|
buttons().add(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rebuild(){
|
public void rebuild(){
|
||||||
content().clear();
|
content().clear();
|
||||||
if(world.maps().all().size > 0){
|
if(world.maps().all().size > 0){
|
||||||
selected = world.maps().all().first();
|
selected = world.maps().all().first();
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
||||||
|
|
||||||
int maxcol = 3;
|
int maxcol = 3;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
Table table = new Table();
|
Table table = new Table();
|
||||||
table.defaults().size(200f, 90f).pad(4f);
|
table.defaults().size(200f, 90f).pad(4f);
|
||||||
table.margin(10f);
|
table.margin(10f);
|
||||||
|
|
||||||
ScrollPane pane = new ScrollPane(table, "horizontal");
|
ScrollPane pane = new ScrollPane(table, "horizontal");
|
||||||
pane.setFadeScrollBars(false);
|
pane.setFadeScrollBars(false);
|
||||||
|
|
||||||
for (Map map : world.maps().all()) {
|
for(Map map : world.maps().all()){
|
||||||
|
|
||||||
TextButton button = new TextButton(map.getDisplayName(), "toggle");
|
TextButton button = new TextButton(map.getDisplayName(), "toggle");
|
||||||
button.add(new BorderImage(map.texture, 2f)).size(16 * 4f);
|
button.add(new BorderImage(map.texture, 2f)).size(16 * 4f);
|
||||||
button.getCells().reverse();
|
button.getCells().reverse();
|
||||||
button.clicked(() -> selected = map);
|
button.clicked(() -> selected = map);
|
||||||
button.getLabelCell().grow().left().padLeft(5f);
|
button.getLabelCell().grow().left().padLeft(5f);
|
||||||
group.add(button);
|
group.add(button);
|
||||||
table.add(button);
|
table.add(button);
|
||||||
if (++i % maxcol == 0) table.row();
|
if(++i % maxcol == 0) table.row();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(world.maps().all().size == 0){
|
if(world.maps().all().size == 0){
|
||||||
pane.setStyle(Core.skin.get("clear", ScrollPaneStyle.class));
|
pane.setStyle(Core.skin.get("clear", ScrollPaneStyle.class));
|
||||||
table.add("$text.maps.none").center();
|
table.add("$text.maps.none").center();
|
||||||
}else {
|
}else{
|
||||||
content().add("$text.editor.loadmap");
|
content().add("$text.editor.loadmap");
|
||||||
}
|
}
|
||||||
|
|
||||||
content().row();
|
content().row();
|
||||||
content().add(pane);
|
content().add(pane);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,18 +34,18 @@ public class MapRenderer implements Disposable{
|
|||||||
|
|
||||||
public void resize(int width, int height){
|
public void resize(int width, int height){
|
||||||
if(chunks != null){
|
if(chunks != null){
|
||||||
for(int x = 0; x < chunks.length; x ++){
|
for(int x = 0; x < chunks.length; x++){
|
||||||
for(int y = 0; y < chunks[0].length; y ++){
|
for(int y = 0; y < chunks[0].length; y++){
|
||||||
chunks[x][y].dispose();
|
chunks[x][y].dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunks = new IndexedRenderer[(int)Math.ceil((float)width/chunksize)][(int)Math.ceil((float)height/chunksize )];
|
chunks = new IndexedRenderer[(int) Math.ceil((float) width / chunksize)][(int) Math.ceil((float) height / chunksize)];
|
||||||
|
|
||||||
for(int x = 0; x < chunks.length; x ++){
|
for(int x = 0; x < chunks.length; x++){
|
||||||
for(int y = 0; y < chunks[0].length; y ++){
|
for(int y = 0; y < chunks[0].length; y++){
|
||||||
chunks[x][y] = new IndexedRenderer(chunksize*chunksize*2);
|
chunks[x][y] = new IndexedRenderer(chunksize * chunksize * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.width = width;
|
this.width = width;
|
||||||
@@ -69,8 +69,8 @@ public class MapRenderer implements Disposable{
|
|||||||
updates.addAll(delayedUpdates);
|
updates.addAll(delayedUpdates);
|
||||||
delayedUpdates.clear();
|
delayedUpdates.clear();
|
||||||
|
|
||||||
for(int x = 0; x < chunks.length; x ++){
|
for(int x = 0; x < chunks.length; x++){
|
||||||
for(int y = 0; y < chunks[0].length; y ++){
|
for(int y = 0; y < chunks[0].length; y++){
|
||||||
IndexedRenderer mesh = chunks[x][y];
|
IndexedRenderer mesh = chunks[x][y];
|
||||||
|
|
||||||
mesh.getTransformMatrix().setToTranslation(tx, ty, 0).scl(tw / (width * tilesize),
|
mesh.getTransformMatrix().setToTranslation(tx, ty, 0).scl(tw / (width * tilesize),
|
||||||
@@ -86,19 +86,19 @@ public class MapRenderer implements Disposable{
|
|||||||
|
|
||||||
public void updatePoint(int x, int y){
|
public void updatePoint(int x, int y){
|
||||||
//TODO spread out over multiple frames?
|
//TODO spread out over multiple frames?
|
||||||
updates.add(x + y*width);
|
updates.add(x + y * width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAll(){
|
public void updateAll(){
|
||||||
for(int x = 0; x < width; x ++){
|
for(int x = 0; x < width; x++){
|
||||||
for(int y = 0; y < height; y ++){
|
for(int y = 0; y < height; y++){
|
||||||
render(x, y);
|
render(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void render(int wx, int wy){
|
private void render(int wx, int wy){
|
||||||
int x = wx/chunksize, y = wy/chunksize;
|
int x = wx / chunksize, y = wy / chunksize;
|
||||||
IndexedRenderer mesh = chunks[x][y];
|
IndexedRenderer mesh = chunks[x][y];
|
||||||
//TileDataMarker data = editor.getMap().readAt(wx, wy);
|
//TileDataMarker data = editor.getMap().readAt(wx, wy);
|
||||||
byte bf = editor.getMap().read(wx, wy, DataPosition.floor);
|
byte bf = editor.getMap().read(wx, wy, DataPosition.floor);
|
||||||
@@ -111,19 +111,19 @@ public class MapRenderer implements Disposable{
|
|||||||
Block floor = Block.getByID(bf);
|
Block floor = Block.getByID(bf);
|
||||||
Block wall = Block.getByID(bw);
|
Block wall = Block.getByID(bw);
|
||||||
|
|
||||||
int offsetx = -(wall.size-1)/2;
|
int offsetx = -(wall.size - 1) / 2;
|
||||||
int offsety = -(wall.size-1)/2;
|
int offsety = -(wall.size - 1) / 2;
|
||||||
|
|
||||||
TextureRegion region;
|
TextureRegion region;
|
||||||
|
|
||||||
if(bw != 0) {
|
if(bw != 0){
|
||||||
region = wall.getEditorIcon();
|
region = wall.getEditorIcon();
|
||||||
|
|
||||||
if (wall.rotate) {
|
if(wall.rotate){
|
||||||
mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize, region,
|
mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize, region,
|
||||||
wx * tilesize + offsetx * tilesize, wy * tilesize + offsety * tilesize,
|
wx * tilesize + offsetx * tilesize, wy * tilesize + offsety * tilesize,
|
||||||
region.getRegionWidth(), region.getRegionHeight(), rotation * 90 - 90);
|
region.getRegionWidth(), region.getRegionHeight(), rotation * 90 - 90);
|
||||||
} else {
|
}else{
|
||||||
mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize, region,
|
mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize, region,
|
||||||
wx * tilesize + offsetx * tilesize, wy * tilesize + offsety * tilesize,
|
wx * tilesize + offsetx * tilesize, wy * tilesize + offsety * tilesize,
|
||||||
region.getRegionWidth(), region.getRegionHeight());
|
region.getRegionWidth(), region.getRegionHeight());
|
||||||
@@ -131,16 +131,16 @@ public class MapRenderer implements Disposable{
|
|||||||
}else{
|
}else{
|
||||||
region = floor.getEditorIcon();
|
region = floor.getEditorIcon();
|
||||||
|
|
||||||
mesh.draw((wx % chunksize) + (wy % chunksize)*chunksize, region, wx * tilesize, wy * tilesize, 8, 8);
|
mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize, region, wx * tilesize, wy * tilesize, 8, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean check = checkElevation(elev, wx, wy);
|
boolean check = checkElevation(elev, wx, wy);
|
||||||
|
|
||||||
if(wall.update || wall.destructible) {
|
if(wall.update || wall.destructible){
|
||||||
mesh.setColor(team.color);
|
mesh.setColor(team.color);
|
||||||
region = Draw.region("block-border");
|
region = Draw.region("block-border");
|
||||||
}else if(elev > 0 && check){
|
}else if(elev > 0 && check){
|
||||||
mesh.setColor(tmpColor.fromHsv((360f * elev/127f * 4f) % 360f, 0.5f + (elev / 4f) % 0.5f, 1f));
|
mesh.setColor(tmpColor.fromHsv((360f * elev / 127f * 4f) % 360f, 0.5f + (elev / 4f) % 0.5f, 1f));
|
||||||
region = Draw.region("block-elevation");
|
region = Draw.region("block-elevation");
|
||||||
}else if(elev == -1){
|
}else if(elev == -1){
|
||||||
region = Draw.region("block-slope");
|
region = Draw.region("block-slope");
|
||||||
@@ -148,8 +148,8 @@ public class MapRenderer implements Disposable{
|
|||||||
region = Draw.region("clear");
|
region = Draw.region("clear");
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.draw((wx % chunksize) + (wy % chunksize)*chunksize + chunksize*chunksize, region,
|
mesh.draw((wx % chunksize) + (wy % chunksize) * chunksize + chunksize * chunksize, region,
|
||||||
wx * tilesize + offsetx*tilesize, wy * tilesize + offsety * tilesize,
|
wx * tilesize + offsetx * tilesize, wy * tilesize + offsety * tilesize,
|
||||||
region.getRegionWidth(), region.getRegionHeight());
|
region.getRegionWidth(), region.getRegionHeight());
|
||||||
mesh.setColor(Color.WHITE);
|
mesh.setColor(Color.WHITE);
|
||||||
}
|
}
|
||||||
@@ -165,19 +165,19 @@ public class MapRenderer implements Disposable{
|
|||||||
if(value < elev){
|
if(value < elev){
|
||||||
return true;
|
return true;
|
||||||
}else if(value > elev){
|
}else if(value > elev){
|
||||||
delayedUpdates.add(wx + wy*width);
|
delayedUpdates.add(wx + wy * width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose(){
|
||||||
if(chunks == null){
|
if(chunks == null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(int x = 0; x < chunks.length; x ++){
|
for(int x = 0; x < chunks.length; x++){
|
||||||
for(int y = 0; y < chunks[0].length; y ++){
|
for(int y = 0; y < chunks[0].length; y++){
|
||||||
if(chunks[x][y] != null){
|
if(chunks[x][y] != null){
|
||||||
chunks[x][y].dispose();
|
chunks[x][y].dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,55 +9,55 @@ import io.anuke.ucore.scene.ui.layout.Table;
|
|||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class MapResizeDialog extends FloatingDialog{
|
public class MapResizeDialog extends FloatingDialog{
|
||||||
int[] validMapSizes = {200, 300, 400, 500};
|
int[] validMapSizes = {200, 300, 400, 500};
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
public MapResizeDialog(MapEditor editor, BiConsumer<Integer, Integer> cons){
|
public MapResizeDialog(MapEditor editor, BiConsumer<Integer, Integer> cons){
|
||||||
super("$text.editor.resizemap");
|
super("$text.editor.resizemap");
|
||||||
shown(() -> {
|
shown(() -> {
|
||||||
content().clear();
|
content().clear();
|
||||||
MapTileData data = editor.getMap();
|
MapTileData data = editor.getMap();
|
||||||
width = data.width();
|
width = data.width();
|
||||||
height = data.height();
|
height = data.height();
|
||||||
|
|
||||||
Table table = new Table();
|
Table table = new Table();
|
||||||
|
|
||||||
for(boolean w : Mathf.booleans){
|
for(boolean w : Mathf.booleans){
|
||||||
int curr = w ? data.width() : data.height();
|
int curr = w ? data.width() : data.height();
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for(int i = 0; i < validMapSizes.length; i ++) {
|
for(int i = 0; i < validMapSizes.length; i++){
|
||||||
if (validMapSizes[i] == curr) idx = i;
|
if(validMapSizes[i] == curr) idx = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.add(w ? "$text.width": "$text.height").padRight(8f);
|
table.add(w ? "$text.width" : "$text.height").padRight(8f);
|
||||||
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
||||||
for(int i = 0; i < validMapSizes.length; i ++){
|
for(int i = 0; i < validMapSizes.length; i++){
|
||||||
int size = validMapSizes[i];
|
int size = validMapSizes[i];
|
||||||
TextButton button = new TextButton(size + "", "toggle");
|
TextButton button = new TextButton(size + "", "toggle");
|
||||||
button.clicked(() -> {
|
button.clicked(() -> {
|
||||||
if(w)
|
if(w)
|
||||||
width = size;
|
width = size;
|
||||||
else
|
else
|
||||||
height = size;
|
height = size;
|
||||||
});
|
});
|
||||||
group.add(button);
|
group.add(button);
|
||||||
if(i == idx) button.setChecked(true);
|
if(i == idx) button.setChecked(true);
|
||||||
table.add(button).size(100f, 54f).pad(2f);
|
table.add(button).size(100f, 54f).pad(2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
table.row();
|
table.row();
|
||||||
}
|
}
|
||||||
content().row();
|
content().row();
|
||||||
content().add(table);
|
content().add(table);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
buttons().defaults().size(200f, 50f);
|
buttons().defaults().size(200f, 50f);
|
||||||
buttons().addButton("$text.cancel", this::hide);
|
buttons().addButton("$text.cancel", this::hide);
|
||||||
buttons().addButton("$text.editor.resize", () -> {
|
buttons().addButton("$text.editor.resize", () -> {
|
||||||
cons.accept(width, height);
|
cons.accept(width, height);
|
||||||
hide();
|
hide();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package io.anuke.mindustry.editor;
|
package io.anuke.mindustry.editor;
|
||||||
|
|
||||||
import io.anuke.mindustry.io.Map;
|
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
|
import io.anuke.mindustry.io.Map;
|
||||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||||
import io.anuke.ucore.function.Consumer;
|
import io.anuke.ucore.function.Consumer;
|
||||||
import io.anuke.ucore.scene.ui.TextButton;
|
import io.anuke.ucore.scene.ui.TextButton;
|
||||||
@@ -11,65 +11,65 @@ import static io.anuke.mindustry.Vars.ui;
|
|||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class MapSaveDialog extends FloatingDialog{
|
public class MapSaveDialog extends FloatingDialog{
|
||||||
private TextField field;
|
private TextField field;
|
||||||
private Consumer<String> listener;
|
private Consumer<String> listener;
|
||||||
|
|
||||||
public MapSaveDialog(Consumer<String> cons){
|
|
||||||
super("$text.editor.savemap");
|
|
||||||
field = new TextField();
|
|
||||||
listener = cons;
|
|
||||||
|
|
||||||
Platform.instance.addDialog(field);
|
|
||||||
|
|
||||||
shown(() -> {
|
|
||||||
content().clear();
|
|
||||||
content().label(() ->{
|
|
||||||
Map map = world.maps().getByName(field.getText());
|
|
||||||
if(map != null){
|
|
||||||
if(map.custom){
|
|
||||||
return "$text.editor.overwrite";
|
|
||||||
}else{
|
|
||||||
return "$text.editor.failoverwrite";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}).colspan(2);
|
|
||||||
content().row();
|
|
||||||
content().add("$text.editor.mapname").padRight(14f);
|
|
||||||
content().add(field).size(220f, 48f);
|
|
||||||
});
|
|
||||||
|
|
||||||
buttons().defaults().size(200f, 50f).pad(2f);
|
|
||||||
buttons().addButton("$text.cancel", this::hide);
|
|
||||||
|
|
||||||
TextButton button = new TextButton("$text.save");
|
|
||||||
button.clicked(() -> {
|
|
||||||
if(!invalid()){
|
|
||||||
cons.accept(field.getText());
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
button.setDisabled(this::invalid);
|
|
||||||
buttons().add(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save(){
|
public MapSaveDialog(Consumer<String> cons){
|
||||||
if(!invalid()){
|
super("$text.editor.savemap");
|
||||||
listener.accept(field.getText());
|
field = new TextField();
|
||||||
}else{
|
listener = cons;
|
||||||
ui.showError("$text.editor.failoverwrite");
|
|
||||||
}
|
Platform.instance.addDialog(field);
|
||||||
}
|
|
||||||
|
shown(() -> {
|
||||||
public void setFieldText(String text){
|
content().clear();
|
||||||
field.setText(text);
|
content().label(() -> {
|
||||||
}
|
Map map = world.maps().getByName(field.getText());
|
||||||
|
if(map != null){
|
||||||
private boolean invalid(){
|
if(map.custom){
|
||||||
if(field.getText().isEmpty()){
|
return "$text.editor.overwrite";
|
||||||
return true;
|
}else{
|
||||||
}
|
return "$text.editor.failoverwrite";
|
||||||
Map map = world.maps().getByName(field.getText());
|
}
|
||||||
return map != null && !map.custom;
|
}
|
||||||
}
|
return "";
|
||||||
|
}).colspan(2);
|
||||||
|
content().row();
|
||||||
|
content().add("$text.editor.mapname").padRight(14f);
|
||||||
|
content().add(field).size(220f, 48f);
|
||||||
|
});
|
||||||
|
|
||||||
|
buttons().defaults().size(200f, 50f).pad(2f);
|
||||||
|
buttons().addButton("$text.cancel", this::hide);
|
||||||
|
|
||||||
|
TextButton button = new TextButton("$text.save");
|
||||||
|
button.clicked(() -> {
|
||||||
|
if(!invalid()){
|
||||||
|
cons.accept(field.getText());
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
button.setDisabled(this::invalid);
|
||||||
|
buttons().add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(){
|
||||||
|
if(!invalid()){
|
||||||
|
listener.accept(field.getText());
|
||||||
|
}else{
|
||||||
|
ui.showError("$text.editor.failoverwrite");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldText(String text){
|
||||||
|
field.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean invalid(){
|
||||||
|
if(field.getText().isEmpty()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Map map = world.maps().getByName(field.getText());
|
||||||
|
return map != null && !map.custom;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,261 +33,261 @@ import static io.anuke.mindustry.Vars.mobile;
|
|||||||
import static io.anuke.mindustry.Vars.ui;
|
import static io.anuke.mindustry.Vars.ui;
|
||||||
|
|
||||||
public class MapView extends Element implements GestureListener{
|
public class MapView extends Element implements GestureListener{
|
||||||
private MapEditor editor;
|
private MapEditor editor;
|
||||||
private EditorTool tool = EditorTool.pencil;
|
private EditorTool tool = EditorTool.pencil;
|
||||||
private OperationStack stack = new OperationStack();
|
private OperationStack stack = new OperationStack();
|
||||||
private DrawOperation op;
|
private DrawOperation op;
|
||||||
private Bresenham2 br = new Bresenham2();
|
private Bresenham2 br = new Bresenham2();
|
||||||
private boolean updated = false;
|
private boolean updated = false;
|
||||||
private float offsetx, offsety;
|
private float offsetx, offsety;
|
||||||
private float zoom = 1f;
|
private float zoom = 1f;
|
||||||
private boolean grid = false;
|
private boolean grid = false;
|
||||||
private GridImage image = new GridImage(0, 0);
|
private GridImage image = new GridImage(0, 0);
|
||||||
private Vector2 vec = new Vector2();
|
private Vector2 vec = new Vector2();
|
||||||
private Rectangle rect = new Rectangle();
|
private Rectangle rect = new Rectangle();
|
||||||
private Vector2[][] brushPolygons = new Vector2[MapEditor.brushSizes.length][0];
|
private Vector2[][] brushPolygons = new Vector2[MapEditor.brushSizes.length][0];
|
||||||
|
|
||||||
private boolean drawing;
|
private boolean drawing;
|
||||||
private int lastx, lasty;
|
private int lastx, lasty;
|
||||||
private int startx, starty;
|
private int startx, starty;
|
||||||
private float mousex, mousey;
|
private float mousex, mousey;
|
||||||
private EditorTool lastTool;
|
private EditorTool lastTool;
|
||||||
|
|
||||||
public void setTool(EditorTool tool){
|
public MapView(MapEditor editor){
|
||||||
this.tool = tool;
|
this.editor = editor;
|
||||||
}
|
|
||||||
|
|
||||||
public EditorTool getTool() {
|
for(int i = 0; i < MapEditor.brushSizes.length; i++){
|
||||||
return tool;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearStack(){
|
|
||||||
stack.clear();
|
|
||||||
//TODO clear und obuffer
|
|
||||||
}
|
|
||||||
|
|
||||||
public OperationStack getStack() {
|
|
||||||
return stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGrid(boolean grid) {
|
|
||||||
this.grid = grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isGrid() {
|
|
||||||
return grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void undo(){
|
|
||||||
if(stack.canUndo()){
|
|
||||||
stack.undo(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redo(){
|
|
||||||
if(stack.canRedo()){
|
|
||||||
stack.redo(editor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addTileOp(TileOperation t){
|
|
||||||
op.addOperation(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkForDuplicates(short x, short y){
|
|
||||||
return op.checkDuplicate(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MapView(MapEditor editor){
|
|
||||||
this.editor = editor;
|
|
||||||
|
|
||||||
for(int i = 0; i < MapEditor.brushSizes.length; i ++){
|
|
||||||
float size = MapEditor.brushSizes[i];
|
float size = MapEditor.brushSizes[i];
|
||||||
brushPolygons[i] = Geometry.pixelCircle(size, (index, x, y) -> Vector2.dst(x, y, index, index) <= index - 0.5f);
|
brushPolygons[i] = Geometry.pixelCircle(size, (index, x, y) -> Vector2.dst(x, y, index, index) <= index - 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inputs.addProcessor(0, new GestureDetector(20, 0.5f, 2, 0.15f, this));
|
|
||||||
setTouchable(Touchable.enabled);
|
|
||||||
|
|
||||||
addListener(new InputListener(){
|
|
||||||
|
|
||||||
@Override
|
Inputs.addProcessor(0, new GestureDetector(20, 0.5f, 2, 0.15f, this));
|
||||||
public boolean mouseMoved (InputEvent event, float x, float y) {
|
setTouchable(Touchable.enabled);
|
||||||
mousex = x;
|
|
||||||
mousey = y;
|
|
||||||
|
|
||||||
return false;
|
addListener(new InputListener(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseMoved(InputEvent event, float x, float y){
|
||||||
|
mousex = x;
|
||||||
|
mousey = y;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
|
|
||||||
if(pointer != 0){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!mobile && button != Buttons.LEFT && button != Buttons.MIDDLE){
|
@Override
|
||||||
return true;
|
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
|
||||||
}
|
if(pointer != 0){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(button == Buttons.MIDDLE){
|
if(!mobile && button != Buttons.LEFT && button != Buttons.MIDDLE){
|
||||||
lastTool = tool;
|
return true;
|
||||||
tool = EditorTool.zoom;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mousex = x;
|
if(button == Buttons.MIDDLE){
|
||||||
mousey = y;
|
lastTool = tool;
|
||||||
|
tool = EditorTool.zoom;
|
||||||
|
}
|
||||||
|
|
||||||
op = new DrawOperation(editor.getMap());
|
mousex = x;
|
||||||
|
mousey = y;
|
||||||
|
|
||||||
updated = false;
|
op = new DrawOperation(editor.getMap());
|
||||||
|
|
||||||
GridPoint2 p = project(x, y);
|
updated = false;
|
||||||
lastx = p.x;
|
|
||||||
lasty = p.y;
|
|
||||||
startx = p.x;
|
|
||||||
starty = p.y;
|
|
||||||
tool.touched(editor, p.x, p.y);
|
|
||||||
|
|
||||||
if(tool.edit){
|
|
||||||
updated = true;
|
|
||||||
ui.editor.resetSaved();
|
|
||||||
}
|
|
||||||
|
|
||||||
drawing = true;
|
GridPoint2 p = project(x, y);
|
||||||
return true;
|
lastx = p.x;
|
||||||
}
|
lasty = p.y;
|
||||||
|
startx = p.x;
|
||||||
@Override
|
starty = p.y;
|
||||||
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
|
tool.touched(editor, p.x, p.y);
|
||||||
if(!mobile && button != Buttons.LEFT && button != Buttons.MIDDLE){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawing = false;
|
if(tool.edit){
|
||||||
|
updated = true;
|
||||||
|
ui.editor.resetSaved();
|
||||||
|
}
|
||||||
|
|
||||||
GridPoint2 p = project(x, y);
|
drawing = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(tool == EditorTool.line){
|
@Override
|
||||||
ui.editor.resetSaved();
|
public void touchUp(InputEvent event, float x, float y, int pointer, int button){
|
||||||
Array<GridPoint2> points = br.line(startx, starty, p.x, p.y);
|
if(!mobile && button != Buttons.LEFT && button != Buttons.MIDDLE){
|
||||||
for(GridPoint2 point : points){
|
return;
|
||||||
editor.draw(point.x, point.y);
|
}
|
||||||
}
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(op != null && updated){
|
drawing = false;
|
||||||
if(!op.isEmpty()){
|
|
||||||
stack.add(op);
|
|
||||||
}
|
|
||||||
op = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(lastTool != null){
|
GridPoint2 p = project(x, y);
|
||||||
tool = lastTool;
|
|
||||||
lastTool = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if(tool == EditorTool.line){
|
||||||
|
ui.editor.resetSaved();
|
||||||
@Override
|
Array<GridPoint2> points = br.line(startx, starty, p.x, p.y);
|
||||||
public void touchDragged (InputEvent event, float x, float y, int pointer) {
|
for(GridPoint2 point : points){
|
||||||
mousex = x;
|
editor.draw(point.x, point.y);
|
||||||
mousey = y;
|
}
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
GridPoint2 p = project(x, y);
|
if(op != null && updated){
|
||||||
|
if(!op.isEmpty()){
|
||||||
if(drawing && tool.draggable){
|
stack.add(op);
|
||||||
ui.editor.resetSaved();
|
}
|
||||||
Array<GridPoint2> points = br.line(lastx, lasty, p.x, p.y);
|
op = null;
|
||||||
for(GridPoint2 point : points){
|
}
|
||||||
tool.touched(editor, point.x, point.y);
|
|
||||||
}
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
lastx = p.x;
|
|
||||||
lasty = p.y;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void act(float delta){
|
|
||||||
super.act(delta);
|
|
||||||
|
|
||||||
if(Core.scene.getKeyboardFocus() == null || !(Core.scene.getKeyboardFocus() instanceof TextField) &&
|
if(lastTool != null){
|
||||||
!Inputs.keyDown(io.anuke.ucore.input.Input.CONTROL_LEFT)) {
|
tool = lastTool;
|
||||||
float ax = Inputs.getAxis("move_x");
|
lastTool = null;
|
||||||
float ay = Inputs.getAxis("move_y");
|
}
|
||||||
offsetx -= ax * 15f / zoom;
|
|
||||||
offsety -= ay * 15f / zoom;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ui.editor.hasPane()) return;
|
}
|
||||||
|
|
||||||
zoom += Inputs.scroll()/10f * zoom;
|
|
||||||
clampZoom();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clampZoom(){
|
|
||||||
zoom = Mathf.clamp(zoom, 0.2f, 12f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GridPoint2 project(float x, float y){
|
|
||||||
float ratio = 1f / ((float)editor.getMap().width() / editor.getMap().height());
|
|
||||||
float size = Math.min(width, height);
|
|
||||||
float sclwidth = size * zoom;
|
|
||||||
float sclheight = size * zoom * ratio;
|
|
||||||
x = (x - getWidth()/2 + sclwidth/2 - offsetx*zoom) / sclwidth * editor.getMap().width();
|
|
||||||
y = (y - getHeight()/2 + sclheight/2 - offsety*zoom) / sclheight * editor.getMap().height();
|
|
||||||
|
|
||||||
if(editor.getDrawBlock().size % 2 == 0 && tool != EditorTool.eraser){
|
@Override
|
||||||
return Tmp.g1.set((int)(x - 0.5f), (int)(y - 0.5f));
|
public void touchDragged(InputEvent event, float x, float y, int pointer){
|
||||||
}else{
|
mousex = x;
|
||||||
return Tmp.g1.set((int)x, (int)y);
|
mousey = y;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Vector2 unproject(int x, int y){
|
GridPoint2 p = project(x, y);
|
||||||
float ratio = 1f / ((float)editor.getMap().width() / editor.getMap().height());
|
|
||||||
float size = Math.min(width, height);
|
|
||||||
float sclwidth = size * zoom;
|
|
||||||
float sclheight = size * zoom * ratio;
|
|
||||||
float px = ((float)x / editor.getMap().width()) * sclwidth + offsetx*zoom - sclwidth/2 + getWidth()/2;
|
|
||||||
float py = ((float)(y) / editor.getMap().height()) * sclheight
|
|
||||||
+ offsety*zoom - sclheight/2 + getHeight()/2;
|
|
||||||
return vec.set(px, py);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if(drawing && tool.draggable){
|
||||||
public void draw(Batch batch, float alpha){
|
ui.editor.resetSaved();
|
||||||
float ratio = 1f / ((float)editor.getMap().width() / editor.getMap().height());
|
Array<GridPoint2> points = br.line(lastx, lasty, p.x, p.y);
|
||||||
float size = Math.min(width, height);
|
for(GridPoint2 point : points){
|
||||||
float sclwidth = size * zoom;
|
tool.touched(editor, point.x, point.y);
|
||||||
float sclheight = size * zoom * ratio;
|
}
|
||||||
float centerx = x + width/2 + offsetx * zoom;
|
updated = true;
|
||||||
float centery = y + height/2 + offsety * zoom;
|
}
|
||||||
|
lastx = p.x;
|
||||||
|
lasty = p.y;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
image.setImageSize(editor.getMap().width(), editor.getMap().height());
|
public EditorTool getTool(){
|
||||||
|
return tool;
|
||||||
batch.flush();
|
}
|
||||||
boolean pop = ScissorStack.pushScissors(rect.set(x, y, width, height));
|
|
||||||
|
|
||||||
Draw.color(Color.LIGHT_GRAY);
|
public void setTool(EditorTool tool){
|
||||||
Lines.stroke(-2f);
|
this.tool = tool;
|
||||||
Lines.rect(centerx - sclwidth/2 - 1, centery - sclheight/2 - 1, sclwidth + 2, sclheight + 2);
|
}
|
||||||
editor.renderer().draw(centerx - sclwidth/2, centery - sclheight/2, sclwidth, sclheight);
|
|
||||||
Draw.reset();
|
|
||||||
|
|
||||||
if(grid){
|
public void clearStack(){
|
||||||
Draw.color(Color.GRAY);
|
stack.clear();
|
||||||
image.setBounds(centerx - sclwidth/2, centery - sclheight/2, sclwidth, sclheight);
|
//TODO clear und obuffer
|
||||||
image.draw(batch, alpha);
|
}
|
||||||
Draw.color();
|
|
||||||
}
|
public OperationStack getStack(){
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGrid(){
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrid(boolean grid){
|
||||||
|
this.grid = grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void undo(){
|
||||||
|
if(stack.canUndo()){
|
||||||
|
stack.undo(editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void redo(){
|
||||||
|
if(stack.canRedo()){
|
||||||
|
stack.redo(editor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTileOp(TileOperation t){
|
||||||
|
op.addOperation(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkForDuplicates(short x, short y){
|
||||||
|
return op.checkDuplicate(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void act(float delta){
|
||||||
|
super.act(delta);
|
||||||
|
|
||||||
|
if(Core.scene.getKeyboardFocus() == null || !(Core.scene.getKeyboardFocus() instanceof TextField) &&
|
||||||
|
!Inputs.keyDown(io.anuke.ucore.input.Input.CONTROL_LEFT)){
|
||||||
|
float ax = Inputs.getAxis("move_x");
|
||||||
|
float ay = Inputs.getAxis("move_y");
|
||||||
|
offsetx -= ax * 15f / zoom;
|
||||||
|
offsety -= ay * 15f / zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ui.editor.hasPane()) return;
|
||||||
|
|
||||||
|
zoom += Inputs.scroll() / 10f * zoom;
|
||||||
|
clampZoom();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clampZoom(){
|
||||||
|
zoom = Mathf.clamp(zoom, 0.2f, 12f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GridPoint2 project(float x, float y){
|
||||||
|
float ratio = 1f / ((float) editor.getMap().width() / editor.getMap().height());
|
||||||
|
float size = Math.min(width, height);
|
||||||
|
float sclwidth = size * zoom;
|
||||||
|
float sclheight = size * zoom * ratio;
|
||||||
|
x = (x - getWidth() / 2 + sclwidth / 2 - offsetx * zoom) / sclwidth * editor.getMap().width();
|
||||||
|
y = (y - getHeight() / 2 + sclheight / 2 - offsety * zoom) / sclheight * editor.getMap().height();
|
||||||
|
|
||||||
|
if(editor.getDrawBlock().size % 2 == 0 && tool != EditorTool.eraser){
|
||||||
|
return Tmp.g1.set((int) (x - 0.5f), (int) (y - 0.5f));
|
||||||
|
}else{
|
||||||
|
return Tmp.g1.set((int) x, (int) y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 unproject(int x, int y){
|
||||||
|
float ratio = 1f / ((float) editor.getMap().width() / editor.getMap().height());
|
||||||
|
float size = Math.min(width, height);
|
||||||
|
float sclwidth = size * zoom;
|
||||||
|
float sclheight = size * zoom * ratio;
|
||||||
|
float px = ((float) x / editor.getMap().width()) * sclwidth + offsetx * zoom - sclwidth / 2 + getWidth() / 2;
|
||||||
|
float py = ((float) (y) / editor.getMap().height()) * sclheight
|
||||||
|
+ offsety * zoom - sclheight / 2 + getHeight() / 2;
|
||||||
|
return vec.set(px, py);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Batch batch, float alpha){
|
||||||
|
float ratio = 1f / ((float) editor.getMap().width() / editor.getMap().height());
|
||||||
|
float size = Math.min(width, height);
|
||||||
|
float sclwidth = size * zoom;
|
||||||
|
float sclheight = size * zoom * ratio;
|
||||||
|
float centerx = x + width / 2 + offsetx * zoom;
|
||||||
|
float centery = y + height / 2 + offsety * zoom;
|
||||||
|
|
||||||
|
image.setImageSize(editor.getMap().width(), editor.getMap().height());
|
||||||
|
|
||||||
|
batch.flush();
|
||||||
|
boolean pop = ScissorStack.pushScissors(rect.set(x, y, width, height));
|
||||||
|
|
||||||
|
Draw.color(Color.LIGHT_GRAY);
|
||||||
|
Lines.stroke(-2f);
|
||||||
|
Lines.rect(centerx - sclwidth / 2 - 1, centery - sclheight / 2 - 1, sclwidth + 2, sclheight + 2);
|
||||||
|
editor.renderer().draw(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight);
|
||||||
|
Draw.reset();
|
||||||
|
|
||||||
|
if(grid){
|
||||||
|
Draw.color(Color.GRAY);
|
||||||
|
image.setBounds(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight);
|
||||||
|
image.draw(batch, alpha);
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(int i = 0; i < MapEditor.brushSizes.length; i ++){
|
for(int i = 0; i < MapEditor.brushSizes.length; i++){
|
||||||
if(editor.getBrushSize() == MapEditor.brushSizes[i]){
|
if(editor.getBrushSize() == MapEditor.brushSizes[i]){
|
||||||
index = i;
|
index = i;
|
||||||
break;
|
break;
|
||||||
@@ -297,102 +297,102 @@ public class MapView extends Element implements GestureListener{
|
|||||||
//todo is it really math.max?
|
//todo is it really math.max?
|
||||||
float scaling = zoom * Math.min(width, height) / Math.max(editor.getMap().width(), editor.getMap().height());
|
float scaling = zoom * Math.min(width, height) / Math.max(editor.getMap().width(), editor.getMap().height());
|
||||||
|
|
||||||
Draw.color(Palette.accent);
|
Draw.color(Palette.accent);
|
||||||
Lines.stroke(Unit.dp.scl(1f * zoom));
|
Lines.stroke(Unit.dp.scl(1f * zoom));
|
||||||
|
|
||||||
if(!editor.getDrawBlock().isMultiblock() || tool == EditorTool.eraser) {
|
if(!editor.getDrawBlock().isMultiblock() || tool == EditorTool.eraser){
|
||||||
if (tool == EditorTool.line && drawing) {
|
if(tool == EditorTool.line && drawing){
|
||||||
Vector2 v1 = unproject(startx, starty).add(x, y);
|
Vector2 v1 = unproject(startx, starty).add(x, y);
|
||||||
float sx = v1.x, sy = v1.y;
|
float sx = v1.x, sy = v1.y;
|
||||||
Vector2 v2 = unproject(lastx, lasty).add(x, y);
|
Vector2 v2 = unproject(lastx, lasty).add(x, y);
|
||||||
|
|
||||||
Lines.poly(brushPolygons[index], sx, sy, scaling);
|
Lines.poly(brushPolygons[index], sx, sy, scaling);
|
||||||
Lines.poly(brushPolygons[index], v2.x, v2.y, scaling);
|
Lines.poly(brushPolygons[index], v2.x, v2.y, scaling);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tool.edit && (!mobile || drawing)) {
|
if(tool.edit && (!mobile || drawing)){
|
||||||
GridPoint2 p = project(mousex, mousey);
|
GridPoint2 p = project(mousex, mousey);
|
||||||
Vector2 v = unproject(p.x, p.y).add(x, y);
|
Vector2 v = unproject(p.x, p.y).add(x, y);
|
||||||
Lines.poly(brushPolygons[index], v.x, v.y, scaling);
|
Lines.poly(brushPolygons[index], v.x, v.y, scaling);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if((tool.edit || tool == EditorTool.line) && (!mobile || drawing)){
|
if((tool.edit || tool == EditorTool.line) && (!mobile || drawing)){
|
||||||
GridPoint2 p = project(mousex, mousey);
|
GridPoint2 p = project(mousex, mousey);
|
||||||
Vector2 v = unproject(p.x, p.y).add(x, y);
|
Vector2 v = unproject(p.x, p.y).add(x, y);
|
||||||
float offset = (editor.getDrawBlock().size % 2 == 0 ? scaling/2f : 0f);
|
float offset = (editor.getDrawBlock().size % 2 == 0 ? scaling / 2f : 0f);
|
||||||
Lines.square(
|
Lines.square(
|
||||||
v.x + scaling/2f + offset,
|
v.x + scaling / 2f + offset,
|
||||||
v.y + scaling/2f + offset,
|
v.y + scaling / 2f + offset,
|
||||||
scaling * editor.getDrawBlock().size /2f);
|
scaling * editor.getDrawBlock().size / 2f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.flush();
|
batch.flush();
|
||||||
|
|
||||||
if(pop) ScissorStack.popScissors();
|
|
||||||
|
|
||||||
Draw.color(Palette.accent);
|
|
||||||
Lines.stroke(Unit.dp.scl(3f));
|
|
||||||
Lines.rect(x, y, width, height);
|
|
||||||
Draw.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean active(){
|
|
||||||
return Core.scene.getKeyboardFocus() != null
|
|
||||||
&& Core.scene.getKeyboardFocus().isDescendantOf(ui.editor)
|
|
||||||
&& ui.editor.isShown() && tool == EditorTool.zoom &&
|
|
||||||
Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true) == this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if(pop) ScissorStack.popScissors();
|
||||||
public boolean touchDown(float x, float y, int pointer, int button){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
Draw.color(Palette.accent);
|
||||||
public boolean tap(float x, float y, int count, int button){
|
Lines.stroke(Unit.dp.scl(3f));
|
||||||
return false;
|
Lines.rect(x, y, width, height);
|
||||||
}
|
Draw.reset();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private boolean active(){
|
||||||
public boolean longPress(float x, float y){
|
return Core.scene.getKeyboardFocus() != null
|
||||||
return false;
|
&& Core.scene.getKeyboardFocus().isDescendantOf(ui.editor)
|
||||||
}
|
&& ui.editor.isShown() && tool == EditorTool.zoom &&
|
||||||
|
Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true) == this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fling(float velocityX, float velocityY, int button){
|
public boolean touchDown(float x, float y, int pointer, int button){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean pan(float x, float y, float deltaX, float deltaY){
|
public boolean tap(float x, float y, int count, int button){
|
||||||
if(!active()) return false;
|
return false;
|
||||||
offsetx += deltaX / zoom;
|
}
|
||||||
offsety -= deltaY / zoom;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean panStop(float x, float y, int pointer, int button){
|
public boolean longPress(float x, float y){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean zoom(float initialDistance, float distance){
|
public boolean fling(float velocityX, float velocityY, int button){
|
||||||
if(!active()) return false;
|
return false;
|
||||||
float nzoom = distance - initialDistance;
|
}
|
||||||
zoom += nzoom / 10000f / Unit.dp.scl(1f) * zoom;
|
|
||||||
clampZoom();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2){
|
public boolean pan(float x, float y, float deltaX, float deltaY){
|
||||||
return false;
|
if(!active()) return false;
|
||||||
}
|
offsetx += deltaX / zoom;
|
||||||
|
offsety -= deltaY / zoom;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pinchStop(){
|
public boolean panStop(float x, float y, int pointer, int button){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public boolean zoom(float initialDistance, float distance){
|
||||||
|
if(!active()) return false;
|
||||||
|
float nzoom = distance - initialDistance;
|
||||||
|
zoom += nzoom / 10000f / Unit.dp.scl(1f) * zoom;
|
||||||
|
clampZoom();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pinchStop(){
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,49 +3,49 @@ package io.anuke.mindustry.editor;
|
|||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
public class OperationStack{
|
public class OperationStack{
|
||||||
private final static int maxSize = 10;
|
private final static int maxSize = 10;
|
||||||
private Array<DrawOperation> stack = new Array<>();
|
private Array<DrawOperation> stack = new Array<>();
|
||||||
private int index = 0;
|
private int index = 0;
|
||||||
|
|
||||||
public OperationStack(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear(){
|
|
||||||
stack.clear();
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void add(DrawOperation action){
|
|
||||||
stack.truncate(stack.size + index);
|
|
||||||
index = 0;
|
|
||||||
stack.add(action);
|
|
||||||
|
|
||||||
if(stack.size > maxSize){
|
public OperationStack(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear(){
|
||||||
|
stack.clear();
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(DrawOperation action){
|
||||||
|
stack.truncate(stack.size + index);
|
||||||
|
index = 0;
|
||||||
|
stack.add(action);
|
||||||
|
|
||||||
|
if(stack.size > maxSize){
|
||||||
stack.removeIndex(0);
|
stack.removeIndex(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canUndo(){
|
|
||||||
return !(stack.size - 1 + index < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canRedo(){
|
|
||||||
return !(index > -1 || stack.size + index < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void undo(MapEditor editor){
|
public boolean canUndo(){
|
||||||
if(!canUndo()) return;
|
return !(stack.size - 1 + index < 0);
|
||||||
|
}
|
||||||
|
|
||||||
stack.get(stack.size - 1 + index).undo(editor);
|
public boolean canRedo(){
|
||||||
index --;
|
return !(index > -1 || stack.size + index < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void redo(MapEditor editor){
|
public void undo(MapEditor editor){
|
||||||
if(!canRedo()) return;
|
if(!canUndo()) return;
|
||||||
|
|
||||||
index ++;
|
stack.get(stack.size - 1 + index).undo(editor);
|
||||||
stack.get(stack.size - 1 + index).redo(editor);
|
index--;
|
||||||
|
}
|
||||||
}
|
|
||||||
|
public void redo(MapEditor editor){
|
||||||
|
if(!canRedo()) return;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
stack.get(stack.size - 1 + index).redo(editor);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,84 +24,90 @@ import io.anuke.ucore.util.Translator;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
/**Utility class for damaging in an area.*/
|
/**
|
||||||
public class Damage {
|
* Utility class for damaging in an area.
|
||||||
private static Rectangle rect = new Rectangle();
|
*/
|
||||||
private static Rectangle hitrect = new Rectangle();
|
public class Damage{
|
||||||
private static Translator tr = new Translator();
|
private static Rectangle rect = new Rectangle();
|
||||||
|
private static Rectangle hitrect = new Rectangle();
|
||||||
|
private static Translator tr = new Translator();
|
||||||
|
|
||||||
/**Creates a dynamic explosion based on specified parameters.*/
|
/**
|
||||||
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color){
|
* Creates a dynamic explosion based on specified parameters.
|
||||||
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i ++){
|
*/
|
||||||
int branches = 5 + Mathf.clamp((int)(power/30), 1, 20);
|
public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color){
|
||||||
Timers.run(i*2f + Mathf.random(4f), () -> Lightning.create(Team.none, Fx.none, Palette.power, 3,
|
for(int i = 0; i < Mathf.clamp(power / 20, 0, 6); i++){
|
||||||
x, y, Mathf.random(360f), branches + Mathf.range(2)));
|
int branches = 5 + Mathf.clamp((int) (power / 30), 1, 20);
|
||||||
}
|
Timers.run(i * 2f + Mathf.random(4f), () -> Lightning.create(Team.none, Fx.none, Palette.power, 3,
|
||||||
|
x, y, Mathf.random(360f), branches + Mathf.range(2)));
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i ++){
|
for(int i = 0; i < Mathf.clamp(flammability / 4, 0, 30); i++){
|
||||||
Timers.run(i/2, () -> CallEntity.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)));
|
Timers.run(i / 2, () -> CallEntity.createBullet(TurretBullets.fireball, x, y, Mathf.random(360f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int waves = Mathf.clamp((int)(explosiveness / 4), 0, 30);
|
int waves = Mathf.clamp((int) (explosiveness / 4), 0, 30);
|
||||||
|
|
||||||
for(int i = 0; i < waves; i ++){
|
for(int i = 0; i < waves; i++){
|
||||||
int f = i;
|
int f = i;
|
||||||
Timers.run(i*2f, () -> {
|
Timers.run(i * 2f, () -> {
|
||||||
Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f)/waves), explosiveness/2f);
|
Damage.damage(x, y, Mathf.clamp(radius + explosiveness, 0, 50f) * ((f + 1f) / waves), explosiveness / 2f);
|
||||||
Effects.effect(ExplosionFx.blockExplosionSmoke, x + Mathf.range(radius), y + Mathf.range(radius));
|
Effects.effect(ExplosionFx.blockExplosionSmoke, x + Mathf.range(radius), y + Mathf.range(radius));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(explosiveness > 15f){
|
if(explosiveness > 15f){
|
||||||
Effects.effect(ExplosionFx.shockwave, x, y);
|
Effects.effect(ExplosionFx.shockwave, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(explosiveness > 30f){
|
if(explosiveness > 30f){
|
||||||
Effects.effect(ExplosionFx.bigShockwave, x, y);
|
Effects.effect(ExplosionFx.bigShockwave, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
float shake = Math.min(explosiveness/4f + 3f, 9f);
|
float shake = Math.min(explosiveness / 4f + 3f, 9f);
|
||||||
Effects.shake(shake, shake, x, y);
|
Effects.shake(shake, shake, x, y);
|
||||||
Effects.effect(ExplosionFx.blockExplosion, x, y);
|
Effects.effect(ExplosionFx.blockExplosion, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createIncend(float x, float y, float range, int amount){
|
public static void createIncend(float x, float y, float range, int amount){
|
||||||
for (int i = 0; i < amount; i++) {
|
for(int i = 0; i < amount; i++){
|
||||||
float cx = x + Mathf.range(range);
|
float cx = x + Mathf.range(range);
|
||||||
float cy = y + Mathf.range(range);
|
float cy = y + Mathf.range(range);
|
||||||
Tile tile = world.tileWorld(cx, cy);
|
Tile tile = world.tileWorld(cx, cy);
|
||||||
if(tile != null){
|
if(tile != null){
|
||||||
Fire.create(tile);
|
Fire.create(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Damages entities in a line.
|
/**
|
||||||
* Only enemies of the specified team are damaged.*/
|
* Damages entities in a line.
|
||||||
public static void collideLine(SolidEntity hitter, Team team, Effect effect, float x, float y, float angle, float length){
|
* Only enemies of the specified team are damaged.
|
||||||
tr.trns(angle, length);
|
*/
|
||||||
rect.setPosition(x, y).setSize(tr.x, tr.y);
|
public static void collideLine(SolidEntity hitter, Team team, Effect effect, float x, float y, float angle, float length){
|
||||||
float x2 = tr.x + x, y2 = tr.y + y;
|
tr.trns(angle, length);
|
||||||
|
rect.setPosition(x, y).setSize(tr.x, tr.y);
|
||||||
|
float x2 = tr.x + x, y2 = tr.y + y;
|
||||||
|
|
||||||
if(rect.width < 0){
|
if(rect.width < 0){
|
||||||
rect.x += rect.width;
|
rect.x += rect.width;
|
||||||
rect.width *= -1;
|
rect.width *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rect.height < 0){
|
if(rect.height < 0){
|
||||||
rect.y += rect.height;
|
rect.y += rect.height;
|
||||||
rect.height *= -1;
|
rect.height *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float expand = 3f;
|
float expand = 3f;
|
||||||
|
|
||||||
rect.y -= expand;
|
rect.y -= expand;
|
||||||
rect.x -= expand;
|
rect.x -= expand;
|
||||||
rect.width += expand*2;
|
rect.width += expand * 2;
|
||||||
rect.height += expand*2;
|
rect.height += expand * 2;
|
||||||
|
|
||||||
Consumer<Unit> cons = e -> {
|
Consumer<Unit> cons = e -> {
|
||||||
e.getHitbox(hitrect);
|
e.getHitbox(hitrect);
|
||||||
Rectangle other = hitrect;
|
Rectangle other = hitrect;
|
||||||
other.y -= expand;
|
other.y -= expand;
|
||||||
other.x -= expand;
|
other.x -= expand;
|
||||||
@@ -110,79 +116,85 @@ public class Damage {
|
|||||||
|
|
||||||
Vector2 vec = Physics.raycastRect(x, y, x2, y2, other);
|
Vector2 vec = Physics.raycastRect(x, y, x2, y2, other);
|
||||||
|
|
||||||
if (vec != null) {
|
if(vec != null){
|
||||||
Effects.effect(effect, vec.x, vec.y);
|
Effects.effect(effect, vec.x, vec.y);
|
||||||
e.collision(hitter, vec.x, vec.y);
|
e.collision(hitter, vec.x, vec.y);
|
||||||
hitter.collision(e, vec.x, vec.y);
|
hitter.collision(e, vec.x, vec.y);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Units.getNearbyEnemies(team, rect, cons);
|
Units.getNearbyEnemies(team, rect, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Damages all entities and blocks in a radius that are enemies of the team.*/
|
/**
|
||||||
public static void damageUnits(Team team, float x, float y, float size, float damage, Predicate<Unit> predicate, Consumer<Unit> acceptor) {
|
* Damages all entities and blocks in a radius that are enemies of the team.
|
||||||
Consumer<Unit> cons = entity -> {
|
*/
|
||||||
if(!predicate.test(entity)) return;
|
public static void damageUnits(Team team, float x, float y, float size, float damage, Predicate<Unit> predicate, Consumer<Unit> acceptor){
|
||||||
|
Consumer<Unit> cons = entity -> {
|
||||||
|
if(!predicate.test(entity)) return;
|
||||||
|
|
||||||
entity.getHitbox(hitrect);
|
entity.getHitbox(hitrect);
|
||||||
if (!hitrect.overlaps(rect)) {
|
if(!hitrect.overlaps(rect)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entity.damage(damage);
|
entity.damage(damage);
|
||||||
acceptor.accept(entity);
|
acceptor.accept(entity);
|
||||||
};
|
};
|
||||||
|
|
||||||
rect.setSize(size * 2).setCenter(x, y);
|
rect.setSize(size * 2).setCenter(x, y);
|
||||||
if (team != null) {
|
if(team != null){
|
||||||
Units.getNearbyEnemies(team, rect, cons);
|
Units.getNearbyEnemies(team, rect, cons);
|
||||||
} else {
|
}else{
|
||||||
Units.getNearby(rect, cons);
|
Units.getNearby(rect, cons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Damages everything in a radius.*/
|
/**
|
||||||
public static void damage(float x, float y, float radius, float damage){
|
* Damages everything in a radius.
|
||||||
damage(null, x, y, radius, damage);
|
*/
|
||||||
}
|
public static void damage(float x, float y, float radius, float damage){
|
||||||
|
damage(null, x, y, radius, damage);
|
||||||
|
}
|
||||||
|
|
||||||
/**Damages all entities and blocks in a radius that are enemies of the team.*/
|
/**
|
||||||
public static void damage(Team team, float x, float y, float radius, float damage){
|
* Damages all entities and blocks in a radius that are enemies of the team.
|
||||||
Consumer<Unit> cons = entity -> {
|
*/
|
||||||
if(entity.team == team || entity.distanceTo(x, y) > radius){
|
public static void damage(Team team, float x, float y, float radius, float damage){
|
||||||
return;
|
Consumer<Unit> cons = entity -> {
|
||||||
}
|
if(entity.team == team || entity.distanceTo(x, y) > radius){
|
||||||
float amount = calculateDamage(x, y, entity.x, entity.y, radius, damage);
|
return;
|
||||||
entity.damage(amount);
|
}
|
||||||
//TODO better velocity displacement
|
float amount = calculateDamage(x, y, entity.x, entity.y, radius, damage);
|
||||||
float dst = tr.set(entity.x - x, entity.y - y).len();
|
entity.damage(amount);
|
||||||
entity.getVelocity().add(tr.setLength((1f-dst/radius) * 2f));
|
//TODO better velocity displacement
|
||||||
};
|
float dst = tr.set(entity.x - x, entity.y - y).len();
|
||||||
|
entity.getVelocity().add(tr.setLength((1f - dst / radius) * 2f));
|
||||||
|
};
|
||||||
|
|
||||||
rect.setSize(radius *2).setCenter(x, y);
|
rect.setSize(radius * 2).setCenter(x, y);
|
||||||
if(team != null) {
|
if(team != null){
|
||||||
Units.getNearbyEnemies(team, rect, cons);
|
Units.getNearbyEnemies(team, rect, cons);
|
||||||
}else{
|
}else{
|
||||||
Units.getNearby(rect, cons);
|
Units.getNearby(rect, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
int trad = (int)(radius / tilesize);
|
int trad = (int) (radius / tilesize);
|
||||||
for(int dx = -trad; dx <= trad; dx ++){
|
for(int dx = -trad; dx <= trad; dx++){
|
||||||
for(int dy= -trad; dy <= trad; dy ++){
|
for(int dy = -trad; dy <= trad; dy++){
|
||||||
Tile tile = world.tile(Mathf.scl2(x, tilesize) + dx, Mathf.scl2(y, tilesize) + dy);
|
Tile tile = world.tile(Mathf.scl2(x, tilesize) + dx, Mathf.scl2(y, tilesize) + dy);
|
||||||
if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Vector2.dst(dx, dy, 0, 0) <= trad){
|
if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Vector2.dst(dx, dy, 0, 0) <= trad){
|
||||||
float amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage);
|
float amount = calculateDamage(x, y, tile.worldx(), tile.worldy(), radius, damage);
|
||||||
tile.entity.damage(amount);
|
tile.entity.damage(amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float calculateDamage(float x, float y, float tx, float ty, float radius, float damage){
|
private static float calculateDamage(float x, float y, float tx, float ty, float radius, float damage){
|
||||||
float dist = Vector2.dst(x, y, tx, ty);
|
float dist = Vector2.dst(x, y, tx, ty);
|
||||||
float falloff = 0.4f;
|
float falloff = 0.4f;
|
||||||
float scaled = Mathf.lerp(1f - dist/radius, 1f, falloff);
|
float scaled = Mathf.lerp(1f - dist / radius, 1f, falloff);
|
||||||
return damage * scaled;
|
return damage * scaled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,12 +4,16 @@ import com.badlogic.gdx.math.Vector2;
|
|||||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
/**Class for predicting shoot angles based on velocities of targets.*/
|
/**
|
||||||
public class Predict {
|
* Class for predicting shoot angles based on velocities of targets.
|
||||||
|
*/
|
||||||
|
public class Predict{
|
||||||
private static Vector2 vec = new Vector2();
|
private static Vector2 vec = new Vector2();
|
||||||
private static Vector2 vresult = new Vector2();
|
private static Vector2 vresult = new Vector2();
|
||||||
|
|
||||||
/**Calculates of intercept of a stationary and moving target. Do not call from multiple threads!
|
/**
|
||||||
|
* Calculates of intercept of a stationary and moving target. Do not call from multiple threads!
|
||||||
|
*
|
||||||
* @param srcx X of shooter
|
* @param srcx X of shooter
|
||||||
* @param srcy Y of shooter
|
* @param srcy Y of shooter
|
||||||
* @param dstx X of target
|
* @param dstx X of target
|
||||||
@@ -17,52 +21,55 @@ public class Predict {
|
|||||||
* @param dstvx X velocity of target (subtract shooter X velocity if needed)
|
* @param dstvx X velocity of target (subtract shooter X velocity if needed)
|
||||||
* @param dstvy Y velocity of target (subtract shooter Y velocity if needed)
|
* @param dstvy Y velocity of target (subtract shooter Y velocity if needed)
|
||||||
* @param v speed of bullet
|
* @param v speed of bullet
|
||||||
* @return the intercept location*/
|
* @return the intercept location
|
||||||
public static Vector2 intercept(float srcx, float srcy, float dstx, float dsty, float dstvx, float dstvy, float v) {
|
*/
|
||||||
|
public static Vector2 intercept(float srcx, float srcy, float dstx, float dsty, float dstvx, float dstvy, float v){
|
||||||
float tx = dstx - srcx,
|
float tx = dstx - srcx,
|
||||||
ty = dsty - srcy;
|
ty = dsty - srcy;
|
||||||
|
|
||||||
// Get quadratic equation components
|
// Get quadratic equation components
|
||||||
float a = dstvx * dstvx + dstvy * dstvy - v*v;
|
float a = dstvx * dstvx + dstvy * dstvy - v * v;
|
||||||
float b = 2 * (dstvx * tx + dstvy * ty);
|
float b = 2 * (dstvx * tx + dstvy * ty);
|
||||||
float c = tx*tx + ty*ty;
|
float c = tx * tx + ty * ty;
|
||||||
|
|
||||||
// Solve quadratic
|
// Solve quadratic
|
||||||
Vector2 ts = quad(a, b, c);
|
Vector2 ts = quad(a, b, c);
|
||||||
|
|
||||||
// Find smallest positive solution
|
// Find smallest positive solution
|
||||||
Vector2 sol = vresult.set(0, 0);
|
Vector2 sol = vresult.set(0, 0);
|
||||||
if (ts != null) {
|
if(ts != null){
|
||||||
float t0 = ts.x, t1 = ts.y;
|
float t0 = ts.x, t1 = ts.y;
|
||||||
float t = Math.min(t0, t1);
|
float t = Math.min(t0, t1);
|
||||||
if (t < 0) t = Math.max(t0, t1);
|
if(t < 0) t = Math.max(t0, t1);
|
||||||
if (t > 0) {
|
if(t > 0){
|
||||||
sol.set(dstx + dstvx*t, dsty + dstvy*t);
|
sol.set(dstx + dstvx * t, dsty + dstvy * t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sol;
|
return sol;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**See {@link #intercept(float, float, float, float, float, float, float)}.*/
|
/**
|
||||||
public static Vector2 intercept(TargetTrait src, TargetTrait dst, float v) {
|
* See {@link #intercept(float, float, float, float, float, float, float)}.
|
||||||
|
*/
|
||||||
|
public static Vector2 intercept(TargetTrait src, TargetTrait dst, float v){
|
||||||
return intercept(src.getX(), src.getY(), dst.getX(), dst.getY(), dst.getVelocity().x - src.getVelocity().x, dst.getVelocity().x - src.getVelocity().y, v);
|
return intercept(src.getX(), src.getY(), dst.getX(), dst.getY(), dst.getVelocity().x - src.getVelocity().x, dst.getVelocity().x - src.getVelocity().y, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vector2 quad(float a, float b, float c) {
|
private static Vector2 quad(float a, float b, float c){
|
||||||
Vector2 sol = null;
|
Vector2 sol = null;
|
||||||
if (Math.abs(a) < 1e-6) {
|
if(Math.abs(a) < 1e-6){
|
||||||
if (Math.abs(b) < 1e-6) {
|
if(Math.abs(b) < 1e-6){
|
||||||
sol = Math.abs(c) < 1e-6 ? vec.set(0,0) : null;
|
sol = Math.abs(c) < 1e-6 ? vec.set(0, 0) : null;
|
||||||
} else {
|
}else{
|
||||||
vec.set(-c/b, -c/b);
|
vec.set(-c / b, -c / b);
|
||||||
}
|
}
|
||||||
} else {
|
}else{
|
||||||
float disc = b*b - 4*a*c;
|
float disc = b * b - 4 * a * c;
|
||||||
if (disc >= 0) {
|
if(disc >= 0){
|
||||||
disc = Mathf.sqrt(disc);
|
disc = Mathf.sqrt(disc);
|
||||||
a = 2*a;
|
a = 2 * a;
|
||||||
sol = vec.set((-b-disc)/a, (-b+disc)/a);
|
sol = vec.set((-b - disc) / a, (-b + disc) / a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sol;
|
return sol;
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import java.io.DataInput;
|
|||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**Class for controlling status effects on an entity.*/
|
/**
|
||||||
|
* Class for controlling status effects on an entity.
|
||||||
|
*/
|
||||||
public class StatusController implements Saveable{
|
public class StatusController implements Saveable{
|
||||||
private static final StatusEntry globalResult = new StatusEntry();
|
private static final StatusEntry globalResult = new StatusEntry();
|
||||||
private static final Array<StatusEntry> removals = new ThreadArray<>();
|
private static final Array<StatusEntry> removals = new ThreadArray<>();
|
||||||
@@ -26,20 +28,20 @@ public class StatusController implements Saveable{
|
|||||||
public void handleApply(Unit unit, StatusEffect effect, float intensity){
|
public void handleApply(Unit unit, StatusEffect effect, float intensity){
|
||||||
if(effect == StatusEffects.none) return; //don't apply empty effects
|
if(effect == StatusEffects.none) return; //don't apply empty effects
|
||||||
|
|
||||||
float newTime = effect.baseDuration*intensity;
|
float newTime = effect.baseDuration * intensity;
|
||||||
|
|
||||||
if(statuses.size > 0){
|
if(statuses.size > 0){
|
||||||
//check for opposite effects
|
//check for opposite effects
|
||||||
for(StatusEntry entry : statuses){
|
for(StatusEntry entry : statuses){
|
||||||
//extend effect
|
//extend effect
|
||||||
if(entry.effect == effect) {
|
if(entry.effect == effect){
|
||||||
entry.time = Math.max(entry.time, newTime);
|
entry.time = Math.max(entry.time, newTime);
|
||||||
return;
|
return;
|
||||||
}else if(entry.effect.isOpposite(effect)){ //find opposite
|
}else if(entry.effect.isOpposite(effect)){ //find opposite
|
||||||
entry.effect.getTransition(unit, effect, entry.time, newTime, globalResult);
|
entry.effect.getTransition(unit, effect, entry.time, newTime, globalResult);
|
||||||
entry.time = globalResult.time;
|
entry.time = globalResult.time;
|
||||||
|
|
||||||
if (globalResult.effect != entry.effect) {
|
if(globalResult.effect != entry.effect){
|
||||||
entry.effect.onTransition(unit, globalResult.effect);
|
entry.effect.onTransition(unit, globalResult.effect);
|
||||||
entry.effect = globalResult.effect;
|
entry.effect = globalResult.effect;
|
||||||
}
|
}
|
||||||
@@ -94,7 +96,7 @@ public class StatusController implements Saveable{
|
|||||||
return damageMultiplier;
|
return damageMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getArmorMultiplier() {
|
public float getArmorMultiplier(){
|
||||||
return armorMultiplier;
|
return armorMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,24 +108,24 @@ public class StatusController implements Saveable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSave(DataOutput stream) throws IOException {
|
public void writeSave(DataOutput stream) throws IOException{
|
||||||
stream.writeByte(statuses.size);
|
stream.writeByte(statuses.size);
|
||||||
for(StatusEntry entry : statuses){
|
for(StatusEntry entry : statuses){
|
||||||
stream.writeByte(entry.effect.id);
|
stream.writeByte(entry.effect.id);
|
||||||
stream.writeShort((short)(entry.time * 2));
|
stream.writeShort((short) (entry.time * 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readSave(DataInput stream) throws IOException {
|
public void readSave(DataInput stream) throws IOException{
|
||||||
for (StatusEntry effect : statuses){
|
for(StatusEntry effect : statuses){
|
||||||
Pooling.free(effect);
|
Pooling.free(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
statuses.clear();
|
statuses.clear();
|
||||||
|
|
||||||
byte amount = stream.readByte();
|
byte amount = stream.readByte();
|
||||||
for (int i = 0; i < amount; i++) {
|
for(int i = 0; i < amount; i++){
|
||||||
byte id = stream.readByte();
|
byte id = stream.readByte();
|
||||||
float time = stream.readShort() / 2f;
|
float time = stream.readShort() / 2f;
|
||||||
StatusEntry entry = Pooling.obtain(StatusEntry.class);
|
StatusEntry entry = Pooling.obtain(StatusEntry.class);
|
||||||
@@ -132,7 +134,7 @@ public class StatusController implements Saveable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StatusEntry {
|
public static class StatusEntry{
|
||||||
public StatusEffect effect;
|
public StatusEffect effect;
|
||||||
public float time;
|
public float time;
|
||||||
|
|
||||||
|
|||||||
@@ -35,213 +35,219 @@ import java.io.IOException;
|
|||||||
import static io.anuke.mindustry.Vars.tileGroup;
|
import static io.anuke.mindustry.Vars.tileGroup;
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class TileEntity extends BaseEntity implements TargetTrait {
|
public class TileEntity extends BaseEntity implements TargetTrait{
|
||||||
public static final float timeToSleep = 60f*4; //4 seconds to fall asleep
|
public static final float timeToSleep = 60f * 4; //4 seconds to fall asleep
|
||||||
/**This value is only used for debugging.*/
|
private static final ObjectSet<Tile> tmpTiles = new ObjectSet<>();
|
||||||
public static int sleepingEntities = 0;
|
/**
|
||||||
|
* This value is only used for debugging.
|
||||||
|
*/
|
||||||
|
public static int sleepingEntities = 0;
|
||||||
|
public Tile tile;
|
||||||
|
public Timer timer;
|
||||||
|
public float health;
|
||||||
|
|
||||||
private static final ObjectSet<Tile> tmpTiles = new ObjectSet<>();
|
public PowerModule power;
|
||||||
|
public InventoryModule items;
|
||||||
|
public LiquidModule liquids;
|
||||||
|
public ConsumeModule cons;
|
||||||
|
|
||||||
public Tile tile;
|
/**List of (cached) tiles with entities in proximity, used for outputting to*/
|
||||||
public Timer timer;
|
private Array<Tile> proximity = new Array<>(8);
|
||||||
public float health;
|
private boolean dead = false;
|
||||||
|
private boolean sleeping;
|
||||||
|
private float sleepTime;
|
||||||
|
|
||||||
public PowerModule power;
|
@Remote(called = Loc.server, in = In.blocks)
|
||||||
public InventoryModule items;
|
public static void onTileDamage(Tile tile, float health){
|
||||||
public LiquidModule liquids;
|
if(tile.entity != null){
|
||||||
public ConsumeModule cons;
|
tile.entity.health = health;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//list of (cached) tiles with entities in proximity, used for outputting to
|
@Remote(called = Loc.server, in = In.blocks)
|
||||||
//TODO implement
|
public static void onTileDestroyed(Tile tile){
|
||||||
private Array<Tile> proximity = new Array<>(8);
|
if(tile.entity == null) return;
|
||||||
private boolean dead = false;
|
tile.entity.onDeath();
|
||||||
private boolean sleeping;
|
}
|
||||||
private float sleepTime;
|
|
||||||
|
|
||||||
/**Sets this tile entity data to this tile, and adds it if necessary.*/
|
|
||||||
public TileEntity init(Tile tile, boolean added){
|
|
||||||
this.tile = tile;
|
|
||||||
x = tile.drawx();
|
|
||||||
y = tile.drawy();
|
|
||||||
|
|
||||||
health = tile.block().health;
|
/**Sets this tile entity data to this tile, and adds it if necessary.*/
|
||||||
|
public TileEntity init(Tile tile, boolean added){
|
||||||
timer = new Timer(tile.block().timers);
|
this.tile = tile;
|
||||||
|
x = tile.drawx();
|
||||||
if(added){
|
y = tile.drawy();
|
||||||
add();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Call when nothing is happening to the entity.
|
health = tile.block().health;
|
||||||
* This increments the internal sleep timer.*/
|
|
||||||
public void sleep(){
|
|
||||||
sleepTime += Timers.delta();
|
|
||||||
if(!sleeping && sleepTime >= timeToSleep){
|
|
||||||
remove();
|
|
||||||
sleeping = true;
|
|
||||||
sleepingEntities ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Call when something just happened to the entity.
|
timer = new Timer(tile.block().timers);
|
||||||
* If the entity was sleeping, this enables it. This also resets the sleep timer.*/
|
|
||||||
public void wakeUp(){
|
|
||||||
sleepTime = 0f;
|
|
||||||
if(sleeping){
|
|
||||||
add();
|
|
||||||
sleeping = false;
|
|
||||||
sleepingEntities --;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSleeping(){
|
if(added){
|
||||||
return sleeping;
|
add();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDead() {
|
return this;
|
||||||
return dead;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void write(DataOutputStream stream) throws IOException{}
|
/**
|
||||||
public void read(DataInputStream stream) throws IOException{}
|
* Call when nothing is happening to the entity.
|
||||||
|
* This increments the internal sleep timer.
|
||||||
|
*/
|
||||||
|
public void sleep(){
|
||||||
|
sleepTime += Timers.delta();
|
||||||
|
if(!sleeping && sleepTime >= timeToSleep){
|
||||||
|
remove();
|
||||||
|
sleeping = true;
|
||||||
|
sleepingEntities++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onDeath(){
|
/**
|
||||||
if(!dead) {
|
* Call when something just happened to the entity.
|
||||||
dead = true;
|
* If the entity was sleeping, this enables it. This also resets the sleep timer.
|
||||||
Block block = tile.block();
|
*/
|
||||||
|
public void wakeUp(){
|
||||||
|
sleepTime = 0f;
|
||||||
|
if(sleeping){
|
||||||
|
add();
|
||||||
|
sleeping = false;
|
||||||
|
sleepingEntities--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
block.onDestroyed(tile);
|
public boolean isSleeping(){
|
||||||
world.removeBlock(tile);
|
return sleeping;
|
||||||
block.afterDestroyed(tile, this);
|
}
|
||||||
remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean collide(Bullet other){
|
public boolean isDead(){
|
||||||
return true;
|
return dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collision(Bullet other){
|
|
||||||
tile.block().handleBulletHit(this, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void damage(float damage){
|
|
||||||
if(dead) return;
|
|
||||||
|
|
||||||
CallBlocks.onTileDamage(tile, health - tile.block().handleDamage(tile, damage));
|
public void write(DataOutputStream stream) throws IOException{
|
||||||
|
}
|
||||||
|
|
||||||
if(health <= 0){
|
public void read(DataInputStream stream) throws IOException{
|
||||||
CallBlocks.onTileDestroyed(tile);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Tile getTile(){
|
private void onDeath(){
|
||||||
return tile;
|
if(!dead){
|
||||||
}
|
dead = true;
|
||||||
|
Block block = tile.block();
|
||||||
|
|
||||||
public boolean consumed(Class<? extends Consume> type){
|
block.onDestroyed(tile);
|
||||||
return tile.block().consumes.get(type).valid(tile.block(), this);
|
world.removeBlock(tile);
|
||||||
}
|
block.afterDestroyed(tile, this);
|
||||||
|
remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeFromProximity(){
|
public boolean collide(Bullet other){
|
||||||
GridPoint2[] nearby = Edges.getEdges(tile.block().size);
|
return true;
|
||||||
for (GridPoint2 point : nearby) {
|
}
|
||||||
Tile other = world.tile(tile.x + point.x, tile.y + point.y);
|
|
||||||
//remove this tile from all nearby tile's proximities
|
public void collision(Bullet other){
|
||||||
if(other != null){
|
tile.block().handleBulletHit(this, other);
|
||||||
other = other.target();
|
}
|
||||||
|
|
||||||
|
public void damage(float damage){
|
||||||
|
if(dead) return;
|
||||||
|
|
||||||
|
CallBlocks.onTileDamage(tile, health - tile.block().handleDamage(tile, damage));
|
||||||
|
|
||||||
|
if(health <= 0){
|
||||||
|
CallBlocks.onTileDestroyed(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tile getTile(){
|
||||||
|
return tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean consumed(Class<? extends Consume> type){
|
||||||
|
return tile.block().consumes.get(type).valid(tile.block(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFromProximity(){
|
||||||
|
GridPoint2[] nearby = Edges.getEdges(tile.block().size);
|
||||||
|
for(GridPoint2 point : nearby){
|
||||||
|
Tile other = world.tile(tile.x + point.x, tile.y + point.y);
|
||||||
|
//remove this tile from all nearby tile's proximities
|
||||||
|
if(other != null){
|
||||||
|
other = other.target();
|
||||||
other.block().onProximityUpdate(other);
|
other.block().onProximityUpdate(other);
|
||||||
}
|
}
|
||||||
if(other != null && other.entity != null){
|
if(other != null && other.entity != null){
|
||||||
other.entity.proximity.removeValue(tile, true);
|
other.entity.proximity.removeValue(tile, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateProximity(){
|
public void updateProximity(){
|
||||||
tmpTiles.clear();
|
tmpTiles.clear();
|
||||||
proximity.clear();
|
proximity.clear();
|
||||||
|
|
||||||
GridPoint2[] nearby = Edges.getEdges(tile.block().size);
|
GridPoint2[] nearby = Edges.getEdges(tile.block().size);
|
||||||
for (GridPoint2 point : nearby) {
|
for(GridPoint2 point : nearby){
|
||||||
Tile other = world.tile(tile.x + point.x, tile.y + point.y);
|
Tile other = world.tile(tile.x + point.x, tile.y + point.y);
|
||||||
|
|
||||||
if(other != null){
|
if(other != null){
|
||||||
other.block().onProximityUpdate(other);
|
other.block().onProximityUpdate(other);
|
||||||
other = other.target();
|
other = other.target();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(other != null && other.entity != null){
|
if(other != null && other.entity != null){
|
||||||
tmpTiles.add(other);
|
tmpTiles.add(other);
|
||||||
|
|
||||||
//add this tile to proximity of nearby tiles
|
//add this tile to proximity of nearby tiles
|
||||||
if(!other.entity.proximity.contains(tile, true)){
|
if(!other.entity.proximity.contains(tile, true)){
|
||||||
other.entity.proximity.add(tile);
|
other.entity.proximity.add(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//using a set to prevent duplicates
|
//using a set to prevent duplicates
|
||||||
for(Tile tile : tmpTiles){
|
for(Tile tile : tmpTiles){
|
||||||
proximity.add(tile);
|
proximity.add(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
tile.block().onProximityUpdate(tile);
|
tile.block().onProximityUpdate(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Tile> proximity(){
|
public Array<Tile> proximity(){
|
||||||
return proximity;
|
return proximity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Team getTeam() {
|
public Team getTeam(){
|
||||||
return tile.getTeam();
|
return tile.getTeam();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2 getVelocity() {
|
public Vector2 getVelocity(){
|
||||||
return Vector2.Zero;
|
return Vector2.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
synchronized (Tile.tileSetLock) {
|
synchronized(Tile.tileSetLock){
|
||||||
//TODO better smoke effect, this one is awful
|
//TODO better smoke effect, this one is awful
|
||||||
if (health != 0 && health < tile.block().health && !(tile.block() instanceof Wall) &&
|
if(health != 0 && health < tile.block().health && !(tile.block() instanceof Wall) &&
|
||||||
Mathf.chance(0.009f * Timers.delta() * (1f - health / tile.block().health))) {
|
Mathf.chance(0.009f * Timers.delta() * (1f - health / tile.block().health))){
|
||||||
|
|
||||||
Effects.effect(Fx.smoke, x + Mathf.range(4), y + Mathf.range(4));
|
Effects.effect(Fx.smoke, x + Mathf.range(4), y + Mathf.range(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (health <= 0) {
|
if(health <= 0){
|
||||||
onDeath();
|
onDeath();
|
||||||
}
|
}
|
||||||
|
|
||||||
tile.block().update(tile);
|
tile.block().update(tile);
|
||||||
if(cons != null){
|
if(cons != null){
|
||||||
cons.update(this);
|
cons.update(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityGroup targetGroup() {
|
public EntityGroup targetGroup(){
|
||||||
return tileGroup;
|
return tileGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
|
||||||
public static void onTileDamage(Tile tile, float health){
|
|
||||||
if(tile.entity != null){
|
|
||||||
tile.entity.health = health;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
|
||||||
public static void onTileDestroyed(Tile tile){
|
|
||||||
if(tile.entity == null) return;
|
|
||||||
tile.entity.onDeath();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,13 +31,19 @@ import java.io.IOException;
|
|||||||
import static io.anuke.mindustry.Vars.state;
|
import static io.anuke.mindustry.Vars.state;
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait, CarriableTrait, InventoryTrait {
|
public abstract class Unit extends DestructibleEntity implements SaveTrait, TargetTrait, SyncTrait, DrawTrait, TeamTrait, CarriableTrait, InventoryTrait{
|
||||||
/**total duration of hit flash effect*/
|
/**
|
||||||
|
* total duration of hit flash effect
|
||||||
|
*/
|
||||||
public static final float hitDuration = 9f;
|
public static final float hitDuration = 9f;
|
||||||
/**Percision divisor of velocity, used when writing. For example a value of '2' would mean the percision is 1/2 = 0.5-size chunks.*/
|
/**
|
||||||
|
* Percision divisor of velocity, used when writing. For example a value of '2' would mean the percision is 1/2 = 0.5-size chunks.
|
||||||
|
*/
|
||||||
public static final float velocityPercision = 8f;
|
public static final float velocityPercision = 8f;
|
||||||
/**Maximum absolute value of a velocity vector component.*/
|
/**
|
||||||
public static final float maxAbsVelocity = 127f/velocityPercision;
|
* Maximum absolute value of a velocity vector component.
|
||||||
|
*/
|
||||||
|
public static final float maxAbsVelocity = 127f / velocityPercision;
|
||||||
public static final float elevationScale = 4f;
|
public static final float elevationScale = 4f;
|
||||||
|
|
||||||
private static final Vector2 moveVector = new Vector2();
|
private static final Vector2 moveVector = new Vector2();
|
||||||
@@ -56,28 +62,28 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
protected float elevation;
|
protected float elevation;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnitInventory getInventory() {
|
public UnitInventory getInventory(){
|
||||||
return inventory;
|
return inventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getRotation() {
|
public float getRotation(){
|
||||||
return rotation;
|
return rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRotation(float rotation) {
|
public void setRotation(float rotation){
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCarrier(CarryTrait carrier) {
|
public CarryTrait getCarrier(){
|
||||||
this.carrier = carrier;
|
return carrier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CarryTrait getCarrier() {
|
public void setCarrier(CarryTrait carrier){
|
||||||
return carrier;
|
this.carrier = carrier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -86,7 +92,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void interpolate() {
|
public void interpolate(){
|
||||||
interpolator.update();
|
interpolator.update();
|
||||||
|
|
||||||
x = interpolator.pos.x;
|
x = interpolator.pos.x;
|
||||||
@@ -98,7 +104,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Interpolator getInterpolator() {
|
public Interpolator getInterpolator(){
|
||||||
return interpolator;
|
return interpolator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,31 +121,31 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDeath() {
|
public void onDeath(){
|
||||||
inventory.clear();
|
inventory.clear();
|
||||||
drownTime = 0f;
|
drownTime = 0f;
|
||||||
status.clear();
|
status.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2 getVelocity() {
|
public Vector2 getVelocity(){
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSave(DataOutput stream) throws IOException {
|
public void writeSave(DataOutput stream) throws IOException{
|
||||||
writeSave(stream, false);
|
writeSave(stream, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readSave(DataInput stream) throws IOException {
|
public void readSave(DataInput stream) throws IOException{
|
||||||
byte team = stream.readByte();
|
byte team = stream.readByte();
|
||||||
boolean dead = stream.readBoolean();
|
boolean dead = stream.readBoolean();
|
||||||
float x = stream.readFloat();
|
float x = stream.readFloat();
|
||||||
float y = stream.readFloat();
|
float y = stream.readFloat();
|
||||||
byte xv = stream.readByte();
|
byte xv = stream.readByte();
|
||||||
byte yv = stream.readByte();
|
byte yv = stream.readByte();
|
||||||
float rotation = stream.readShort()/2f;
|
float rotation = stream.readShort() / 2f;
|
||||||
int health = stream.readShort();
|
int health = stream.readShort();
|
||||||
|
|
||||||
this.status.readSave(stream);
|
this.status.readSave(stream);
|
||||||
@@ -153,21 +159,21 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeSave(DataOutput stream, boolean net) throws IOException {
|
public void writeSave(DataOutput stream, boolean net) throws IOException{
|
||||||
stream.writeByte(team.ordinal());
|
stream.writeByte(team.ordinal());
|
||||||
stream.writeBoolean(isDead());
|
stream.writeBoolean(isDead());
|
||||||
stream.writeFloat(net ? interpolator.target.x : x);
|
stream.writeFloat(net ? interpolator.target.x : x);
|
||||||
stream.writeFloat(net ? interpolator.target.y : y);
|
stream.writeFloat(net ? interpolator.target.y : y);
|
||||||
stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
stream.writeByte((byte) (Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
||||||
stream.writeByte((byte)(Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
stream.writeByte((byte) (Mathf.clamp(velocity.y, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
||||||
stream.writeShort((short)(rotation*2));
|
stream.writeShort((short) (rotation * 2));
|
||||||
stream.writeShort((short)health);
|
stream.writeShort((short) health);
|
||||||
status.writeSave(stream);
|
status.writeSave(stream);
|
||||||
inventory.writeSave(stream);
|
inventory.writeSave(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float calculateDamage(float amount){
|
public float calculateDamage(float amount){
|
||||||
return amount * Mathf.clamp(1f-getArmor()/100f*status.getArmorMultiplier());
|
return amount * Mathf.clamp(1f - getArmor() / 100f * status.getArmorMultiplier());
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getDamageMultipler(){
|
public float getDamageMultipler(){
|
||||||
@@ -182,7 +188,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
if(state.teams.has(team)){
|
if(state.teams.has(team)){
|
||||||
TeamData data = state.teams.get(team);
|
TeamData data = state.teams.get(team);
|
||||||
|
|
||||||
Tile tile = Geometry.findClosest(x, y, data.cores);
|
Tile tile = Geometry.findClosest(x, y, data.cores);
|
||||||
if(tile == null){
|
if(tile == null){
|
||||||
return null;
|
return null;
|
||||||
}else{
|
}else{
|
||||||
@@ -200,15 +206,18 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
|
|
||||||
public void avoidOthers(float avoidRange){
|
public void avoidOthers(float avoidRange){
|
||||||
|
|
||||||
EntityPhysics.getNearby(getGroup(), x, y, avoidRange*2f, t -> {
|
EntityPhysics.getNearby(getGroup(), x, y, avoidRange * 2f, t -> {
|
||||||
if(t == this || (t instanceof Unit && (((Unit) t).isDead() || (((Unit) t).isFlying() != isFlying()) || ((Unit) t).getCarrier() == this) || getCarrier() == t)) return;
|
if(t == this || (t instanceof Unit && (((Unit) t).isDead() || (((Unit) t).isFlying() != isFlying()) || ((Unit) t).getCarrier() == this) || getCarrier() == t))
|
||||||
|
return;
|
||||||
float dst = distanceTo(t);
|
float dst = distanceTo(t);
|
||||||
if(dst > avoidRange) return;
|
if(dst > avoidRange) return;
|
||||||
velocity.add(moveVector.set(x, y).sub(t.getX(), t.getY()).setLength(1f * (1f - (dst / avoidRange))));
|
velocity.add(moveVector.set(x, y).sub(t.getX(), t.getY()).setLength(1f * (1f - (dst / avoidRange))));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Updates velocity and status effects.*/
|
/**
|
||||||
|
* Updates velocity and status effects.
|
||||||
|
*/
|
||||||
public void updateVelocityStatus(float drag, float maxVelocity){
|
public void updateVelocityStatus(float drag, float maxVelocity){
|
||||||
if(isCarried()){ //carried units do not take into account velocity normally
|
if(isCarried()){ //carried units do not take into account velocity normally
|
||||||
set(carrier.getX(), carrier.getY());
|
set(carrier.getX(), carrier.getY());
|
||||||
@@ -223,7 +232,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
|
|
||||||
velocity.limit(maxVelocity).scl(status.getSpeedMultiplier());
|
velocity.limit(maxVelocity).scl(status.getSpeedMultiplier());
|
||||||
|
|
||||||
if(isFlying()) {
|
if(isFlying()){
|
||||||
x += velocity.x / getMass() * Timers.delta();
|
x += velocity.x / getMass() * Timers.delta();
|
||||||
y += velocity.y / getMass() * Timers.delta();
|
y += velocity.y / getMass() * Timers.delta();
|
||||||
|
|
||||||
@@ -245,7 +254,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(onLiquid && velocity.len() > 0.4f && Timers.get(this, "flooreffect", 14 - (velocity.len() * floor.speedMultiplier)*2f)){
|
if(onLiquid && velocity.len() > 0.4f && Timers.get(this, "flooreffect", 14 - (velocity.len() * floor.speedMultiplier) * 2f)){
|
||||||
Effects.effect(floor.walkEffect, floor.liquidColor, x, y);
|
Effects.effect(floor.walkEffect, floor.liquidColor, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +265,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(onLiquid && floor.drownTime > 0){
|
if(onLiquid && floor.drownTime > 0){
|
||||||
drownTime += Timers.delta() * 1f/floor.drownTime;
|
drownTime += Timers.delta() * 1f / floor.drownTime;
|
||||||
if(Timers.get(this, "drowneffect", 15)){
|
if(Timers.get(this, "drowneffect", 15)){
|
||||||
Effects.effect(floor.drownUpdateEffect, floor.liquidColor, x, y);
|
Effects.effect(floor.drownUpdateEffect, floor.liquidColor, x, y);
|
||||||
}
|
}
|
||||||
@@ -276,7 +285,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
if(Math.abs(py - y) <= 0.0001f) velocity.y = 0f;
|
if(Math.abs(py - y) <= 0.0001f) velocity.y = 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
velocity.scl(Mathf.clamp(1f-drag* floor.dragMultiplier* Timers.delta()));
|
velocity.scl(Mathf.clamp(1f - drag * floor.dragMultiplier * Timers.delta()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyEffect(StatusEffect effect, float intensity){
|
public void applyEffect(StatusEffect effect, float intensity){
|
||||||
@@ -299,12 +308,17 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
public float getAmmoFraction(){
|
public float getAmmoFraction(){
|
||||||
return inventory.totalAmmo() / (float)inventory.ammoCapacity();
|
return inventory.totalAmmo() / (float) inventory.ammoCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawUnder(){}
|
public void drawUnder(){
|
||||||
public void drawOver(){}
|
}
|
||||||
public void drawShadow(){}
|
|
||||||
|
public void drawOver(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawShadow(){
|
||||||
|
}
|
||||||
|
|
||||||
public void drawView(){
|
public void drawView(){
|
||||||
Fill.circle(x, y, getViewDistance());
|
Fill.circle(x, y, getViewDistance());
|
||||||
@@ -319,12 +333,20 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract TextureRegion getIconRegion();
|
public abstract TextureRegion getIconRegion();
|
||||||
|
|
||||||
public abstract int getItemCapacity();
|
public abstract int getItemCapacity();
|
||||||
|
|
||||||
public abstract int getAmmoCapacity();
|
public abstract int getAmmoCapacity();
|
||||||
|
|
||||||
public abstract float getArmor();
|
public abstract float getArmor();
|
||||||
|
|
||||||
public abstract boolean acceptsAmmo(Item item);
|
public abstract boolean acceptsAmmo(Item item);
|
||||||
|
|
||||||
public abstract void addAmmo(Item item);
|
public abstract void addAmmo(Item item);
|
||||||
|
|
||||||
public abstract float getMass();
|
public abstract float getMass();
|
||||||
|
|
||||||
public abstract boolean isFlying();
|
public abstract boolean isFlying();
|
||||||
|
|
||||||
public abstract float getSize();
|
public abstract float getSize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,17 @@ import io.anuke.mindustry.type.AmmoType;
|
|||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class UnitInventory implements Saveable{
|
public class UnitInventory implements Saveable{
|
||||||
|
private final Unit unit;
|
||||||
private Array<AmmoEntry> ammos = new Array<>();
|
private Array<AmmoEntry> ammos = new Array<>();
|
||||||
private int totalAmmo;
|
private int totalAmmo;
|
||||||
private ItemStack item = new ItemStack(Items.stone, 0);
|
private ItemStack item = new ItemStack(Items.stone, 0);
|
||||||
|
|
||||||
private final Unit unit;
|
public UnitInventory(Unit unit){
|
||||||
|
|
||||||
public UnitInventory(Unit unit) {
|
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,24 +27,24 @@ public class UnitInventory implements Saveable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSave(DataOutput stream) throws IOException {
|
public void writeSave(DataOutput stream) throws IOException{
|
||||||
stream.writeShort(item.amount);
|
stream.writeShort(item.amount);
|
||||||
stream.writeByte(item.item.id);
|
stream.writeByte(item.item.id);
|
||||||
stream.writeShort(totalAmmo);
|
stream.writeShort(totalAmmo);
|
||||||
stream.writeByte(ammos.size);
|
stream.writeByte(ammos.size);
|
||||||
for(int i = 0; i < ammos.size; i ++){
|
for(int i = 0; i < ammos.size; i++){
|
||||||
stream.writeByte(ammos.get(i).type.id);
|
stream.writeByte(ammos.get(i).type.id);
|
||||||
stream.writeShort(ammos.get(i).amount);
|
stream.writeShort(ammos.get(i).amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readSave(DataInput stream) throws IOException {
|
public void readSave(DataInput stream) throws IOException{
|
||||||
short iamount = stream.readShort();
|
short iamount = stream.readShort();
|
||||||
byte iid = stream.readByte();
|
byte iid = stream.readByte();
|
||||||
this.totalAmmo = stream.readShort();
|
this.totalAmmo = stream.readShort();
|
||||||
byte ammoa = stream.readByte();
|
byte ammoa = stream.readByte();
|
||||||
for(int i = 0; i < ammoa; i ++){
|
for(int i = 0; i < ammoa; i++){
|
||||||
byte aid = stream.readByte();
|
byte aid = stream.readByte();
|
||||||
int am = stream.readShort();
|
int am = stream.readShort();
|
||||||
ammos.add(new AmmoEntry(AmmoType.getByID(aid), am));
|
ammos.add(new AmmoEntry(AmmoType.getByID(aid), am));
|
||||||
@@ -53,12 +54,14 @@ public class UnitInventory implements Saveable{
|
|||||||
item.amount = iamount;
|
item.amount = iamount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns ammo range, or MAX_VALUE if this inventory has no ammo.*/
|
/**
|
||||||
|
* Returns ammo range, or MAX_VALUE if this inventory has no ammo.
|
||||||
|
*/
|
||||||
public float getAmmoRange(){
|
public float getAmmoRange(){
|
||||||
return hasAmmo() ? getAmmo().getRange() : Float.MAX_VALUE;
|
return hasAmmo() ? getAmmo().getRange() : Float.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AmmoType getAmmo() {
|
public AmmoType getAmmo(){
|
||||||
return ammos.size == 0 ? null : ammos.peek().type;
|
return ammos.size == 0 ? null : ammos.peek().type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,9 +72,9 @@ public class UnitInventory implements Saveable{
|
|||||||
public void useAmmo(){
|
public void useAmmo(){
|
||||||
if(unit.isInfiniteAmmo()) return;
|
if(unit.isInfiniteAmmo()) return;
|
||||||
AmmoEntry entry = ammos.peek();
|
AmmoEntry entry = ammos.peek();
|
||||||
entry.amount --;
|
entry.amount--;
|
||||||
if(entry.amount == 0) ammos.pop();
|
if(entry.amount == 0) ammos.pop();
|
||||||
totalAmmo --;
|
totalAmmo--;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int totalAmmo(){
|
public int totalAmmo(){
|
||||||
@@ -91,19 +94,19 @@ public class UnitInventory implements Saveable{
|
|||||||
totalAmmo += type.quantityMultiplier;
|
totalAmmo += type.quantityMultiplier;
|
||||||
|
|
||||||
//find ammo entry by type
|
//find ammo entry by type
|
||||||
for(int i = ammos.size - 1; i >= 0; i --){
|
for(int i = ammos.size - 1; i >= 0; i--){
|
||||||
AmmoEntry entry = ammos.get(i);
|
AmmoEntry entry = ammos.get(i);
|
||||||
|
|
||||||
//if found, put it to the right
|
//if found, put it to the right
|
||||||
if(entry.type == type){
|
if(entry.type == type){
|
||||||
entry.amount += type.quantityMultiplier;
|
entry.amount += type.quantityMultiplier;
|
||||||
ammos.swap(i, ammos.size-1);
|
ammos.swap(i, ammos.size - 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//must not be found
|
//must not be found
|
||||||
AmmoEntry entry = new AmmoEntry(type, (int)type.quantityMultiplier);
|
AmmoEntry entry = new AmmoEntry(type, (int) type.quantityMultiplier);
|
||||||
ammos.add(entry);
|
ammos.add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,15 +15,19 @@ import io.anuke.ucore.function.Predicate;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
/**Utility class for unit and team interactions.*/
|
/**
|
||||||
public class Units {
|
* Utility class for unit and team interactions.
|
||||||
|
*/
|
||||||
|
public class Units{
|
||||||
private static Rectangle rect = new Rectangle();
|
private static Rectangle rect = new Rectangle();
|
||||||
private static Rectangle hitrect = new Rectangle();
|
private static Rectangle hitrect = new Rectangle();
|
||||||
private static Unit result;
|
private static Unit result;
|
||||||
private static float cdist;
|
private static float cdist;
|
||||||
private static boolean boolResult;
|
private static boolean boolResult;
|
||||||
|
|
||||||
/**Validates a target.
|
/**
|
||||||
|
* Validates a target.
|
||||||
|
*
|
||||||
* @param target The target to validate
|
* @param target The target to validate
|
||||||
* @param team The team of the thing doing tha targeting
|
* @param team The team of the thing doing tha targeting
|
||||||
* @param x The X position of the thing doign the targeting
|
* @param x The X position of the thing doign the targeting
|
||||||
@@ -31,22 +35,28 @@ public class Units {
|
|||||||
* @param range The maximum distance from the target X/Y the targeter can be for it to be valid
|
* @param range The maximum distance from the target X/Y the targeter can be for it to be valid
|
||||||
* @return whether the target is invalid
|
* @return whether the target is invalid
|
||||||
*/
|
*/
|
||||||
public static boolean invalidateTarget(TargetTrait target, Team team, float x, float y, float range) {
|
public static boolean invalidateTarget(TargetTrait target, Team team, float x, float y, float range){
|
||||||
return target == null || (range != Float.MAX_VALUE && target.distanceTo(x, y) > range) || target.getTeam() == team || !target.isValid();
|
return target == null || (range != Float.MAX_VALUE && target.distanceTo(x, y) > range) || target.getTeam() == team || !target.isValid();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/
|
/**
|
||||||
|
* See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}
|
||||||
|
*/
|
||||||
public static boolean invalidateTarget(TargetTrait target, Team team, float x, float y){
|
public static boolean invalidateTarget(TargetTrait target, Team team, float x, float y){
|
||||||
return invalidateTarget(target, team, x, y, Float.MAX_VALUE);
|
return invalidateTarget(target, team, x, y, Float.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/
|
/**
|
||||||
|
* See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}
|
||||||
|
*/
|
||||||
public static boolean invalidateTarget(TargetTrait target, Unit targeter){
|
public static boolean invalidateTarget(TargetTrait target, Unit targeter){
|
||||||
return invalidateTarget(target, targeter.team, targeter.x, targeter.y, targeter.inventory.getAmmoRange());
|
return invalidateTarget(target, targeter.team, targeter.x, targeter.y, targeter.inventory.getAmmoRange());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns whether there are any entities on this tile.*/
|
/**
|
||||||
|
* Returns whether there are any entities on this tile.
|
||||||
|
*/
|
||||||
public static boolean anyEntities(Tile tile){
|
public static boolean anyEntities(Tile tile){
|
||||||
Block type = tile.block();
|
Block type = tile.block();
|
||||||
rect.setSize(type.size * tilesize, type.size * tilesize);
|
rect.setSize(type.size * tilesize, type.size * tilesize);
|
||||||
@@ -55,11 +65,11 @@ public class Units {
|
|||||||
boolResult = false;
|
boolResult = false;
|
||||||
|
|
||||||
Units.getNearby(rect, unit -> {
|
Units.getNearby(rect, unit -> {
|
||||||
if (boolResult) return;
|
if(boolResult) return;
|
||||||
if (!unit.isFlying()) {
|
if(!unit.isFlying()){
|
||||||
unit.getHitbox(hitrect);
|
unit.getHitbox(hitrect);
|
||||||
|
|
||||||
if (hitrect.overlaps(rect)) {
|
if(hitrect.overlaps(rect)){
|
||||||
boolResult = true;
|
boolResult = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +78,9 @@ public class Units {
|
|||||||
return boolResult;
|
return boolResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns whether there are any entities on this tile, with the hitbox expanded.*/
|
/**
|
||||||
|
* Returns whether there are any entities on this tile, with the hitbox expanded.
|
||||||
|
*/
|
||||||
public static boolean anyEntities(Tile tile, float expansion, Predicate<Unit> pred){
|
public static boolean anyEntities(Tile tile, float expansion, Predicate<Unit> pred){
|
||||||
Block type = tile.block();
|
Block type = tile.block();
|
||||||
rect.setSize(type.size * tilesize + expansion, type.size * tilesize + expansion);
|
rect.setSize(type.size * tilesize + expansion, type.size * tilesize + expansion);
|
||||||
@@ -81,7 +93,7 @@ public class Units {
|
|||||||
if(!unit.isFlying()){
|
if(!unit.isFlying()){
|
||||||
unit.getHitbox(hitrect);
|
unit.getHitbox(hitrect);
|
||||||
|
|
||||||
if(hitrect.overlaps(rect)) {
|
if(hitrect.overlaps(rect)){
|
||||||
value[0] = true;
|
value[0] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,7 +102,9 @@ public class Units {
|
|||||||
return value[0];
|
return value[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns the neareset ally tile in a range.*/
|
/**
|
||||||
|
* Returns the neareset ally tile in a range.
|
||||||
|
*/
|
||||||
public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
|
public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
|
||||||
for(Team enemy : state.teams.alliesOf(team)){
|
for(Team enemy : state.teams.alliesOf(team)){
|
||||||
TileEntity entity = world.indexer().findTile(enemy, x, y, range, pred);
|
TileEntity entity = world.indexer().findTile(enemy, x, y, range, pred);
|
||||||
@@ -101,7 +115,9 @@ public class Units {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns the neareset enemy tile in a range.*/
|
/**
|
||||||
|
* Returns the neareset enemy tile in a range.
|
||||||
|
*/
|
||||||
public static TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
|
public static TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
|
||||||
for(Team enemy : state.teams.enemiesOf(team)){
|
for(Team enemy : state.teams.enemiesOf(team)){
|
||||||
TileEntity entity = world.indexer().findTile(enemy, x, y, range, pred);
|
TileEntity entity = world.indexer().findTile(enemy, x, y, range, pred);
|
||||||
@@ -112,7 +128,9 @@ public class Units {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Iterates over all units on all teams, including players.*/
|
/**
|
||||||
|
* Iterates over all units on all teams, including players.
|
||||||
|
*/
|
||||||
public static void allUnits(Consumer<Unit> cons){
|
public static void allUnits(Consumer<Unit> cons){
|
||||||
//check all unit groups first
|
//check all unit groups first
|
||||||
for(EntityGroup<BaseUnit> group : unitGroups){
|
for(EntityGroup<BaseUnit> group : unitGroups){
|
||||||
@@ -129,7 +147,9 @@ public class Units {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns the closest target enemy. First, units are checked, then tile entities.*/
|
/**
|
||||||
|
* Returns the closest target enemy. First, units are checked, then tile entities.
|
||||||
|
*/
|
||||||
public static TargetTrait getClosestTarget(Team team, float x, float y, float range){
|
public static TargetTrait getClosestTarget(Team team, float x, float y, float range){
|
||||||
Unit unit = getClosestEnemy(team, x, y, range, u -> true);
|
Unit unit = getClosestEnemy(team, x, y, range, u -> true);
|
||||||
if(unit != null){
|
if(unit != null){
|
||||||
@@ -139,20 +159,22 @@ public class Units {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns the closest enemy of this team. Filter by predicate.*/
|
/**
|
||||||
|
* Returns the closest enemy of this team. Filter by predicate.
|
||||||
|
*/
|
||||||
public static Unit getClosestEnemy(Team team, float x, float y, float range, Predicate<Unit> predicate){
|
public static Unit getClosestEnemy(Team team, float x, float y, float range, Predicate<Unit> predicate){
|
||||||
result = null;
|
result = null;
|
||||||
cdist = 0f;
|
cdist = 0f;
|
||||||
|
|
||||||
rect.setSize(range*2f).setCenter(x, y);
|
rect.setSize(range * 2f).setCenter(x, y);
|
||||||
|
|
||||||
getNearbyEnemies(team, rect, e -> {
|
getNearbyEnemies(team, rect, e -> {
|
||||||
if (e.isDead() || !predicate.test(e))
|
if(e.isDead() || !predicate.test(e))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float dist = Vector2.dst(e.x, e.y, x, y);
|
float dist = Vector2.dst(e.x, e.y, x, y);
|
||||||
if (dist < range) {
|
if(dist < range){
|
||||||
if (result == null || dist < cdist) {
|
if(result == null || dist < cdist){
|
||||||
result = e;
|
result = e;
|
||||||
cdist = dist;
|
cdist = dist;
|
||||||
}
|
}
|
||||||
@@ -162,20 +184,22 @@ public class Units {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns the closest ally of this team. Filter by predicate.*/
|
/**
|
||||||
|
* Returns the closest ally of this team. Filter by predicate.
|
||||||
|
*/
|
||||||
public static Unit getClosest(Team team, float x, float y, float range, Predicate<Unit> predicate){
|
public static Unit getClosest(Team team, float x, float y, float range, Predicate<Unit> predicate){
|
||||||
result = null;
|
result = null;
|
||||||
cdist = 0f;
|
cdist = 0f;
|
||||||
|
|
||||||
rect.setSize(range*2f).setCenter(x, y);
|
rect.setSize(range * 2f).setCenter(x, y);
|
||||||
|
|
||||||
getNearby(team, rect, e -> {
|
getNearby(team, rect, e -> {
|
||||||
if (!predicate.test(e))
|
if(!predicate.test(e))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float dist = Vector2.dst(e.x, e.y, x, y);
|
float dist = Vector2.dst(e.x, e.y, x, y);
|
||||||
if (dist < range) {
|
if(dist < range){
|
||||||
if (result == null || dist < cdist) {
|
if(result == null || dist < cdist){
|
||||||
result = e;
|
result = e;
|
||||||
cdist = dist;
|
cdist = dist;
|
||||||
}
|
}
|
||||||
@@ -185,28 +209,32 @@ public class Units {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Iterates over all units in a rectangle.*/
|
/**
|
||||||
|
* Iterates over all units in a rectangle.
|
||||||
|
*/
|
||||||
public static void getNearby(Team team, Rectangle rect, Consumer<Unit> cons){
|
public static void getNearby(Team team, Rectangle rect, Consumer<Unit> cons){
|
||||||
|
|
||||||
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
||||||
if(!group.isEmpty()){
|
if(!group.isEmpty()){
|
||||||
EntityPhysics.getNearby(group, rect, entity -> cons.accept((Unit)entity));
|
EntityPhysics.getNearby(group, rect, entity -> cons.accept((Unit) entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
//now check all players
|
//now check all players
|
||||||
EntityPhysics.getNearby(playerGroup, rect, player -> {
|
EntityPhysics.getNearby(playerGroup, rect, player -> {
|
||||||
if(((Unit)player).team == team) cons.accept((Unit)player);
|
if(((Unit) player).team == team) cons.accept((Unit) player);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Iterates over all units in a circle around this position.*/
|
/**
|
||||||
|
* Iterates over all units in a circle around this position.
|
||||||
|
*/
|
||||||
public static void getNearby(Team team, float x, float y, float radius, Consumer<Unit> cons){
|
public static void getNearby(Team team, float x, float y, float radius, Consumer<Unit> cons){
|
||||||
rect.setSize(radius * 2).setCenter(x, y);
|
rect.setSize(radius * 2).setCenter(x, y);
|
||||||
|
|
||||||
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
||||||
if(!group.isEmpty()){
|
if(!group.isEmpty()){
|
||||||
EntityPhysics.getNearby(group, rect, entity -> {
|
EntityPhysics.getNearby(group, rect, entity -> {
|
||||||
if(entity.distanceTo(x, y) <= radius) {
|
if(entity.distanceTo(x, y) <= radius){
|
||||||
cons.accept((Unit) entity);
|
cons.accept((Unit) entity);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -214,46 +242,52 @@ public class Units {
|
|||||||
|
|
||||||
//now check all players
|
//now check all players
|
||||||
EntityPhysics.getNearby(playerGroup, rect, player -> {
|
EntityPhysics.getNearby(playerGroup, rect, player -> {
|
||||||
if(((Unit)player).team == team && player.distanceTo(x, y) <= radius){
|
if(((Unit) player).team == team && player.distanceTo(x, y) <= radius){
|
||||||
cons.accept((Unit)player);
|
cons.accept((Unit) player);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Iterates over all units in a rectangle.*/
|
/**
|
||||||
|
* Iterates over all units in a rectangle.
|
||||||
|
*/
|
||||||
public static void getNearby(Rectangle rect, Consumer<Unit> cons){
|
public static void getNearby(Rectangle rect, Consumer<Unit> cons){
|
||||||
|
|
||||||
for(Team team : Team.all){
|
for(Team team : Team.all){
|
||||||
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
||||||
if(!group.isEmpty()){
|
if(!group.isEmpty()){
|
||||||
EntityPhysics.getNearby(group, rect, entity -> cons.accept((Unit)entity));
|
EntityPhysics.getNearby(group, rect, entity -> cons.accept((Unit) entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//now check all enemy players
|
//now check all enemy players
|
||||||
EntityPhysics.getNearby(playerGroup, rect, player -> cons.accept((Unit)player));
|
EntityPhysics.getNearby(playerGroup, rect, player -> cons.accept((Unit) player));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Iterates over all units that are enemies of this team.*/
|
/**
|
||||||
|
* Iterates over all units that are enemies of this team.
|
||||||
|
*/
|
||||||
public static void getNearbyEnemies(Team team, Rectangle rect, Consumer<Unit> cons){
|
public static void getNearbyEnemies(Team team, Rectangle rect, Consumer<Unit> cons){
|
||||||
ObjectSet<Team> targets = state.teams.enemiesOf(team);
|
ObjectSet<Team> targets = state.teams.enemiesOf(team);
|
||||||
|
|
||||||
for(Team other : targets){
|
for(Team other : targets){
|
||||||
EntityGroup<BaseUnit> group = unitGroups[other.ordinal()];
|
EntityGroup<BaseUnit> group = unitGroups[other.ordinal()];
|
||||||
if(!group.isEmpty()){
|
if(!group.isEmpty()){
|
||||||
EntityPhysics.getNearby(group, rect, entity -> cons.accept((Unit)entity));
|
EntityPhysics.getNearby(group, rect, entity -> cons.accept((Unit) entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//now check all enemy players
|
//now check all enemy players
|
||||||
EntityPhysics.getNearby(playerGroup, rect, player -> {
|
EntityPhysics.getNearby(playerGroup, rect, player -> {
|
||||||
if(targets.contains(((Player)player).team)){
|
if(targets.contains(((Player) player).team)){
|
||||||
cons.accept((Unit)player);
|
cons.accept((Unit) player);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Iterates over all units.*/
|
/**
|
||||||
|
* Iterates over all units.
|
||||||
|
*/
|
||||||
public static void getAllUnits(Consumer<Unit> cons){
|
public static void getAllUnits(Consumer<Unit> cons){
|
||||||
|
|
||||||
for(Team team : Team.all){
|
for(Team team : Team.all){
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import io.anuke.ucore.core.Effects.Effect;
|
|||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
|
|
||||||
//TODO scale velocity depending on fslope()
|
//TODO scale velocity depending on fslope()
|
||||||
public class ArtilleryBulletType extends BasicBulletType {
|
public class ArtilleryBulletType extends BasicBulletType{
|
||||||
protected Effect trailEffect = BulletFx.artilleryTrail;
|
protected Effect trailEffect = BulletFx.artilleryTrail;
|
||||||
|
|
||||||
public ArtilleryBulletType(float speed, float damage, String bulletSprite) {
|
public ArtilleryBulletType(float speed, float damage, String bulletSprite){
|
||||||
super(speed, damage, bulletSprite);
|
super(speed, damage, bulletSprite);
|
||||||
collidesTiles = false;
|
collidesTiles = false;
|
||||||
collides = false;
|
collides = false;
|
||||||
@@ -17,18 +17,18 @@ public class ArtilleryBulletType extends BasicBulletType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Bullet b) {
|
public void update(Bullet b){
|
||||||
super.update(b);
|
super.update(b);
|
||||||
|
|
||||||
if(b.timer.get(0, 3 + b.fslope()*2f)){
|
if(b.timer.get(0, 3 + b.fslope() * 2f)){
|
||||||
Effects.effect(trailEffect, backColor, b.x, b.y, b.fslope() * 4f);
|
Effects.effect(trailEffect, backColor, b.x, b.y, b.fslope() * 4f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b) {
|
public void draw(Bullet b){
|
||||||
float baseScale = 0.7f;
|
float baseScale = 0.7f;
|
||||||
float scale = (baseScale + b.fslope()*(1f-baseScale));
|
float scale = (baseScale + b.fslope() * (1f - baseScale));
|
||||||
|
|
||||||
float height = bulletHeight * ((1f - bulletShrink) + bulletShrink * b.fout());
|
float height = bulletHeight * ((1f - bulletShrink) + bulletShrink * b.fout());
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ import io.anuke.ucore.graphics.Draw;
|
|||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.Angles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
/**A BulletType for most ammo-based bullets shot from turrets and units.*/
|
/**
|
||||||
public class BasicBulletType extends BulletType {
|
* A BulletType for most ammo-based bullets shot from turrets and units.
|
||||||
|
*/
|
||||||
|
public class BasicBulletType extends BulletType{
|
||||||
public Color backColor = Palette.bulletYellowBack, frontColor = Palette.bulletYellow;
|
public Color backColor = Palette.bulletYellowBack, frontColor = Palette.bulletYellow;
|
||||||
public float bulletWidth = 5f, bulletHeight = 7f;
|
public float bulletWidth = 5f, bulletHeight = 7f;
|
||||||
public float bulletShrink = 0.5f;
|
public float bulletShrink = 0.5f;
|
||||||
@@ -23,7 +25,9 @@ public class BasicBulletType extends BulletType {
|
|||||||
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f;
|
public float fragVelocityMin = 0.2f, fragVelocityMax = 1f;
|
||||||
public BulletType fragBullet = null;
|
public BulletType fragBullet = null;
|
||||||
|
|
||||||
/**Use a negative value to disable splash damage.*/
|
/**
|
||||||
|
* Use a negative value to disable splash damage.
|
||||||
|
*/
|
||||||
public float splashDamageRadius = -1f;
|
public float splashDamageRadius = -1f;
|
||||||
public float splashDamage = 6f;
|
public float splashDamage = 6f;
|
||||||
|
|
||||||
@@ -39,19 +43,19 @@ public class BasicBulletType extends BulletType {
|
|||||||
|
|
||||||
public float hitShake = 0f;
|
public float hitShake = 0f;
|
||||||
|
|
||||||
public BasicBulletType(float speed, float damage, String bulletSprite) {
|
public BasicBulletType(float speed, float damage, String bulletSprite){
|
||||||
super(speed, damage);
|
super(speed, damage);
|
||||||
this.bulletSprite = bulletSprite;
|
this.bulletSprite = bulletSprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load(){
|
||||||
backRegion = Draw.region(bulletSprite + "-back");
|
backRegion = Draw.region(bulletSprite + "-back");
|
||||||
frontRegion = Draw.region(bulletSprite);
|
frontRegion = Draw.region(bulletSprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b) {
|
public void draw(Bullet b){
|
||||||
float height = bulletHeight * ((1f - bulletShrink) + bulletShrink * b.fout());
|
float height = bulletHeight * ((1f - bulletShrink) + bulletShrink * b.fout());
|
||||||
|
|
||||||
Draw.color(backColor);
|
Draw.color(backColor);
|
||||||
@@ -62,7 +66,7 @@ public class BasicBulletType extends BulletType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Bullet b) {
|
public void update(Bullet b){
|
||||||
super.update(b);
|
super.update(b);
|
||||||
|
|
||||||
if(homingPower > 0.0001f){
|
if(homingPower > 0.0001f){
|
||||||
@@ -74,20 +78,20 @@ public class BasicBulletType extends BulletType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hit(Bullet b, float x, float y) {
|
public void hit(Bullet b, float x, float y){
|
||||||
super.hit(b, x, y);
|
super.hit(b, x, y);
|
||||||
|
|
||||||
Effects.shake(hitShake, hitShake, b);
|
Effects.shake(hitShake, hitShake, b);
|
||||||
|
|
||||||
if(fragBullet != null) {
|
if(fragBullet != null){
|
||||||
for (int i = 0; i < fragBullets; i++) {
|
for(int i = 0; i < fragBullets; i++){
|
||||||
float len = Mathf.random(1f, 7f);
|
float len = Mathf.random(1f, 7f);
|
||||||
float a = Mathf.random(360f);
|
float a = Mathf.random(360f);
|
||||||
Bullet.create(fragBullet, b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax));
|
Bullet.create(fragBullet, b, x + Angles.trnsx(a, len), y + Angles.trnsy(a, len), a, Mathf.random(fragVelocityMin, fragVelocityMax));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Mathf.chance(incendChance)) {
|
if(Mathf.chance(incendChance)){
|
||||||
Damage.createIncend(x, y, incendSpread, incendAmount);
|
Damage.createIncend(x, y, incendSpread, incendAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +101,7 @@ public class BasicBulletType extends BulletType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void despawned(Bullet b) {
|
public void despawned(Bullet b){
|
||||||
if(fragBullet != null || splashDamageRadius > 0){
|
if(fragBullet != null || splashDamageRadius > 0){
|
||||||
hit(b);
|
hit(b);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package io.anuke.mindustry.entities.bullet;
|
package io.anuke.mindustry.entities.bullet;
|
||||||
|
|
||||||
public class BombBulletType extends BasicBulletType {
|
public class BombBulletType extends BasicBulletType{
|
||||||
|
|
||||||
public BombBulletType(float damage, float radius, String sprite) {
|
public BombBulletType(float damage, float radius, String sprite){
|
||||||
super(0.7f, 0, sprite);
|
super(0.7f, 0, sprite);
|
||||||
splashDamageRadius = radius;
|
splashDamageRadius = radius;
|
||||||
splashDamage = damage;
|
splashDamage = damage;
|
||||||
|
|||||||
@@ -27,198 +27,199 @@ import static io.anuke.mindustry.Vars.bulletGroup;
|
|||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class Bullet extends BulletEntity<BulletType> implements TeamTrait, SyncTrait{
|
public class Bullet extends BulletEntity<BulletType> implements TeamTrait, SyncTrait{
|
||||||
private static Vector2 vector = new Vector2();
|
private static Vector2 vector = new Vector2();
|
||||||
|
public Timer timer = new Timer(3);
|
||||||
|
private Team team;
|
||||||
|
private Object data;
|
||||||
|
private boolean supressCollision;
|
||||||
|
|
||||||
private Team team;
|
/**
|
||||||
private Object data;
|
* Internal use only!
|
||||||
private boolean supressCollision;
|
*/
|
||||||
|
public Bullet(){
|
||||||
|
}
|
||||||
|
|
||||||
public Timer timer = new Timer(3);
|
public static void create(BulletType type, TeamTrait owner, float x, float y, float angle){
|
||||||
|
create(type, owner, owner.getTeam(), x, y, angle);
|
||||||
|
}
|
||||||
|
|
||||||
public static void create (BulletType type, TeamTrait owner, float x, float y, float angle){
|
public static void create(BulletType type, Entity owner, Team team, float x, float y, float angle){
|
||||||
create(type, owner, owner.getTeam(), x, y, angle);
|
create(type, owner, team, x, y, angle, 1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void create (BulletType type, Entity owner, Team team, float x, float y, float angle){
|
public static void create(BulletType type, Entity owner, Team team, float x, float y, float angle, float velocityScl){
|
||||||
create(type, owner, team, x, y, angle, 1f);
|
create(type, owner, team, x, y, angle, velocityScl, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void create (BulletType type, Entity owner, Team team, float x, float y, float angle, float velocityScl){
|
public static void create(BulletType type, Entity owner, Team team, float x, float y, float angle, float velocityScl, Object data){
|
||||||
create(type, owner, team, x, y, angle, velocityScl, null);
|
Bullet bullet = Pooling.obtain(Bullet.class);
|
||||||
}
|
bullet.type = type;
|
||||||
|
bullet.owner = owner;
|
||||||
|
bullet.data = data;
|
||||||
|
|
||||||
public static void create (BulletType type, Entity owner, Team team, float x, float y, float angle, float velocityScl, Object data){
|
bullet.velocity.set(0, type.speed).setAngle(angle).scl(velocityScl);
|
||||||
Bullet bullet = Pooling.obtain(Bullet.class);
|
if(type.keepVelocity){
|
||||||
bullet.type = type;
|
bullet.velocity.add(owner instanceof VelocityTrait ? ((VelocityTrait) owner).getVelocity() : Vector2.Zero);
|
||||||
bullet.owner = owner;
|
}
|
||||||
bullet.data = data;
|
bullet.hitbox.setSize(type.hitsize);
|
||||||
|
|
||||||
bullet.velocity.set(0, type.speed).setAngle(angle).scl(velocityScl);
|
bullet.team = team;
|
||||||
if(type.keepVelocity){
|
bullet.type = type;
|
||||||
bullet.velocity.add(owner instanceof VelocityTrait ? ((VelocityTrait)owner).getVelocity() : Vector2.Zero);
|
|
||||||
}
|
|
||||||
bullet.hitbox.setSize(type.hitsize);
|
|
||||||
|
|
||||||
bullet.team = team;
|
//translate bullets backwards, purely for visual reasons
|
||||||
bullet.type = type;
|
float backDelta = Timers.delta();
|
||||||
|
|
||||||
//translate bullets backwards, purely for visual reasons
|
bullet.lastPosition().set(x - bullet.velocity.x * backDelta, y - bullet.velocity.y * backDelta, bullet.angle());
|
||||||
float backDelta = Timers.delta();
|
bullet.setLastUpdated(TimeUtils.millis());
|
||||||
|
bullet.setUpdateSpacing((long) ((Timers.delta() / 60f) * 1000));
|
||||||
|
bullet.set(x - bullet.velocity.x * backDelta, y - bullet.velocity.y * backDelta);
|
||||||
|
|
||||||
bullet.lastPosition().set(x-bullet.velocity.x * backDelta, y-bullet.velocity.y * backDelta, bullet.angle());
|
bullet.add();
|
||||||
bullet.setLastUpdated(TimeUtils.millis());
|
}
|
||||||
bullet.setUpdateSpacing((long)((Timers.delta() / 60f) * 1000));
|
|
||||||
bullet.set(x-bullet.velocity.x * backDelta, y-bullet.velocity.y * backDelta);
|
|
||||||
|
|
||||||
bullet.add();
|
public static void create(BulletType type, Bullet parent, float x, float y, float angle){
|
||||||
}
|
create(type, parent.owner, parent.team, x, y, angle);
|
||||||
|
}
|
||||||
|
|
||||||
public static void create(BulletType type, Bullet parent, float x, float y, float angle){
|
public static void create(BulletType type, Bullet parent, float x, float y, float angle, float velocityScl){
|
||||||
create(type, parent.owner, parent.team, x, y, angle);
|
create(type, parent.owner, parent.team, x, y, angle, velocityScl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void create(BulletType type, Bullet parent, float x, float y, float angle, float velocityScl){
|
@Remote(called = Loc.server, in = In.entities)
|
||||||
create(type, parent.owner, parent.team, x, y, angle, velocityScl);
|
public static void createBullet(BulletType type, float x, float y, float angle){
|
||||||
}
|
create(type, null, Team.none, x, y, angle);
|
||||||
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.entities)
|
public boolean collidesTiles(){
|
||||||
public static void createBullet(BulletType type, float x, float y, float angle){
|
return type.collidesTiles;
|
||||||
create(type, null, Team.none, x, y, angle);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**Internal use only!*/
|
public void supressCollision(){
|
||||||
public Bullet(){}
|
supressCollision = true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean collidesTiles(){
|
public void resetOwner(Entity entity, Team team){
|
||||||
return type.collidesTiles;
|
this.owner = entity;
|
||||||
}
|
this.team = team;
|
||||||
|
}
|
||||||
|
|
||||||
public void supressCollision(){
|
public void scaleTime(float add){
|
||||||
supressCollision = true;
|
time += add;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetOwner(Entity entity, Team team){
|
public Object getData(){
|
||||||
this.owner = entity;
|
return data;
|
||||||
this.team = team;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void scaleTime(float add){
|
@Override
|
||||||
time += add;
|
public float getDamage(){
|
||||||
}
|
if(owner instanceof Unit){
|
||||||
|
return super.getDamage() * ((Unit) owner).getDamageMultipler();
|
||||||
|
}
|
||||||
|
|
||||||
public Object getData() {
|
return super.getDamage();
|
||||||
return data;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getDamage(){
|
public boolean isSyncing(){
|
||||||
if(owner instanceof Unit){
|
return type.syncable;
|
||||||
return super.getDamage() * ((Unit) owner).getDamageMultipler();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return super.getDamage();
|
@Override
|
||||||
}
|
public void write(DataOutput data) throws IOException{
|
||||||
|
data.writeFloat(x);
|
||||||
|
data.writeFloat(y);
|
||||||
|
data.writeFloat(velocity.x);
|
||||||
|
data.writeFloat(velocity.y);
|
||||||
|
data.writeByte(team.ordinal());
|
||||||
|
data.writeByte(type.id);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSyncing(){
|
public void read(DataInput data, long time) throws IOException{
|
||||||
return type.syncable;
|
x = data.readFloat();
|
||||||
}
|
y = data.readFloat();
|
||||||
|
velocity.x = data.readFloat();
|
||||||
|
velocity.y = data.readFloat();
|
||||||
|
team = Team.all[data.readByte()];
|
||||||
|
type = BulletType.getByID(data.readByte());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput data) throws IOException {
|
public Team getTeam(){
|
||||||
data.writeFloat(x);
|
return team;
|
||||||
data.writeFloat(y);
|
}
|
||||||
data.writeFloat(velocity.x);
|
|
||||||
data.writeFloat(velocity.y);
|
|
||||||
data.writeByte(team.ordinal());
|
|
||||||
data.writeByte(type.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput data, long time) throws IOException{
|
public void draw(){
|
||||||
x = data.readFloat();
|
type.draw(this);
|
||||||
y = data.readFloat();
|
}
|
||||||
velocity.x = data.readFloat();
|
|
||||||
velocity.y = data.readFloat();
|
|
||||||
team = Team.all[data.readByte()];
|
|
||||||
type = BulletType.getByID(data.readByte());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Team getTeam() {
|
public float drawSize(){
|
||||||
return team;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public boolean collides(SolidTrait other){
|
||||||
type.draw(this);
|
return type.collides && super.collides(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float drawSize(){
|
public void collision(SolidTrait other, float x, float y){
|
||||||
return 8;
|
super.collision(other, x, y);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if(other instanceof Unit){
|
||||||
public boolean collides(SolidTrait other){
|
Unit unit = (Unit) other;
|
||||||
return type.collides && super.collides(other);
|
unit.getVelocity().add(vector.set(other.getX(), other.getY()).sub(x, y).setLength(type.knockback / unit.getMass()));
|
||||||
}
|
unit.applyEffect(type.status, type.statusIntensity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collision(SolidTrait other, float x, float y){
|
public void update(){
|
||||||
super.collision(other, x, y);
|
super.update();
|
||||||
|
|
||||||
if(other instanceof Unit){
|
if(type.hitTiles && collidesTiles() && !supressCollision){
|
||||||
Unit unit = (Unit)other;
|
world.raycastEach(world.toTile(lastPosition().x), world.toTile(lastPosition().y), world.toTile(x), world.toTile(y), (x, y) -> {
|
||||||
unit.getVelocity().add(vector.set(other.getX(), other.getY()).sub(x, y).setLength(type.knockback / unit.getMass()));
|
|
||||||
unit.applyEffect(type.status, type.statusIntensity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
Tile tile = world.tile(x, y);
|
||||||
public void update(){
|
if(tile == null) return false;
|
||||||
super.update();
|
tile = tile.target();
|
||||||
|
|
||||||
if (type.hitTiles && collidesTiles() && !supressCollision) {
|
if(tile.entity != null && tile.entity.collide(this) && !tile.entity.isDead() && tile.entity.tile.getTeam() != team){
|
||||||
world.raycastEach(world.toTile(lastPosition().x), world.toTile(lastPosition().y), world.toTile(x), world.toTile(y), (x, y) -> {
|
tile.entity.collision(this);
|
||||||
|
|
||||||
Tile tile = world.tile(x, y);
|
if(!supressCollision){
|
||||||
if (tile == null) return false;
|
type.hit(this);
|
||||||
tile = tile.target();
|
remove();
|
||||||
|
}
|
||||||
|
|
||||||
if (tile.entity != null && tile.entity.collide(this) && !tile.entity.isDead() && tile.entity.tile.getTeam() != team) {
|
return true;
|
||||||
tile.entity.collision(this);
|
}
|
||||||
|
|
||||||
if(!supressCollision){
|
return false;
|
||||||
type.hit(this);
|
});
|
||||||
remove();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
supressCollision = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
@Override
|
||||||
});
|
public void reset(){
|
||||||
}
|
super.reset();
|
||||||
|
timer.clear();
|
||||||
|
team = null;
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
|
||||||
supressCollision = false;
|
@Override
|
||||||
}
|
public void removed(){
|
||||||
|
Pooling.free(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public EntityGroup targetGroup(){
|
||||||
super.reset();
|
return bulletGroup;
|
||||||
timer.clear();
|
}
|
||||||
team = null;
|
|
||||||
data = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removed() {
|
|
||||||
Pooling.free(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EntityGroup targetGroup() {
|
|
||||||
return bulletGroup;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,65 +9,83 @@ import io.anuke.ucore.core.Effects;
|
|||||||
import io.anuke.ucore.entities.impl.BaseBulletType;
|
import io.anuke.ucore.entities.impl.BaseBulletType;
|
||||||
|
|
||||||
public abstract class BulletType extends BaseBulletType<Bullet> implements Content{
|
public abstract class BulletType extends BaseBulletType<Bullet> implements Content{
|
||||||
private static int lastid = 0;
|
private static int lastid = 0;
|
||||||
private static Array<BulletType> types = new Array<>();
|
private static Array<BulletType> types = new Array<>();
|
||||||
|
|
||||||
public final int id;
|
public final int id;
|
||||||
/**Knockback in velocity.*/
|
/**
|
||||||
public float knockback;
|
* Knockback in velocity.
|
||||||
/**Whether this bullet hits tiles.*/
|
*/
|
||||||
public boolean hitTiles = true;
|
public float knockback;
|
||||||
/**Status effect applied on hit.*/
|
/**
|
||||||
public StatusEffect status = StatusEffects.none;
|
* Whether this bullet hits tiles.
|
||||||
/**Intensity of applied status effect in terms of duration.*/
|
*/
|
||||||
public float statusIntensity = 0.5f;
|
public boolean hitTiles = true;
|
||||||
/**What fraction of armor is pierced, 0-1*/
|
/**
|
||||||
public float armorPierce = 0f;
|
* Status effect applied on hit.
|
||||||
/**Whether to sync this bullet to clients.*/
|
*/
|
||||||
public boolean syncable;
|
public StatusEffect status = StatusEffects.none;
|
||||||
/**Whether this bullet type collides with tiles.*/
|
/**
|
||||||
public boolean collidesTiles = true;
|
* Intensity of applied status effect in terms of duration.
|
||||||
/**Whether this bullet types collides with anything at all.*/
|
*/
|
||||||
public boolean collides = true;
|
public float statusIntensity = 0.5f;
|
||||||
/**Whether velocity is inherited from the shooter.*/
|
/**
|
||||||
public boolean keepVelocity = true;
|
* What fraction of armor is pierced, 0-1
|
||||||
|
*/
|
||||||
|
public float armorPierce = 0f;
|
||||||
|
/**
|
||||||
|
* Whether to sync this bullet to clients.
|
||||||
|
*/
|
||||||
|
public boolean syncable;
|
||||||
|
/**
|
||||||
|
* Whether this bullet type collides with tiles.
|
||||||
|
*/
|
||||||
|
public boolean collidesTiles = true;
|
||||||
|
/**
|
||||||
|
* Whether this bullet types collides with anything at all.
|
||||||
|
*/
|
||||||
|
public boolean collides = true;
|
||||||
|
/**
|
||||||
|
* Whether velocity is inherited from the shooter.
|
||||||
|
*/
|
||||||
|
public boolean keepVelocity = true;
|
||||||
|
|
||||||
public BulletType(float speed, float damage){
|
public BulletType(float speed, float damage){
|
||||||
this.id = lastid ++;
|
this.id = lastid++;
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
this.damage = damage;
|
this.damage = damage;
|
||||||
lifetime = 40f;
|
lifetime = 40f;
|
||||||
hiteffect = BulletFx.hitBulletSmall;
|
hiteffect = BulletFx.hitBulletSmall;
|
||||||
despawneffect = BulletFx.despawn;
|
despawneffect = BulletFx.despawn;
|
||||||
|
|
||||||
types.add(this);
|
types.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void hit(Bullet b, float hitx, float hity){
|
|
||||||
Effects.effect(hiteffect, hitx, hity, b.angle());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public static BulletType getByID(int id){
|
||||||
public void despawned(Bullet b){
|
return types.get(id);
|
||||||
Effects.effect(despawneffect, b.x, b.y, b.angle());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public static Array<BulletType> all(){
|
||||||
public String getContentTypeName() {
|
return types;
|
||||||
return "bullettype";
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Array<? extends Content> getAll() {
|
public void hit(Bullet b, float hitx, float hity){
|
||||||
return types;
|
Effects.effect(hiteffect, hitx, hity, b.angle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BulletType getByID(int id){
|
@Override
|
||||||
return types.get(id);
|
public void despawned(Bullet b){
|
||||||
}
|
Effects.effect(despawneffect, b.x, b.y, b.angle());
|
||||||
|
}
|
||||||
|
|
||||||
public static Array<BulletType> all(){
|
@Override
|
||||||
return types;
|
public String getContentTypeName(){
|
||||||
}
|
return "bullettype";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Array<? extends Content> getAll(){
|
||||||
|
return types;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ import io.anuke.ucore.util.Mathf;
|
|||||||
import static io.anuke.mindustry.Vars.tilesize;
|
import static io.anuke.mindustry.Vars.tilesize;
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class LiquidBulletType extends BulletType {
|
public class LiquidBulletType extends BulletType{
|
||||||
Liquid liquid;
|
Liquid liquid;
|
||||||
|
|
||||||
public LiquidBulletType(Liquid liquid) {
|
public LiquidBulletType(Liquid liquid){
|
||||||
super(2.5f, 0);
|
super(2.5f, 0);
|
||||||
this.liquid = liquid;
|
this.liquid = liquid;
|
||||||
|
|
||||||
@@ -31,14 +31,14 @@ public class LiquidBulletType extends BulletType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Bullet b) {
|
public void draw(Bullet b){
|
||||||
Draw.color(liquid.color, Color.WHITE, b.fout() / 100f + Mathf.randomSeedRange(b.id, 0.1f));
|
Draw.color(liquid.color, Color.WHITE, b.fout() / 100f + Mathf.randomSeedRange(b.id, 0.1f));
|
||||||
|
|
||||||
Fill.circle(b.x, b.y, 0.5f + b.fout()*2.5f);
|
Fill.circle(b.x, b.y, 0.5f + b.fout() * 2.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hit(Bullet b, float hitx, float hity) {
|
public void hit(Bullet b, float hitx, float hity){
|
||||||
Effects.effect(hiteffect, liquid.color, hitx, hity);
|
Effects.effect(hiteffect, liquid.color, hitx, hity);
|
||||||
Puddle.deposit(world.tileWorld(hitx, hity), liquid, 5f);
|
Puddle.deposit(world.tileWorld(hitx, hity), liquid, 5f);
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ public class LiquidBulletType extends BulletType {
|
|||||||
float intensity = 400f;
|
float intensity = 400f;
|
||||||
Fire.extinguish(world.tileWorld(hitx, hity), intensity);
|
Fire.extinguish(world.tileWorld(hitx, hity), intensity);
|
||||||
for(GridPoint2 p : Geometry.d4){
|
for(GridPoint2 p : Geometry.d4){
|
||||||
Fire.extinguish(world.tileWorld(hitx + p.x*tilesize, hity + p.y*tilesize), intensity);
|
Fire.extinguish(world.tileWorld(hitx + p.x * tilesize, hity + p.y * tilesize), intensity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import io.anuke.mindustry.content.fx.BulletFx;
|
|||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.ucore.core.Effects;
|
import io.anuke.ucore.core.Effects;
|
||||||
|
|
||||||
public class MissileBulletType extends BasicBulletType {
|
public class MissileBulletType extends BasicBulletType{
|
||||||
|
|
||||||
public MissileBulletType(float speed, float damage, String bulletSprite) {
|
public MissileBulletType(float speed, float damage, String bulletSprite){
|
||||||
super(speed, damage, bulletSprite);
|
super(speed, damage, bulletSprite);
|
||||||
backColor = Palette.missileYellowBack;
|
backColor = Palette.missileYellowBack;
|
||||||
frontColor = Palette.missileYellow;
|
frontColor = Palette.missileYellow;
|
||||||
@@ -14,7 +14,7 @@ public class MissileBulletType extends BasicBulletType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Bullet b) {
|
public void update(Bullet b){
|
||||||
super.update(b);
|
super.update(b);
|
||||||
|
|
||||||
if(b.timer.get(0, 4f)){
|
if(b.timer.get(0, 4f)){
|
||||||
|
|||||||
@@ -10,24 +10,26 @@ import io.anuke.ucore.util.Mathf;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.groundEffectGroup;
|
import static io.anuke.mindustry.Vars.groundEffectGroup;
|
||||||
|
|
||||||
/**Class for creating block rubble on the ground.*/
|
/**
|
||||||
public abstract class Decal extends TimedEntity implements BelowLiquidTrait, DrawTrait {
|
* Class for creating block rubble on the ground.
|
||||||
|
*/
|
||||||
|
public abstract class Decal extends TimedEntity implements BelowLiquidTrait, DrawTrait{
|
||||||
private static final Color color = Color.valueOf("52504e");
|
private static final Color color = Color.valueOf("52504e");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float lifetime() {
|
public float lifetime(){
|
||||||
return 8200f;
|
return 8200f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
Draw.color(color.r, color.g, color.b, 1f-Mathf.curve(fin(), 0.98f));
|
Draw.color(color.r, color.g, color.b, 1f - Mathf.curve(fin(), 0.98f));
|
||||||
drawDecal();
|
drawDecal();
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityGroup targetGroup() {
|
public EntityGroup targetGroup(){
|
||||||
return groundEffectGroup;
|
return groundEffectGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable {
|
public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
||||||
private static final IntMap<Fire> map = new IntMap<>();
|
private static final IntMap<Fire> map = new IntMap<>();
|
||||||
private static final float baseLifetime = 1000f;
|
private static final float baseLifetime = 1000f;
|
||||||
|
|
||||||
@@ -41,7 +41,15 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
private float baseFlammability = -1, puddleFlammability;
|
private float baseFlammability = -1, puddleFlammability;
|
||||||
private float lifetime;
|
private float lifetime;
|
||||||
|
|
||||||
/**Start a fire on the tile. If there already is a file there, refreshes its lifetime.*/
|
/**
|
||||||
|
* Deserialization use only!
|
||||||
|
*/
|
||||||
|
public Fire(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a fire on the tile. If there already is a file there, refreshes its lifetime.
|
||||||
|
*/
|
||||||
public static void create(Tile tile){
|
public static void create(Tile tile){
|
||||||
if(Net.client() || tile == null) return; //not clientside.
|
if(Net.client() || tile == null) return; //not clientside.
|
||||||
|
|
||||||
@@ -60,24 +68,28 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing.*/
|
/**
|
||||||
public static void extinguish(Tile tile, float intensity) {
|
* Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing.
|
||||||
if (tile != null && map.containsKey(tile.packedPosition())) {
|
*/
|
||||||
|
public static void extinguish(Tile tile, float intensity){
|
||||||
|
if(tile != null && map.containsKey(tile.packedPosition())){
|
||||||
map.get(tile.packedPosition()).time += intensity * Timers.delta();
|
map.get(tile.packedPosition()).time += intensity * Timers.delta();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Deserialization use only!*/
|
@Remote(called = Loc.server, in = In.entities)
|
||||||
public Fire(){}
|
public static void onFireRemoved(int fireid){
|
||||||
|
fireGroup.removeByID(fireid);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float lifetime() {
|
public float lifetime(){
|
||||||
return lifetime;
|
return lifetime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update(){
|
||||||
if(Mathf.chance(0.1 * Timers.delta())) {
|
if(Mathf.chance(0.1 * Timers.delta())){
|
||||||
Effects.effect(EnvironmentFx.fire, x + Mathf.range(4f), y + Mathf.range(4f));
|
Effects.effect(EnvironmentFx.fire, x + Mathf.range(4f), y + Mathf.range(4f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,19 +115,19 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
float flammability = baseFlammability + puddleFlammability;
|
float flammability = baseFlammability + puddleFlammability;
|
||||||
|
|
||||||
if(!damage && flammability <= 0){
|
if(!damage && flammability <= 0){
|
||||||
time += Timers.delta()*8;
|
time += Timers.delta() * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baseFlammability < 0 || block != tile.block()){
|
if(baseFlammability < 0 || block != tile.block()){
|
||||||
baseFlammability = tile.block().getFlammability(tile);
|
baseFlammability = tile.block().getFlammability(tile);
|
||||||
block = tile.block();
|
block = tile.block();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(damage) {
|
if(damage){
|
||||||
lifetime += Mathf.clamp(flammability / 8f, 0f, 0.6f) * Timers.delta();
|
lifetime += Mathf.clamp(flammability / 8f, 0f, 0.6f) * Timers.delta();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flammability > 1f && Mathf.chance(0.03 * Timers.delta() * Mathf.clamp(flammability/5f, 0.3f, 2f))) {
|
if(flammability > 1f && Mathf.chance(0.03 * Timers.delta() * Mathf.clamp(flammability / 5f, 0.3f, 2f))){
|
||||||
GridPoint2 p = Mathf.select(Geometry.d4);
|
GridPoint2 p = Mathf.select(Geometry.d4);
|
||||||
Tile other = world.tile(tile.x + p.x, tile.y + p.y);
|
Tile other = world.tile(tile.x + p.x, tile.y + p.y);
|
||||||
create(other);
|
create(other);
|
||||||
@@ -128,7 +140,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
if(Mathf.chance(0.1 * Timers.delta())){
|
if(Mathf.chance(0.1 * Timers.delta())){
|
||||||
Puddle p = Puddle.getPuddle(tile);
|
Puddle p = Puddle.getPuddle(tile);
|
||||||
if(p != null){
|
if(p != null){
|
||||||
puddleFlammability = p.getFlammability()/3f;
|
puddleFlammability = p.getFlammability() / 3f;
|
||||||
}else{
|
}else{
|
||||||
puddleFlammability = 0;
|
puddleFlammability = 0;
|
||||||
}
|
}
|
||||||
@@ -141,14 +153,14 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSave(DataOutput stream) throws IOException {
|
public void writeSave(DataOutput stream) throws IOException{
|
||||||
stream.writeInt(tile.packedPosition());
|
stream.writeInt(tile.packedPosition());
|
||||||
stream.writeFloat(lifetime);
|
stream.writeFloat(lifetime);
|
||||||
stream.writeFloat(time);
|
stream.writeFloat(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readSave(DataInput stream) throws IOException {
|
public void readSave(DataInput stream) throws IOException{
|
||||||
this.loadedPosition = stream.readInt();
|
this.loadedPosition = stream.readInt();
|
||||||
this.lifetime = stream.readFloat();
|
this.lifetime = stream.readFloat();
|
||||||
this.time = stream.readFloat();
|
this.time = stream.readFloat();
|
||||||
@@ -156,19 +168,19 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput data) throws IOException {
|
public void write(DataOutput data) throws IOException{
|
||||||
data.writeFloat(x);
|
data.writeFloat(x);
|
||||||
data.writeFloat(y);
|
data.writeFloat(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput data, long time) throws IOException {
|
public void read(DataInput data, long time) throws IOException{
|
||||||
x = data.readFloat();
|
x = data.readFloat();
|
||||||
y = data.readFloat();
|
y = data.readFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset(){
|
||||||
loadedPosition = -1;
|
loadedPosition = -1;
|
||||||
tile = null;
|
tile = null;
|
||||||
baseFlammability = -1;
|
baseFlammability = -1;
|
||||||
@@ -176,7 +188,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void added() {
|
public void added(){
|
||||||
if(loadedPosition != -1){
|
if(loadedPosition != -1){
|
||||||
map.put(loadedPosition, this);
|
map.put(loadedPosition, this);
|
||||||
tile = world.tile(loadedPosition);
|
tile = world.tile(loadedPosition);
|
||||||
@@ -185,7 +197,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removed() {
|
public void removed(){
|
||||||
if(tile != null){
|
if(tile != null){
|
||||||
map.remove(tile.packedPosition());
|
map.remove(tile.packedPosition());
|
||||||
}
|
}
|
||||||
@@ -193,12 +205,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityGroup targetGroup() {
|
public EntityGroup targetGroup(){
|
||||||
return fireGroup;
|
return fireGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.entities)
|
|
||||||
public static void onFireRemoved(int fireid){
|
|
||||||
fireGroup.removeByID(fireid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,27 +9,29 @@ import io.anuke.ucore.entities.impl.EffectEntity;
|
|||||||
import io.anuke.ucore.function.EffectRenderer;
|
import io.anuke.ucore.function.EffectRenderer;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
/**A ground effect contains an effect that is rendered on the ground layer as opposed to the top layer.*/
|
/**
|
||||||
public class GroundEffectEntity extends EffectEntity {
|
* A ground effect contains an effect that is rendered on the ground layer as opposed to the top layer.
|
||||||
|
*/
|
||||||
|
public class GroundEffectEntity extends EffectEntity{
|
||||||
private boolean once;
|
private boolean once;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(){
|
public void update(){
|
||||||
GroundEffect effect = (GroundEffect)this.effect;
|
GroundEffect effect = (GroundEffect) this.effect;
|
||||||
|
|
||||||
if(effect.isStatic) {
|
if(effect.isStatic){
|
||||||
time += Timers.delta();
|
time += Timers.delta();
|
||||||
|
|
||||||
time = Mathf.clamp(time, 0, effect.staticLife);
|
time = Mathf.clamp(time, 0, effect.staticLife);
|
||||||
|
|
||||||
if (!once && time >= lifetime()) {
|
if(!once && time >= lifetime()){
|
||||||
once = true;
|
once = true;
|
||||||
time = 0f;
|
time = 0f;
|
||||||
Tile tile = Vars.world.tileWorld(x, y);
|
Tile tile = Vars.world.tileWorld(x, y);
|
||||||
if(tile != null && tile.floor().isLiquid){
|
if(tile != null && tile.floor().isLiquid){
|
||||||
remove();
|
remove();
|
||||||
}
|
}
|
||||||
} else if (once && time >= effect.staticLife) {
|
}else if(once && time >= effect.staticLife){
|
||||||
remove();
|
remove();
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -39,7 +41,7 @@ public class GroundEffectEntity extends EffectEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
GroundEffect effect = (GroundEffect)this.effect;
|
GroundEffect effect = (GroundEffect) this.effect;
|
||||||
|
|
||||||
if(once && effect.isStatic)
|
if(once && effect.isStatic)
|
||||||
Effects.renderEffect(id, effect, color, lifetime(), rotation, x, y, data);
|
Effects.renderEffect(id, effect, color, lifetime(), rotation, x, y, data);
|
||||||
@@ -48,32 +50,38 @@ public class GroundEffectEntity extends EffectEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset(){
|
||||||
super.reset();
|
super.reset();
|
||||||
once = false;
|
once = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**An effect that is rendered on the ground layer as opposed to the top layer.*/
|
/**
|
||||||
|
* An effect that is rendered on the ground layer as opposed to the top layer.
|
||||||
|
*/
|
||||||
public static class GroundEffect extends Effect{
|
public static class GroundEffect extends Effect{
|
||||||
/**How long this effect stays on the ground when static.*/
|
/**
|
||||||
|
* How long this effect stays on the ground when static.
|
||||||
|
*/
|
||||||
public final float staticLife;
|
public final float staticLife;
|
||||||
/**If true, this effect will stop and lie on the ground for a specific duration,
|
/**
|
||||||
* after its initial lifetime is over.*/
|
* If true, this effect will stop and lie on the ground for a specific duration,
|
||||||
|
* after its initial lifetime is over.
|
||||||
|
*/
|
||||||
public final boolean isStatic;
|
public final boolean isStatic;
|
||||||
|
|
||||||
public GroundEffect(float life, float staticLife, EffectRenderer draw) {
|
public GroundEffect(float life, float staticLife, EffectRenderer draw){
|
||||||
super(life, draw);
|
super(life, draw);
|
||||||
this.staticLife = staticLife;
|
this.staticLife = staticLife;
|
||||||
this.isStatic = true;
|
this.isStatic = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroundEffect(boolean isStatic, float life, EffectRenderer draw) {
|
public GroundEffect(boolean isStatic, float life, EffectRenderer draw){
|
||||||
super(life, draw);
|
super(life, draw);
|
||||||
this.staticLife = 0f;
|
this.staticLife = 0f;
|
||||||
this.isStatic = isStatic;
|
this.isStatic = isStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroundEffect(float life, EffectRenderer draw) {
|
public GroundEffect(float life, EffectRenderer draw){
|
||||||
super(life, draw);
|
super(life, draw);
|
||||||
this.staticLife = 0f;
|
this.staticLife = 0f;
|
||||||
this.isStatic = false;
|
this.isStatic = false;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawTrait, VelocityTrait, TimeTrait, TargetTrait, Poolable {
|
public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawTrait, VelocityTrait, TimeTrait, TargetTrait, Poolable{
|
||||||
private static final float sinkLifetime = 80f;
|
private static final float sinkLifetime = 80f;
|
||||||
|
|
||||||
private Interpolator interpolator = new Interpolator();
|
private Interpolator interpolator = new Interpolator();
|
||||||
@@ -46,6 +46,14 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
|||||||
private float time;
|
private float time;
|
||||||
private float sinktime;
|
private float sinktime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal use only!
|
||||||
|
*/
|
||||||
|
public ItemDrop(){
|
||||||
|
hitbox.setSize(5f);
|
||||||
|
hitboxTile.setSize(5f);
|
||||||
|
}
|
||||||
|
|
||||||
public static ItemDrop create(Item item, int amount, float x, float y, float angle){
|
public static ItemDrop create(Item item, int amount, float x, float y, float angle){
|
||||||
ItemDrop drop = new ItemDrop();
|
ItemDrop drop = new ItemDrop();
|
||||||
drop.item = item;
|
drop.item = item;
|
||||||
@@ -73,13 +81,7 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Internal use only!*/
|
public Item getItem(){
|
||||||
public ItemDrop(){
|
|
||||||
hitbox.setSize(5f);
|
|
||||||
hitboxTile.setSize(5f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Item getItem() {
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,66 +90,66 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDead() {
|
public boolean isDead(){
|
||||||
return !isAdded();
|
return !isAdded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Team getTeam() {
|
public Team getTeam(){
|
||||||
return Team.none;
|
return Team.none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float lifetime() {
|
public float lifetime(){
|
||||||
return 60*60;
|
return 60 * 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void time(float time) {
|
public void time(float time){
|
||||||
this.time = time;
|
this.time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float time() {
|
public float time(){
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Vector2 getVelocity() {
|
public Vector2 getVelocity(){
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean collides(SolidTrait other) {
|
public boolean collides(SolidTrait other){
|
||||||
return other instanceof Player && time > 20f;
|
return other instanceof Player && time > 20f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void collision(SolidTrait other, float x, float y) {
|
public void collision(SolidTrait other, float x, float y){
|
||||||
Unit player = (Unit)other;
|
Unit player = (Unit) other;
|
||||||
if(player.inventory.canAcceptItem(item, 1)){
|
if(player.inventory.canAcceptItem(item, 1)){
|
||||||
int used = Math.min(amount, player.inventory.capacity() - player.inventory.getItem().amount);
|
int used = Math.min(amount, player.inventory.capacity() - player.inventory.getItem().amount);
|
||||||
player.inventory.addItem(item, used);
|
player.inventory.addItem(item, used);
|
||||||
amount -= used;
|
amount -= used;
|
||||||
|
|
||||||
if(amount <= 0) {
|
if(amount <= 0){
|
||||||
CallEntity.onPickup(getID());
|
CallEntity.onPickup(getID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw() {
|
public void draw(){
|
||||||
float size = itemSize * (1f - sinktime/sinkLifetime) * (1f-Mathf.curve(fin(), 0.98f));
|
float size = itemSize * (1f - sinktime / sinkLifetime) * (1f - Mathf.curve(fin(), 0.98f));
|
||||||
|
|
||||||
Tile tile = world.tileWorld(x, y);
|
Tile tile = world.tileWorld(x, y);
|
||||||
|
|
||||||
Draw.color(Color.WHITE, tile == null || !tile.floor().isLiquid ? Color.WHITE : tile.floor().liquidColor, sinktime/sinkLifetime);
|
Draw.color(Color.WHITE, tile == null || !tile.floor().isLiquid ? Color.WHITE : tile.floor().liquidColor, sinktime / sinkLifetime);
|
||||||
Draw.rect(item.region, x, y, size, size);
|
Draw.rect(item.region, x, y, size, size);
|
||||||
|
|
||||||
int stored = Mathf.clamp(amount / 6, 1, 8);
|
int stored = Mathf.clamp(amount / 6, 1, 8);
|
||||||
|
|
||||||
for(int i = 0; i < stored; i ++) {
|
for(int i = 0; i < stored; i++){
|
||||||
float px = stored == 1 ? 0 : Mathf.randomSeedRange(i + 1, 4f);
|
float px = stored == 1 ? 0 : Mathf.randomSeedRange(i + 1, 4f);
|
||||||
float py = stored == 1 ? 0 : Mathf.randomSeedRange(i + 2, 4f);
|
float py = stored == 1 ? 0 : Mathf.randomSeedRange(i + 2, 4f);
|
||||||
Draw.rect(item.region, x + px, y + py, size, size);
|
Draw.rect(item.region, x + px, y + py, size, size);
|
||||||
@@ -157,8 +159,8 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update(){
|
||||||
if(Net.client()) {
|
if(Net.client()){
|
||||||
interpolate();
|
interpolate();
|
||||||
}else{
|
}else{
|
||||||
updateVelocity(0.2f);
|
updateVelocity(0.2f);
|
||||||
@@ -190,28 +192,28 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset(){
|
||||||
time = 0f;
|
time = 0f;
|
||||||
interpolator.reset();
|
interpolator.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Interpolator getInterpolator() {
|
public Interpolator getInterpolator(){
|
||||||
return interpolator;
|
return interpolator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float drawSize() {
|
public float drawSize(){
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityGroup targetGroup() {
|
public EntityGroup targetGroup(){
|
||||||
return itemGroup;
|
return itemGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSave(DataOutput data) throws IOException {
|
public void writeSave(DataOutput data) throws IOException{
|
||||||
data.writeFloat(x);
|
data.writeFloat(x);
|
||||||
data.writeFloat(y);
|
data.writeFloat(y);
|
||||||
data.writeByte(item.id);
|
data.writeByte(item.id);
|
||||||
@@ -219,7 +221,7 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readSave(DataInput data) throws IOException {
|
public void readSave(DataInput data) throws IOException{
|
||||||
x = data.readFloat();
|
x = data.readFloat();
|
||||||
y = data.readFloat();
|
y = data.readFloat();
|
||||||
item = Item.getByID(data.readByte());
|
item = Item.getByID(data.readByte());
|
||||||
|
|||||||
@@ -32,17 +32,22 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{
|
|||||||
private PosTrait to;
|
private PosTrait to;
|
||||||
private Runnable done;
|
private Runnable done;
|
||||||
|
|
||||||
|
public ItemTransfer(){
|
||||||
|
}
|
||||||
|
|
||||||
@Remote(in = In.entities, called = Loc.server, unreliable = true)
|
@Remote(in = In.entities, called = Loc.server, unreliable = true)
|
||||||
public static void transferAmmo(Item item, float x, float y, Unit to){
|
public static void transferAmmo(Item item, float x, float y, Unit to){
|
||||||
if(to == null) return;
|
if(to == null) return;
|
||||||
to.addAmmo(item);
|
to.addAmmo(item);
|
||||||
create(item, x, y, to, () -> {});
|
create(item, x, y, to, () -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(in = In.entities, called = Loc.server, unreliable = true)
|
@Remote(in = In.entities, called = Loc.server, unreliable = true)
|
||||||
public static void transferItemEffect(Item item, float x, float y, Unit to){
|
public static void transferItemEffect(Item item, float x, float y, Unit to){
|
||||||
if(to == null) return;
|
if(to == null) return;
|
||||||
create(item, x, y, to, () -> {});
|
create(item, x, y, to, () -> {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(in = In.entities, called = Loc.server, unreliable = true)
|
@Remote(in = In.entities, called = Loc.server, unreliable = true)
|
||||||
@@ -54,8 +59,9 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{
|
|||||||
@Remote(in = In.entities, called = Loc.server)
|
@Remote(in = In.entities, called = Loc.server)
|
||||||
public static void transferItemTo(Item item, int amount, float x, float y, Tile tile){
|
public static void transferItemTo(Item item, int amount, float x, float y, Tile tile){
|
||||||
if(tile == null) return;
|
if(tile == null) return;
|
||||||
for (int i = 0; i < Mathf.clamp(amount/3, 1, 8); i++) {
|
for(int i = 0; i < Mathf.clamp(amount / 3, 1, 8); i++){
|
||||||
Timers.run(i*3, () -> create(item, x, y, tile, () -> {}));
|
Timers.run(i * 3, () -> create(item, x, y, tile, () -> {
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
tile.entity.items.add(item, amount);
|
tile.entity.items.add(item, amount);
|
||||||
}
|
}
|
||||||
@@ -70,15 +76,13 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{
|
|||||||
tr.add();
|
tr.add();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemTransfer(){}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float lifetime() {
|
public float lifetime(){
|
||||||
return 60;
|
return 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset(){
|
||||||
super.reset();
|
super.reset();
|
||||||
item = null;
|
item = null;
|
||||||
to = null;
|
to = null;
|
||||||
@@ -89,7 +93,7 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removed() {
|
public void removed(){
|
||||||
if(done != null){
|
if(done != null){
|
||||||
threads.run(done);
|
threads.run(done);
|
||||||
}
|
}
|
||||||
@@ -97,7 +101,7 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update(){
|
||||||
if(to == null){
|
if(to == null){
|
||||||
remove();
|
remove();
|
||||||
return;
|
return;
|
||||||
@@ -110,24 +114,24 @@ public class ItemTransfer extends TimedEntity implements DrawTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw() {
|
public void draw(){
|
||||||
float length = fslope()*6f;
|
float length = fslope() * 6f;
|
||||||
float angle = current.set(x, y).sub(from).angle();
|
float angle = current.set(x, y).sub(from).angle();
|
||||||
Draw.color(Palette.accent);
|
Draw.color(Palette.accent);
|
||||||
Lines.stroke(fslope()*2f);
|
Lines.stroke(fslope() * 2f);
|
||||||
|
|
||||||
Lines.circle(x, y, fslope()*2f);
|
Lines.circle(x, y, fslope() * 2f);
|
||||||
Lines.lineAngleCenter(x, y, angle, length);
|
Lines.lineAngleCenter(x, y, angle, length);
|
||||||
Lines.lineAngle(x, y, angle, fout()*6f);
|
Lines.lineAngle(x, y, angle, fout() * 6f);
|
||||||
|
|
||||||
Draw.color(item.color);
|
Draw.color(item.color);
|
||||||
Fill.circle(x, y, fslope()*1.5f);
|
Fill.circle(x, y, fslope() * 1.5f);
|
||||||
|
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityGroup targetGroup() {
|
public EntityGroup targetGroup(){
|
||||||
return effectGroup;
|
return effectGroup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,15 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
|||||||
private Color color = Palette.lancerLaser;
|
private Color color = Palette.lancerLaser;
|
||||||
private SeedRandom random = new SeedRandom();
|
private SeedRandom random = new SeedRandom();
|
||||||
|
|
||||||
/**Create a lighting branch at a location. Use Team.none to damage everyone.*/
|
/**
|
||||||
|
* For pooling use only. Do not call directly!
|
||||||
|
*/
|
||||||
|
public Lightning(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a lighting branch at a location. Use Team.none to damage everyone.
|
||||||
|
*/
|
||||||
public static void create(Team team, Effect effect, Color color, float damage, float x, float y, float targetAngle, int length){
|
public static void create(Team team, Effect effect, Color color, float damage, float x, float y, float targetAngle, int length){
|
||||||
CallEntity.createLighting(lastSeed++, team, effect, color, damage, x, y, targetAngle, length);
|
CallEntity.createLighting(lastSeed++, team, effect, color, damage, x, y, targetAngle, length);
|
||||||
}
|
}
|
||||||
@@ -69,7 +77,7 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
|||||||
|
|
||||||
Units.getNearbyEnemies(team, rect, entities::add);
|
Units.getNearbyEnemies(team, rect, entities::add);
|
||||||
|
|
||||||
for(int i = 0; i < length; i ++){
|
for(int i = 0; i < length; i++){
|
||||||
l.lines.add(new Vector2(x, y));
|
l.lines.add(new Vector2(x, y));
|
||||||
|
|
||||||
float fx = x, fy = y;
|
float fx = x, fy = y;
|
||||||
@@ -82,15 +90,15 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
|||||||
|
|
||||||
Units.getNearbyEnemies(team, rect, entity -> {
|
Units.getNearbyEnemies(team, rect, entity -> {
|
||||||
float dst = entity.distanceTo(x2, y2);
|
float dst = entity.distanceTo(x2, y2);
|
||||||
if(dst < attractRange) {
|
if(dst < attractRange){
|
||||||
angle = Mathf.slerp(angle, Angles.angle(x2, y2, entity.x, entity.y), (attractRange - dst) / attractRange / 4f);
|
angle = Mathf.slerp(angle, Angles.angle(x2, y2, entity.x, entity.y), (attractRange - dst) / attractRange / 4f);
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.getHitbox(hitrect);
|
entity.getHitbox(hitrect);
|
||||||
hitrect.x -= range/2f;
|
hitrect.x -= range / 2f;
|
||||||
hitrect.y -= range/2f;
|
hitrect.y -= range / 2f;
|
||||||
hitrect.width += range/2f;
|
hitrect.width += range / 2f;
|
||||||
hitrect.height += range/2f;
|
hitrect.height += range / 2f;
|
||||||
|
|
||||||
if(hitrect.contains(x2, y2) || hitrect.contains(fx, fy)){
|
if(hitrect.contains(x2, y2) || hitrect.contains(fx, fy)){
|
||||||
float result = damage;
|
float result = damage;
|
||||||
@@ -104,7 +112,7 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
|||||||
});
|
});
|
||||||
|
|
||||||
if(l.random.chance(0.1f)){
|
if(l.random.chance(0.1f)){
|
||||||
createLighting(l.random.nextInt(), team, effect, color, damage, x2, y2, angle + l.random.range(100f), length/3);
|
createLighting(l.random.nextInt(), team, effect, color, damage, x2, y2, angle + l.random.range(100f), length / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
x = x2;
|
x = x2;
|
||||||
@@ -115,47 +123,44 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
|||||||
l.add();
|
l.add();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**For pooling use only. Do not call directly!*/
|
|
||||||
public Lightning(){}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSyncing() {
|
public boolean isSyncing(){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput data) throws IOException {
|
public void write(DataOutput data) throws IOException{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput data, long time) throws IOException {
|
public void read(DataInput data, long time) throws IOException{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float lifetime() {
|
public float lifetime(){
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset(){
|
||||||
color = Palette.lancerLaser;
|
color = Palette.lancerLaser;
|
||||||
lines.clear();
|
lines.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removed() {
|
public void removed(){
|
||||||
Pooling.free(this);
|
Pooling.free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw() {
|
public void draw(){
|
||||||
float lx = x, ly = y;
|
float lx = x, ly = y;
|
||||||
Draw.color(color, Color.WHITE, fin());
|
Draw.color(color, Color.WHITE, fin());
|
||||||
for(int i = 0; i < lines.size; i ++){
|
for(int i = 0; i < lines.size; i++){
|
||||||
Vector2 v = lines.get(i);
|
Vector2 v = lines.get(i);
|
||||||
Lines.stroke(fout() * 3f + 1f-(float)i/lines.size);
|
Lines.stroke(fout() * 3f + 1f - (float) i / lines.size);
|
||||||
Lines.line(lx, ly, v.x, v.y);
|
Lines.line(lx, ly, v.x, v.y);
|
||||||
lx = v.x;
|
lx = v.x;
|
||||||
ly = v.y;
|
ly = v.y;
|
||||||
@@ -164,7 +169,7 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityGroup targetGroup() {
|
public EntityGroup targetGroup(){
|
||||||
return bulletGroup;
|
return bulletGroup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import java.io.IOException;
|
|||||||
import static io.anuke.mindustry.Vars.puddleGroup;
|
import static io.anuke.mindustry.Vars.puddleGroup;
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait, SyncTrait {
|
public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait, SyncTrait{
|
||||||
private static final IntMap<Puddle> map = new IntMap<>();
|
private static final IntMap<Puddle> map = new IntMap<>();
|
||||||
private static final float maxLiquid = 70f;
|
private static final float maxLiquid = 70f;
|
||||||
private static final int maxGeneration = 2;
|
private static final int maxGeneration = 2;
|
||||||
@@ -58,17 +58,29 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
private float accepting;
|
private float accepting;
|
||||||
private byte generation;
|
private byte generation;
|
||||||
|
|
||||||
/**Deposists a puddle between tile and source.*/
|
/**
|
||||||
|
* Deserialization use only!
|
||||||
|
*/
|
||||||
|
public Puddle(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deposists a puddle between tile and source.
|
||||||
|
*/
|
||||||
public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){
|
public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){
|
||||||
deposit(tile, source, liquid, amount, 0);
|
deposit(tile, source, liquid, amount, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Deposists a puddle at a tile.*/
|
/**
|
||||||
|
* Deposists a puddle at a tile.
|
||||||
|
*/
|
||||||
public static void deposit(Tile tile, Liquid liquid, float amount){
|
public static void deposit(Tile tile, Liquid liquid, float amount){
|
||||||
deposit(tile, tile, liquid, amount, 0);
|
deposit(tile, tile, liquid, amount, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns the puddle on the specified tile. May return null.*/
|
/**
|
||||||
|
* Returns the puddle on the specified tile. May return null.
|
||||||
|
*/
|
||||||
public static Puddle getPuddle(Tile tile){
|
public static Puddle getPuddle(Tile tile){
|
||||||
return map.get(tile.packedPosition());
|
return map.get(tile.packedPosition());
|
||||||
}
|
}
|
||||||
@@ -76,11 +88,11 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
private static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){
|
private static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){
|
||||||
if(tile.floor().isLiquid && !canStayOn(liquid, tile.floor().liquidDrop)){
|
if(tile.floor().isLiquid && !canStayOn(liquid, tile.floor().liquidDrop)){
|
||||||
reactPuddle(tile.floor().liquidDrop, liquid, amount, tile,
|
reactPuddle(tile.floor().liquidDrop, liquid, amount, tile,
|
||||||
(tile.worldx() + source.worldx())/2f, (tile.worldy() + source.worldy())/2f);
|
(tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||||
|
|
||||||
if(generation == 0 && Timers.get(tile, "ripple", 50)){
|
if(generation == 0 && Timers.get(tile, "ripple", 50)){
|
||||||
Effects.effect(BlockFx.ripple, tile.floor().liquidDrop.color,
|
Effects.effect(BlockFx.ripple, tile.floor().liquidDrop.color,
|
||||||
(tile.worldx() + source.worldx())/2f, (tile.worldy() + source.worldy())/2f);
|
(tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -93,28 +105,32 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
puddle.tile = tile;
|
puddle.tile = tile;
|
||||||
puddle.liquid = liquid;
|
puddle.liquid = liquid;
|
||||||
puddle.amount = amount;
|
puddle.amount = amount;
|
||||||
puddle.generation = (byte)generation;
|
puddle.generation = (byte) generation;
|
||||||
puddle.set((tile.worldx() + source.worldx())/2f, (tile.worldy() + source.worldy())/2f);
|
puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||||
puddle.add();
|
puddle.add();
|
||||||
map.put(tile.packedPosition(), puddle);
|
map.put(tile.packedPosition(), puddle);
|
||||||
}else if(p.liquid == liquid){
|
}else if(p.liquid == liquid){
|
||||||
p.accepting = Math.max(amount, p.accepting);
|
p.accepting = Math.max(amount, p.accepting);
|
||||||
|
|
||||||
if(generation == 0 && Timers.get(p, "ripple2", 50) && p.amount >= maxLiquid/2f){
|
if(generation == 0 && Timers.get(p, "ripple2", 50) && p.amount >= maxLiquid / 2f){
|
||||||
Effects.effect(BlockFx.ripple, p.liquid.color, (tile.worldx() + source.worldx())/2f, (tile.worldy() + source.worldy())/2f);
|
Effects.effect(BlockFx.ripple, p.liquid.color, (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
p.amount -= reactPuddle(p.liquid, liquid, amount, p.tile, p.x, p.y);
|
p.amount -= reactPuddle(p.liquid, liquid, amount, p.tile, p.x, p.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns whether the first liquid can 'stay' on the second one.
|
/**
|
||||||
* Currently, the only place where this can happen is oil on water.*/
|
* Returns whether the first liquid can 'stay' on the second one.
|
||||||
|
* Currently, the only place where this can happen is oil on water.
|
||||||
|
*/
|
||||||
private static boolean canStayOn(Liquid liquid, Liquid other){
|
private static boolean canStayOn(Liquid liquid, Liquid other){
|
||||||
return liquid == Liquids.oil && other == Liquids.water;
|
return liquid == Liquids.oil && other == Liquids.water;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Reacts two liquids together at a location.*/
|
/**
|
||||||
|
* Reacts two liquids together at a location.
|
||||||
|
*/
|
||||||
private static float reactPuddle(Liquid dest, Liquid liquid, float amount, Tile tile, float x, float y){
|
private static float reactPuddle(Liquid dest, Liquid liquid, float amount, Tile tile, float x, float y){
|
||||||
if((dest.flammability > 0.3f && liquid.temperature > 0.7f) ||
|
if((dest.flammability > 0.3f && liquid.temperature > 0.7f) ||
|
||||||
(liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid
|
(liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid
|
||||||
@@ -126,25 +142,27 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
if(Mathf.chance(0.5f * amount)){
|
if(Mathf.chance(0.5f * amount)){
|
||||||
Effects.effect(EnvironmentFx.steam, x, y);
|
Effects.effect(EnvironmentFx.steam, x, y);
|
||||||
}
|
}
|
||||||
return - 0.1f * amount;
|
return -0.1f * amount;
|
||||||
}else if(liquid.temperature > 0.7f && dest.temperature < 0.55f){ //hot liquid poured onto cold puddle
|
}else if(liquid.temperature > 0.7f && dest.temperature < 0.55f){ //hot liquid poured onto cold puddle
|
||||||
if(Mathf.chance(0.8f * amount)){
|
if(Mathf.chance(0.8f * amount)){
|
||||||
Effects.effect(EnvironmentFx.steam, x, y);
|
Effects.effect(EnvironmentFx.steam, x, y);
|
||||||
}
|
}
|
||||||
return - 0.4f * amount;
|
return -0.4f * amount;
|
||||||
}
|
}
|
||||||
return 0f;
|
return 0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Deserialization use only!*/
|
@Remote(called = Loc.server, in = In.entities)
|
||||||
public Puddle(){}
|
public static void onPuddleRemoved(int puddleid){
|
||||||
|
puddleGroup.removeByID(puddleid);
|
||||||
|
}
|
||||||
|
|
||||||
public float getFlammability(){
|
public float getFlammability(){
|
||||||
return liquid.flammability * amount;
|
return liquid.flammability * amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update(){
|
||||||
|
|
||||||
//no updating happens clientside
|
//no updating happens clientside
|
||||||
if(Net.client()){
|
if(Net.client()){
|
||||||
@@ -158,11 +176,11 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
amount += accepting;
|
amount += accepting;
|
||||||
accepting = 0f;
|
accepting = 0f;
|
||||||
|
|
||||||
if (amount >= maxLiquid / 1.5f && generation < maxGeneration) {
|
if(amount >= maxLiquid / 1.5f && generation < maxGeneration){
|
||||||
float deposited = Math.min((amount - maxLiquid / 1.5f) / 4f, 0.3f) * Timers.delta();
|
float deposited = Math.min((amount - maxLiquid / 1.5f) / 4f, 0.3f) * Timers.delta();
|
||||||
for (GridPoint2 point : Geometry.d4) {
|
for(GridPoint2 point : Geometry.d4){
|
||||||
Tile other = world.tile(tile.x + point.x, tile.y + point.y);
|
Tile other = world.tile(tile.x + point.x, tile.y + point.y);
|
||||||
if (other.block() == Blocks.air && other.cliffs == 0) {
|
if(other.block() == Blocks.air && other.cliffs == 0){
|
||||||
deposit(other, tile, liquid, deposited, generation + 1);
|
deposit(other, tile, liquid, deposited, generation + 1);
|
||||||
amount -= deposited / 2f; //tweak to speed up/slow down puddle propagation
|
amount -= deposited / 2f; //tweak to speed up/slow down puddle propagation
|
||||||
}
|
}
|
||||||
@@ -171,14 +189,14 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
|
|
||||||
amount = Mathf.clamp(amount, 0, maxLiquid);
|
amount = Mathf.clamp(amount, 0, maxLiquid);
|
||||||
|
|
||||||
if (amount <= 0f) {
|
if(amount <= 0f){
|
||||||
CallEntity.onPuddleRemoved(getID());
|
CallEntity.onPuddleRemoved(getID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//effects-only code
|
//effects-only code
|
||||||
if(amount >= maxLiquid/2f && updateTime <= 0f){
|
if(amount >= maxLiquid / 2f && updateTime <= 0f){
|
||||||
Units.getNearby(rect.setSize(Mathf.clamp(amount/(maxLiquid/1.5f))*10f).setCenter(x, y), unit -> {
|
Units.getNearby(rect.setSize(Mathf.clamp(amount / (maxLiquid / 1.5f)) * 10f).setCenter(x, y), unit -> {
|
||||||
if(unit.isFlying()) return;
|
if(unit.isFlying()) return;
|
||||||
|
|
||||||
unit.getHitbox(rect2);
|
unit.getHitbox(rect2);
|
||||||
@@ -186,7 +204,7 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
|
|
||||||
unit.applyEffect(liquid.effect, 0.5f);
|
unit.applyEffect(liquid.effect, 0.5f);
|
||||||
|
|
||||||
if(unit.getVelocity().len() > 0.1) {
|
if(unit.getVelocity().len() > 0.1){
|
||||||
Effects.effect(BlockFx.ripple, liquid.color, unit.x, unit.y);
|
Effects.effect(BlockFx.ripple, liquid.color, unit.x, unit.y);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -202,30 +220,30 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw() {
|
public void draw(){
|
||||||
seeds = id;
|
seeds = id;
|
||||||
boolean onLiquid = tile.floor().isLiquid;
|
boolean onLiquid = tile.floor().isLiquid;
|
||||||
float f = Mathf.clamp(amount/(maxLiquid/1.5f));
|
float f = Mathf.clamp(amount / (maxLiquid / 1.5f));
|
||||||
float smag = onLiquid ? 0.8f : 0f;
|
float smag = onLiquid ? 0.8f : 0f;
|
||||||
float sscl = 20f;
|
float sscl = 20f;
|
||||||
|
|
||||||
Draw.color(Hue.shift(tmp.set(liquid.color), 2, -0.05f));
|
Draw.color(Hue.shift(tmp.set(liquid.color), 2, -0.05f));
|
||||||
Fill.circle(x + Mathf.sin(Timers.time() + seeds*532, sscl, smag), y + Mathf.sin(Timers.time() + seeds*53, sscl, smag), f * 8f);
|
Fill.circle(x + Mathf.sin(Timers.time() + seeds * 532, sscl, smag), y + Mathf.sin(Timers.time() + seeds * 53, sscl, smag), f * 8f);
|
||||||
Angles.randLenVectors(id, 3, f * 6f, (ex, ey) -> {
|
Angles.randLenVectors(id, 3, f * 6f, (ex, ey) -> {
|
||||||
Fill.circle(x + ex + Mathf.sin(Timers.time() + seeds*532, sscl, smag),
|
Fill.circle(x + ex + Mathf.sin(Timers.time() + seeds * 532, sscl, smag),
|
||||||
y + ey + Mathf.sin(Timers.time() + seeds*53, sscl, smag), f * 5f);
|
y + ey + Mathf.sin(Timers.time() + seeds * 53, sscl, smag), f * 5f);
|
||||||
seeds ++;
|
seeds++;
|
||||||
});
|
});
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float drawSize() {
|
public float drawSize(){
|
||||||
return 20;
|
return 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeSave(DataOutput stream) throws IOException {
|
public void writeSave(DataOutput stream) throws IOException{
|
||||||
stream.writeInt(tile.packedPosition());
|
stream.writeInt(tile.packedPosition());
|
||||||
stream.writeFloat(x);
|
stream.writeFloat(x);
|
||||||
stream.writeFloat(y);
|
stream.writeFloat(y);
|
||||||
@@ -235,7 +253,7 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readSave(DataInput stream) throws IOException {
|
public void readSave(DataInput stream) throws IOException{
|
||||||
this.loadedPosition = stream.readInt();
|
this.loadedPosition = stream.readInt();
|
||||||
this.x = stream.readFloat();
|
this.x = stream.readFloat();
|
||||||
this.y = stream.readFloat();
|
this.y = stream.readFloat();
|
||||||
@@ -246,7 +264,7 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset(){
|
||||||
loadedPosition = -1;
|
loadedPosition = -1;
|
||||||
tile = null;
|
tile = null;
|
||||||
liquid = null;
|
liquid = null;
|
||||||
@@ -256,7 +274,7 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void added() {
|
public void added(){
|
||||||
if(loadedPosition != -1){
|
if(loadedPosition != -1){
|
||||||
map.put(loadedPosition, this);
|
map.put(loadedPosition, this);
|
||||||
tile = world.tile(loadedPosition);
|
tile = world.tile(loadedPosition);
|
||||||
@@ -264,38 +282,33 @@ public class Puddle extends BaseEntity implements SaveTrait, Poolable, DrawTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removed() {
|
public void removed(){
|
||||||
map.remove(tile.packedPosition());
|
map.remove(tile.packedPosition());
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput data) throws IOException {
|
public void write(DataOutput data) throws IOException{
|
||||||
data.writeFloat(x);
|
data.writeFloat(x);
|
||||||
data.writeFloat(y);
|
data.writeFloat(y);
|
||||||
data.writeByte(liquid.id);
|
data.writeByte(liquid.id);
|
||||||
data.writeShort((short)(amount * 4));
|
data.writeShort((short) (amount * 4));
|
||||||
data.writeInt(tile.packedPosition());
|
data.writeInt(tile.packedPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput data, long time) throws IOException {
|
public void read(DataInput data, long time) throws IOException{
|
||||||
x = data.readFloat();
|
x = data.readFloat();
|
||||||
y = data.readFloat();
|
y = data.readFloat();
|
||||||
liquid = Liquid.getByID(data.readByte());
|
liquid = Liquid.getByID(data.readByte());
|
||||||
targetAmount = data.readShort()/4f;
|
targetAmount = data.readShort() / 4f;
|
||||||
tile = world.tile(data.readInt());
|
tile = world.tile(data.readInt());
|
||||||
|
|
||||||
map.put(tile.packedPosition(), this);
|
map.put(tile.packedPosition(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityGroup targetGroup() {
|
public EntityGroup targetGroup(){
|
||||||
return puddleGroup;
|
return puddleGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.entities)
|
|
||||||
public static void onPuddleRemoved(int puddleid){
|
|
||||||
puddleGroup.removeByID(puddleid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ package io.anuke.mindustry.entities.effect;
|
|||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class RubbleDecal extends Decal {
|
public class RubbleDecal extends Decal{
|
||||||
private int size;
|
private int size;
|
||||||
|
|
||||||
/**Creates a rubble effect at a position. Provide a block size to use.*/
|
/**
|
||||||
|
* Creates a rubble effect at a position. Provide a block size to use.
|
||||||
|
*/
|
||||||
public static void create(float x, float y, int size){
|
public static void create(float x, float y, int size){
|
||||||
RubbleDecal decal = new RubbleDecal();
|
RubbleDecal decal = new RubbleDecal();
|
||||||
decal.size = size;
|
decal.size = size;
|
||||||
|
|||||||
@@ -8,21 +8,21 @@ import io.anuke.ucore.util.Mathf;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class ScorchDecal extends Decal {
|
public class ScorchDecal extends Decal{
|
||||||
private static final int scorches = 5;
|
private static final int scorches = 5;
|
||||||
private static final TextureRegion[] regions = new TextureRegion[scorches];
|
private static final TextureRegion[] regions = new TextureRegion[scorches];
|
||||||
|
|
||||||
public static void create(float x, float y){
|
public static void create(float x, float y){
|
||||||
if(regions[0] == null){
|
if(regions[0] == null){
|
||||||
for (int i = 0; i < regions.length; i++) {
|
for(int i = 0; i < regions.length; i++){
|
||||||
regions[i] = Draw.region("scorch" + (i+1));
|
regions[i] = Draw.region("scorch" + (i + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tile tile = world.tileWorld(x, y);
|
Tile tile = world.tileWorld(x, y);
|
||||||
|
|
||||||
if(tile == null || tile.floor().liquidDrop != null) return;
|
if(tile == null || tile.floor().liquidDrop != null) return;
|
||||||
|
|
||||||
ScorchDecal decal = new ScorchDecal();
|
ScorchDecal decal = new ScorchDecal();
|
||||||
decal.set(x, y);
|
decal.set(x, y);
|
||||||
decal.add();
|
decal.add();
|
||||||
@@ -31,10 +31,10 @@ public class ScorchDecal extends Decal {
|
|||||||
@Override
|
@Override
|
||||||
public void drawDecal(){
|
public void drawDecal(){
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for(int i = 0; i < 5; i++){
|
||||||
TextureRegion region = regions[Mathf.randomSeed(id - i, 0, scorches-1)];
|
TextureRegion region = regions[Mathf.randomSeed(id - i, 0, scorches - 1)];
|
||||||
float rotation = Mathf.randomSeed(id + i, 0, 360);
|
float rotation = Mathf.randomSeed(id + i, 0, 360);
|
||||||
float space = 1.5f + Mathf.randomSeed(id + i + 1, 0, 20)/10f;
|
float space = 1.5f + Mathf.randomSeed(id + i + 1, 0, 20) / 10f;
|
||||||
Draw.grect(region, x + Angles.trnsx(rotation, space), y + Angles.trnsy(rotation, space), rotation - 90);
|
Draw.grect(region, x + Angles.trnsx(rotation, space), y + Angles.trnsy(rotation, space), rotation - 90);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user