im working on plugin, but when player do a command in game, "sender" do four same messages...
#EventHandler
public void oncmd(PlayerCommandPreprocessEvent e) {
List<String> block = Arrays.asList(":");
block.forEach(all -> {
if(e.getMessage().toLowerCase().contains(all.toLowerCase())) {
e.getPlayer().sendMessage("§8[§aSystem§8] §cYou can't use this command!");
e.setCancelled(true);
}
});
}
You could create a char array with the characters which aren't allowed. After that you can use a simple for loop to iterate through all elements. Inside of this loop, you can now check if the command contains this character.
Use a for-each loop instead of calling the forEach function. This will let you add a break statement, which will end the loop after it finds the first bad character:
#EventHandler
public void oncmd(PlayerCommandPreprocessEvent e) {
List<String> block = Arrays.asList(":");
for(String all : block) {
if(e.getMessage().toLowerCase().contains(all.toLowerCase())) {
e.getPlayer().sendMessage("§8[§aSystem§8] §cYou can't use this command!");
e.setCancelled(true);
break;
}
}
}
Alternatively, if you want to stay with a more functional approach, you can use anyMatch:
#EventHandler
public void oncmd(PlayerCommandPreprocessEvent e) {
List<String> block = Arrays.asList(":");
if(block.stream().anyMatch(all -> e.getMessage().toLowerCase().contains(all.toLowerCase()))) {
e.getPlayer().sendMessage("§8[§aSystem§8] §cYou can't use this command!");
e.setCancelled(true);
}
}
Related
I am currently creating a calculator with certain functions and new to apps developer.
Currently, the dot function is working fine, just that it has one issue.
The dot repeat itself after another dot before eventually stopped.
This resulted in either "1.2." or 1..2".
Whenever, there are two dots appeared, it created the NaN value which is not desired.
I do realised that the issue is originated from the "try" section, however I have not found a way to solve this.
Any feedback is appreciated.
b_dot.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
show.setText(show.getText().toString() + "");
try{
val2 = Double.parseDouble(show.getText().toString());
show.setText(show.getText().toString() + ".");
}
catch (Exception e)
{
if (toastMessage!= null) {
toastMessage.cancel();
}
toastMessage= Toast.makeText(getContext(),"Invalid Value",Toast.LENGTH_LONG);
toastMessage.show();
}
}
});
I'm trying to use IPreProcessBuildWithReport and IPostProcessBuildWithReport to add a game object to the scene right before build, and promptly delete it from the scene when the build finishes. The goal is to reduce all that I can from the hierarchy during the development but include these objects during the build.
My issue occurs when the build fails (due to some error), it adds the game object before the build started but never reached the code to delete the game object when it fails.
Is there a similar method to detect when the build fails without building my own build player pipeline? I really don't want to stray away from unity's default build pipeline if I don't need to.
If there was no easy way, I was trying to think if maybe there was a way to track the buildfailed exception or error and run a method if it occurs.
Thanks, let me know what you guys think.
EDIT: As requested, here is an example:
class CustomBuildPipeline : MonoBehaviour, IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
public int callbackOrder => 0;
// CALLED BEFORE THE BUILD
public void OnPreprocessBuild(BuildReport report)
{
// Create and add gameobjects to scene
}
// CALLED AFTER THE BUILD
public void OnPostprocessBuild(BuildReport report)
{
// Remove gameobjects from scene once built
}
}
}
PreProcess Interface
PostProcess Interface
I was wondering if there was a possible solution by somehow detecting when this buildexception was thrown and running code following.
EDIT 2: I found this post that has possible solutions, however, it may not be as elegant as I'd prefer. I'll try some things out and report back.
I used the post in the 'EDIT 2' to come up with a decent solution. I don't know if it will work 100% of the time and I would love for someone to correct me if I have chosen a poor solution. This should allow me to run code before the build starts, and if the build fails or succeeds without changing the unity build pipeline.
class CustomBuildPipeline : MonoBehaviour, IPreprocessBuildWithReport, IPostprocessBuildWithReport
{
public int callbackOrder => 0;
// CALLED BEFORE THE BUILD
public void OnPreprocessBuild(BuildReport report)
{
// Start listening for errors when build starts
Application.logMessageReceived += OnBuildError;
}
// CALLED DURING BUILD TO CHECK FOR ERRORS
private void OnBuildError(string condition, string stacktrace, LogType type)
{
if (type == LogType.Error)
{
// FAILED TO BUILD, STOP LISTENING FOR ERRORS
Application.logMessageReceived -= OnBuildError;
}
}
// CALLED AFTER THE BUILD
public void OnPostprocessBuild(BuildReport report)
{
// IF BUILD FINISHED AND SUCCEEDED, STOP LOOKING FOR ERRORS
Application.logMessageReceived -= OnBuildError;
}
}
}
This approach is using a custom build handler, but still uses the default build pipeline.
Use BuildHandler.OnBuildStarted instead of (or in addition to) IPreprocessBuildWithReport for pre-processing. For post-processing use BuildHandler.OnBuildCleanup, which is called when a build completes or fails. Can also be used in conjunction with IPostprocessBuildWithReport.
[InitializeOnLoad]
public class BuildHandler : MonoBehaviour
{
public static event Action OnBuildStarted;
public static event Action OnBuildCleanup;
static BuildHandler()
{
BuildPlayerWindow.RegisterBuildPlayerHandler(Build);
}
private static void Build(BuildPlayerOptions buildOptions)
{
try
{
BuildStarted();
//now start Unity's default building procedure
BuildPlayerWindow.DefaultBuildMethods.BuildPlayer(buildOptions);
}
catch (BuildPlayerWindow.BuildMethodException) { } //logged internally
catch (Exception ex)
{
Exception log = ex.InnerException == null ? ex : ex.InnerException;
Debug.LogException(log);
Debug.LogErrorFormat("{0} in BuildHandler: '{1}'", log.GetType().Name, ex.Message);
}
finally
{
BuildCleanup();
}
}
private static void BuildStarted()
{
try
{
if (OnBuildStarted != null)
OnBuildStarted.Invoke();
}
catch (Exception ex)
{
throw new Exception("OnBuildStarted failed", ex);
}
}
private static void BuildCleanup()
{
if (OnBuildCleanup != null)
{
foreach (Action cleanupBuild in OnBuildCleanup.GetInvocationList())
{
try
{
cleanupBuild.Invoke();
}
catch (Exception ex)
{
Object context = cleanupBuild.Target as Object;
Debug.LogException(ex, context);
Debug.LogWarning("Caught exception while BuildHandler.OnBuildCleanup... Continuing");
}
}
}
}
}
I am bootstrapping the IEventBroker in a compat-layer Eclipse RCP app.
I have two views: Triggerer and Receiver.
Triggerer (excerpts):
private IEventBroker eventBroker = PlatformUI.getWorkbench().getService(IEventBroker.class);
btn.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
IStructuredSelection selection = viewer.getStructuredSelection();
List selectionList = selection.toList();
for (Object s : selectionList) {
if (s instanceof MyObject) {
matches.add(s);
}
}
eventBroker.send(MyEventConstants.TOPIC_OBJECT_CHANGED, matches);
}
}
Receiver (excerpts):
#Override
public void handleEvent(Event event) {
Object data = event.getProperty(EVENT_DATA);
switch (event.getTopic()) {
case MyEventConstants.TOPIC_OBJECT_CHANGED:
try {
if (data instanceof ArrayList) {
List<MyObject> matches = null;
try {
matches = (List<MyObject>) data;
}
catch (ClassCastException e) {
}
Subthing sub = buildSubthing(matches);
getContentViewer().getContents()
.setAll(Collections.singletonList(sub));
}
}
break;
}
}
buildSubthing does stuff with the respective received data, and sets it to the contents of a GEF4 editor.
In some cases this works just fine, in some it doesn't.
handleEvent() is triggered more than once, although the event hashCode is always the same, and I don't understand why. The topic is the same and the data is also the same. However, buildSubthing just stalls for no apprent reason with some data while it doesn't for other. The data is structurally the same in both cases.
How can I control how often handleEvent is called, as I think the number of times it's called is the reason while the Subthing is sometimes not correctly constructed?
in my vsto addin i have some simple code on a timer
private void MainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!dialogopen & Application.Documents.Count > 0)
{
var doc = Application.ActiveDocument;
Word.InlineShapes shps;
Word.Paragraphs pars;
try
{
pars = doc.Paragraphs;
}
catch (Exception)
{
return;
}
var pars2 = pars.Cast<Word.Paragraph>().ToList();
foreach (var obj in pars2)
{
if (obj.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText )//PROBLEM HERE
{
};
}
}
}
as soon as it reaches the line that checks the outlinelevel, even if i dont do a thing, the selection in the activedocument gets lost
of course the user cant use a plugin which keeps on canceling his selection...
googling didnt give me a thing
thanks
EDIT1
I tried making a static function for checking the styles, but it did not help. Here's the code
static public class Helpers
{
static public Word.Paragraph checkPars(List<Word.Paragraph> pars)
{
return pars.FirstOrDefault();//(x) => x.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText);
}
}
As you can see, I had to remove the actual check, since it was causing the cursor to blink and lose selection
please advise
We use the Application.ScreenUpdating = true; and this keep the selection for all properties in Paragraph except for the Range property.
Then, we tried to access the range via Reflection and this was the solution.
Range rng = (Range)typeof(Paragraph).GetProperty("Range").GetValue(comObj);
We tried to eliminate querying ActiveDocument thinking that that might have had side-effects that were causing the problem but that was not the case.
Then, we confirmed that the selection was not "lost" and screen-updating is the only problem, so we tried restoring the UI with Application.ScreenRefresh and while it did work, it causes the screen to flicker every time the timer fires and this is not good enough.
Finally, knowing that it's only a UI problem, I tried simply switching off Application.ScreenUpdating...
in ThisAddin
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Timer timer = new Timer(2000);
timer.Elapsed += (s, t) =>
{
var scrnUpdating = Application.ScreenUpdating;
Application.ScreenUpdating = false;
MainTimer.onElapsed(Application, t);
if (scrnUpdating)
Application.ScreenUpdating = true;
};
timer.Start();
}
In another class library (note that it's static, I still think this is the best way)...
public static class MainTimer
{
public static void onElapsed (Word.Application state, System.Timers.ElapsedEventArgs e)
{
if (state.Documents.Count > 0)
{
var doc = state.ActiveDocument;
Word.InlineShapes shps;
Word.Paragraphs pars;
try
{
pars = doc.Paragraphs;
}
catch (Exception)
{
return;
}
var pars2 = pars.Cast<Word.Paragraph>()
.Where(p => p.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText)
.Select(p => p) // do stuff with the selected parragraphs...
.ToList();
}
}
}
And this works for me.
The selection remains and is displayed in the UI without flicker.
I also eliminated some premature enumeration from your code: you don't meed the .ToList() before the foreach.
Here is a sample code to retrieve data from a database using the yield keyword that I found in a few place while googling around :
public IEnumerable<object> ExecuteSelect(string commandText)
{
using (IDbConnection connection = CreateConnection())
{
using (IDbCommand cmd = CreateCommand(commandText, connection))
{
connection.Open();
using (IDbDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
yield return reader["SomeField"];
}
}
connection.Close();
}
}
}
Am I correct in thinking that in this sample code, the connection would not be closed if we do not iterate over the whole datareader ?
Here is an example that would not close the connection, if I understand yield correctly..
foreach(object obj in ExecuteSelect(commandText))
{
break;
}
For a db connection that might not be catastrophic, I suppose the GC would clean it up eventually, but what if instead of a connection it was a more critical resource?
The Iterator that the compiler synthesises implements IDisposable, which foreach calls when the foreach loop is exited.
The Iterator's Dispose() method will clean up the using statements on early exit.
As long as you use the iterator in a foreach loop, using() block, or call the Dispose() method in some other way, the cleanup of the Iterator will happen.
Connection will be closed automatically since you're using it inside "using" block.
From the simple test I have tried, aku is right, dispose is called as soon as the foreach block exit.
#David : However call stack is kept between call, so the connection would not be closed because on the next call we would return to the next instruction after the yield, which is the while block.
My understanding is that when the iterator is disposed, the connection would also be disposed with it. I also think that the Connection.Close would not be needed because it would be taken care of when the object is disposed because of the using clause.
Here is a simple program I tried to test the behavior...
class Program
{
static void Main(string[] args)
{
foreach (int v in getValues())
{
Console.WriteLine(v);
}
Console.ReadKey();
foreach (int v in getValues())
{
Console.WriteLine(v);
break;
}
Console.ReadKey();
}
public static IEnumerable<int> getValues()
{
using (TestDisposable t = new TestDisposable())
{
for(int i = 0; i<10; i++)
yield return t.GetValue();
}
}
}
public class TestDisposable : IDisposable
{
private int value;
public void Dispose()
{
Console.WriteLine("Disposed");
}
public int GetValue()
{
value += 1;
return value;
}
}
Judging from this technical explanation, your code will not work as expected, but abort on the second item, because the connection was already closed when returning the first item.
#Joel Gauvreau : Yes, I should have read on. Part 3 of this series explains that the compiler adds special handling for finally blocks to trigger only at the real end.